Create AWS FinSpace Kx Environments

The aws:finspace/kxEnvironment:KxEnvironment resource, part of the Pulumi AWS provider, provisions a FinSpace Kx environment: an isolated workspace for quantitative analytics with KMS encryption and optional network connectivity. This guide focuses on three capabilities: KMS encryption configuration, Transit Gateway connectivity, and network ACL rules for traffic filtering.

Kx environments require KMS keys for encryption and may reference Transit Gateways and custom DNS servers for network connectivity. The examples are intentionally small. Combine them with your own KMS keys, network infrastructure, and cluster configurations.

Create an environment with KMS encryption

Every FinSpace Kx environment requires KMS encryption for data at rest, providing an isolated workspace for analytics workloads.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.kms.Key("example", {
    description: "Sample KMS Key",
    deletionWindowInDays: 7,
});
const exampleKxEnvironment = new aws.finspace.KxEnvironment("example", {
    name: "my-tf-kx-environment",
    kmsKeyId: example.arn,
});
import pulumi
import pulumi_aws as aws

example = aws.kms.Key("example",
    description="Sample KMS Key",
    deletion_window_in_days=7)
example_kx_environment = aws.finspace.KxEnvironment("example",
    name="my-tf-kx-environment",
    kms_key_id=example.arn)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/finspace"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:          pulumi.String("Sample KMS Key"),
			DeletionWindowInDays: pulumi.Int(7),
		})
		if err != nil {
			return err
		}
		_, err = finspace.NewKxEnvironment(ctx, "example", &finspace.KxEnvironmentArgs{
			Name:     pulumi.String("my-tf-kx-environment"),
			KmsKeyId: example.Arn,
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Kms.Key("example", new()
    {
        Description = "Sample KMS Key",
        DeletionWindowInDays = 7,
    });

    var exampleKxEnvironment = new Aws.FinSpace.KxEnvironment("example", new()
    {
        Name = "my-tf-kx-environment",
        KmsKeyId = example.Arn,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.finspace.KxEnvironment;
import com.pulumi.aws.finspace.KxEnvironmentArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Key("example", KeyArgs.builder()
            .description("Sample KMS Key")
            .deletionWindowInDays(7)
            .build());

        var exampleKxEnvironment = new KxEnvironment("exampleKxEnvironment", KxEnvironmentArgs.builder()
            .name("my-tf-kx-environment")
            .kmsKeyId(example.arn())
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: Sample KMS Key
      deletionWindowInDays: 7
  exampleKxEnvironment:
    type: aws:finspace:KxEnvironment
    name: example
    properties:
      name: my-tf-kx-environment
      kmsKeyId: ${example.arn}

The name property sets a unique identifier for the environment. The kmsKeyId property references a KMS key ARN that encrypts all data stored in the environment. Without additional configuration, the environment remains isolated from external networks.

Connect to internal networks via Transit Gateway

Analytics workloads often need to access on-premises data sources or private VPC resources through Transit Gateway connectivity.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.kms.Key("example", {
    description: "Sample KMS Key",
    deletionWindowInDays: 7,
});
const exampleTransitGateway = new aws.ec2transitgateway.TransitGateway("example", {description: "example"});
const exampleEnv = new aws.finspace.KxEnvironment("example_env", {
    name: "my-tf-kx-environment",
    description: "Environment description",
    kmsKeyId: example.arn,
    transitGatewayConfiguration: {
        transitGatewayId: exampleTransitGateway.id,
        routableCidrSpace: "100.64.0.0/26",
    },
    customDnsConfigurations: [{
        customDnsServerName: "example.finspace.amazonaws.com",
        customDnsServerIp: "10.0.0.76",
    }],
});
import pulumi
import pulumi_aws as aws

example = aws.kms.Key("example",
    description="Sample KMS Key",
    deletion_window_in_days=7)
example_transit_gateway = aws.ec2transitgateway.TransitGateway("example", description="example")
example_env = aws.finspace.KxEnvironment("example_env",
    name="my-tf-kx-environment",
    description="Environment description",
    kms_key_id=example.arn,
    transit_gateway_configuration={
        "transit_gateway_id": example_transit_gateway.id,
        "routable_cidr_space": "100.64.0.0/26",
    },
    custom_dns_configurations=[{
        "custom_dns_server_name": "example.finspace.amazonaws.com",
        "custom_dns_server_ip": "10.0.0.76",
    }])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2transitgateway"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/finspace"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:          pulumi.String("Sample KMS Key"),
			DeletionWindowInDays: pulumi.Int(7),
		})
		if err != nil {
			return err
		}
		exampleTransitGateway, err := ec2transitgateway.NewTransitGateway(ctx, "example", &ec2transitgateway.TransitGatewayArgs{
			Description: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		_, err = finspace.NewKxEnvironment(ctx, "example_env", &finspace.KxEnvironmentArgs{
			Name:        pulumi.String("my-tf-kx-environment"),
			Description: pulumi.String("Environment description"),
			KmsKeyId:    example.Arn,
			TransitGatewayConfiguration: &finspace.KxEnvironmentTransitGatewayConfigurationArgs{
				TransitGatewayId:  exampleTransitGateway.ID(),
				RoutableCidrSpace: pulumi.String("100.64.0.0/26"),
			},
			CustomDnsConfigurations: finspace.KxEnvironmentCustomDnsConfigurationArray{
				&finspace.KxEnvironmentCustomDnsConfigurationArgs{
					CustomDnsServerName: pulumi.String("example.finspace.amazonaws.com"),
					CustomDnsServerIp:   pulumi.String("10.0.0.76"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Kms.Key("example", new()
    {
        Description = "Sample KMS Key",
        DeletionWindowInDays = 7,
    });

    var exampleTransitGateway = new Aws.Ec2TransitGateway.TransitGateway("example", new()
    {
        Description = "example",
    });

    var exampleEnv = new Aws.FinSpace.KxEnvironment("example_env", new()
    {
        Name = "my-tf-kx-environment",
        Description = "Environment description",
        KmsKeyId = example.Arn,
        TransitGatewayConfiguration = new Aws.FinSpace.Inputs.KxEnvironmentTransitGatewayConfigurationArgs
        {
            TransitGatewayId = exampleTransitGateway.Id,
            RoutableCidrSpace = "100.64.0.0/26",
        },
        CustomDnsConfigurations = new[]
        {
            new Aws.FinSpace.Inputs.KxEnvironmentCustomDnsConfigurationArgs
            {
                CustomDnsServerName = "example.finspace.amazonaws.com",
                CustomDnsServerIp = "10.0.0.76",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.ec2transitgateway.TransitGateway;
import com.pulumi.aws.ec2transitgateway.TransitGatewayArgs;
import com.pulumi.aws.finspace.KxEnvironment;
import com.pulumi.aws.finspace.KxEnvironmentArgs;
import com.pulumi.aws.finspace.inputs.KxEnvironmentTransitGatewayConfigurationArgs;
import com.pulumi.aws.finspace.inputs.KxEnvironmentCustomDnsConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Key("example", KeyArgs.builder()
            .description("Sample KMS Key")
            .deletionWindowInDays(7)
            .build());

        var exampleTransitGateway = new TransitGateway("exampleTransitGateway", TransitGatewayArgs.builder()
            .description("example")
            .build());

        var exampleEnv = new KxEnvironment("exampleEnv", KxEnvironmentArgs.builder()
            .name("my-tf-kx-environment")
            .description("Environment description")
            .kmsKeyId(example.arn())
            .transitGatewayConfiguration(KxEnvironmentTransitGatewayConfigurationArgs.builder()
                .transitGatewayId(exampleTransitGateway.id())
                .routableCidrSpace("100.64.0.0/26")
                .build())
            .customDnsConfigurations(KxEnvironmentCustomDnsConfigurationArgs.builder()
                .customDnsServerName("example.finspace.amazonaws.com")
                .customDnsServerIp("10.0.0.76")
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: Sample KMS Key
      deletionWindowInDays: 7
  exampleTransitGateway:
    type: aws:ec2transitgateway:TransitGateway
    name: example
    properties:
      description: example
  exampleEnv:
    type: aws:finspace:KxEnvironment
    name: example_env
    properties:
      name: my-tf-kx-environment
      description: Environment description
      kmsKeyId: ${example.arn}
      transitGatewayConfiguration:
        transitGatewayId: ${exampleTransitGateway.id}
        routableCidrSpace: 100.64.0.0/26
      customDnsConfigurations:
        - customDnsServerName: example.finspace.amazonaws.com
          customDnsServerIp: 10.0.0.76

The transitGatewayConfiguration block enables network connectivity between the Kx environment and your internal infrastructure. The transitGatewayId references an existing Transit Gateway, while routableCidrSpace defines the IP range allocated for environment resources. The customDnsConfigurations block sets up Route 53 outbound resolvers, allowing the environment to resolve internal hostnames using your DNS servers.

Control Transit Gateway traffic with network ACLs

When connecting to internal networks, network ACL rules provide fine-grained control over which traffic flows through the Transit Gateway attachment.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.kms.Key("example", {
    description: "Sample KMS Key",
    deletionWindowInDays: 7,
});
const exampleTransitGateway = new aws.ec2transitgateway.TransitGateway("example", {description: "example"});
const exampleEnv = new aws.finspace.KxEnvironment("example_env", {
    name: "my-tf-kx-environment",
    description: "Environment description",
    kmsKeyId: example.arn,
    transitGatewayConfiguration: {
        transitGatewayId: exampleTransitGateway.id,
        routableCidrSpace: "100.64.0.0/26",
        attachmentNetworkAclConfigurations: [{
            ruleNumber: 1,
            protocol: "6",
            ruleAction: "allow",
            cidrBlock: "0.0.0.0/0",
            portRange: {
                from: 53,
                to: 53,
            },
            icmpTypeCode: {
                type: -1,
                code: -1,
            },
        }],
    },
    customDnsConfigurations: [{
        customDnsServerName: "example.finspace.amazonaws.com",
        customDnsServerIp: "10.0.0.76",
    }],
});
import pulumi
import pulumi_aws as aws

example = aws.kms.Key("example",
    description="Sample KMS Key",
    deletion_window_in_days=7)
example_transit_gateway = aws.ec2transitgateway.TransitGateway("example", description="example")
example_env = aws.finspace.KxEnvironment("example_env",
    name="my-tf-kx-environment",
    description="Environment description",
    kms_key_id=example.arn,
    transit_gateway_configuration={
        "transit_gateway_id": example_transit_gateway.id,
        "routable_cidr_space": "100.64.0.0/26",
        "attachment_network_acl_configurations": [{
            "rule_number": 1,
            "protocol": "6",
            "rule_action": "allow",
            "cidr_block": "0.0.0.0/0",
            "port_range": {
                "from_": 53,
                "to": 53,
            },
            "icmp_type_code": {
                "type": -1,
                "code": -1,
            },
        }],
    },
    custom_dns_configurations=[{
        "custom_dns_server_name": "example.finspace.amazonaws.com",
        "custom_dns_server_ip": "10.0.0.76",
    }])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/ec2transitgateway"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/finspace"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/kms"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:          pulumi.String("Sample KMS Key"),
			DeletionWindowInDays: pulumi.Int(7),
		})
		if err != nil {
			return err
		}
		exampleTransitGateway, err := ec2transitgateway.NewTransitGateway(ctx, "example", &ec2transitgateway.TransitGatewayArgs{
			Description: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		_, err = finspace.NewKxEnvironment(ctx, "example_env", &finspace.KxEnvironmentArgs{
			Name:        pulumi.String("my-tf-kx-environment"),
			Description: pulumi.String("Environment description"),
			KmsKeyId:    example.Arn,
			TransitGatewayConfiguration: &finspace.KxEnvironmentTransitGatewayConfigurationArgs{
				TransitGatewayId:  exampleTransitGateway.ID(),
				RoutableCidrSpace: pulumi.String("100.64.0.0/26"),
				AttachmentNetworkAclConfigurations: finspace.KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationArray{
					&finspace.KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationArgs{
						RuleNumber: pulumi.Int(1),
						Protocol:   pulumi.String("6"),
						RuleAction: pulumi.String("allow"),
						CidrBlock:  pulumi.String("0.0.0.0/0"),
						PortRange: &finspace.KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationPortRangeArgs{
							From: pulumi.Int(53),
							To:   pulumi.Int(53),
						},
						IcmpTypeCode: &finspace.KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationIcmpTypeCodeArgs{
							Type: pulumi.Int(-1),
							Code: pulumi.Int(-1),
						},
					},
				},
			},
			CustomDnsConfigurations: finspace.KxEnvironmentCustomDnsConfigurationArray{
				&finspace.KxEnvironmentCustomDnsConfigurationArgs{
					CustomDnsServerName: pulumi.String("example.finspace.amazonaws.com"),
					CustomDnsServerIp:   pulumi.String("10.0.0.76"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Kms.Key("example", new()
    {
        Description = "Sample KMS Key",
        DeletionWindowInDays = 7,
    });

    var exampleTransitGateway = new Aws.Ec2TransitGateway.TransitGateway("example", new()
    {
        Description = "example",
    });

    var exampleEnv = new Aws.FinSpace.KxEnvironment("example_env", new()
    {
        Name = "my-tf-kx-environment",
        Description = "Environment description",
        KmsKeyId = example.Arn,
        TransitGatewayConfiguration = new Aws.FinSpace.Inputs.KxEnvironmentTransitGatewayConfigurationArgs
        {
            TransitGatewayId = exampleTransitGateway.Id,
            RoutableCidrSpace = "100.64.0.0/26",
            AttachmentNetworkAclConfigurations = new[]
            {
                new Aws.FinSpace.Inputs.KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationArgs
                {
                    RuleNumber = 1,
                    Protocol = "6",
                    RuleAction = "allow",
                    CidrBlock = "0.0.0.0/0",
                    PortRange = new Aws.FinSpace.Inputs.KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationPortRangeArgs
                    {
                        From = 53,
                        To = 53,
                    },
                    IcmpTypeCode = new Aws.FinSpace.Inputs.KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationIcmpTypeCodeArgs
                    {
                        Type = -1,
                        Code = -1,
                    },
                },
            },
        },
        CustomDnsConfigurations = new[]
        {
            new Aws.FinSpace.Inputs.KxEnvironmentCustomDnsConfigurationArgs
            {
                CustomDnsServerName = "example.finspace.amazonaws.com",
                CustomDnsServerIp = "10.0.0.76",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.ec2transitgateway.TransitGateway;
import com.pulumi.aws.ec2transitgateway.TransitGatewayArgs;
import com.pulumi.aws.finspace.KxEnvironment;
import com.pulumi.aws.finspace.KxEnvironmentArgs;
import com.pulumi.aws.finspace.inputs.KxEnvironmentTransitGatewayConfigurationArgs;
import com.pulumi.aws.finspace.inputs.KxEnvironmentCustomDnsConfigurationArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new Key("example", KeyArgs.builder()
            .description("Sample KMS Key")
            .deletionWindowInDays(7)
            .build());

        var exampleTransitGateway = new TransitGateway("exampleTransitGateway", TransitGatewayArgs.builder()
            .description("example")
            .build());

        var exampleEnv = new KxEnvironment("exampleEnv", KxEnvironmentArgs.builder()
            .name("my-tf-kx-environment")
            .description("Environment description")
            .kmsKeyId(example.arn())
            .transitGatewayConfiguration(KxEnvironmentTransitGatewayConfigurationArgs.builder()
                .transitGatewayId(exampleTransitGateway.id())
                .routableCidrSpace("100.64.0.0/26")
                .attachmentNetworkAclConfigurations(KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationArgs.builder()
                    .ruleNumber(1)
                    .protocol("6")
                    .ruleAction("allow")
                    .cidrBlock("0.0.0.0/0")
                    .portRange(KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationPortRangeArgs.builder()
                        .from(53)
                        .to(53)
                        .build())
                    .icmpTypeCode(KxEnvironmentTransitGatewayConfigurationAttachmentNetworkAclConfigurationIcmpTypeCodeArgs.builder()
                        .type(-1)
                        .code(-1)
                        .build())
                    .build())
                .build())
            .customDnsConfigurations(KxEnvironmentCustomDnsConfigurationArgs.builder()
                .customDnsServerName("example.finspace.amazonaws.com")
                .customDnsServerIp("10.0.0.76")
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:kms:Key
    properties:
      description: Sample KMS Key
      deletionWindowInDays: 7
  exampleTransitGateway:
    type: aws:ec2transitgateway:TransitGateway
    name: example
    properties:
      description: example
  exampleEnv:
    type: aws:finspace:KxEnvironment
    name: example_env
    properties:
      name: my-tf-kx-environment
      description: Environment description
      kmsKeyId: ${example.arn}
      transitGatewayConfiguration:
        transitGatewayId: ${exampleTransitGateway.id}
        routableCidrSpace: 100.64.0.0/26
        attachmentNetworkAclConfigurations:
          - ruleNumber: 1
            protocol: '6'
            ruleAction: allow
            cidrBlock: 0.0.0.0/0
            portRange:
              from: 53
              to: 53
            icmpTypeCode:
              type: -1
              code: -1
      customDnsConfigurations:
        - customDnsServerName: example.finspace.amazonaws.com
          customDnsServerIp: 10.0.0.76

The attachmentNetworkAclConfigurations array defines rules that filter Transit Gateway traffic. Each rule specifies a ruleNumber for ordering, protocol (6 for TCP), ruleAction (allow or deny), and the target cidrBlock. The portRange block restricts traffic to specific ports; this example allows DNS traffic on port 53. The icmpTypeCode block controls ICMP messages; setting both type and code to -1 disables ICMP filtering for this rule.

Beyond these examples

These snippets focus on specific Kx environment features: KMS encryption and environment naming, Transit Gateway connectivity, and network ACL rules for attachment filtering. They’re intentionally minimal rather than full analytics deployments.

The examples rely on pre-existing infrastructure such as KMS keys for encryption, Transit Gateways for network connectivity, and DNS servers for custom resolution. They focus on configuring the environment rather than provisioning the surrounding infrastructure.

To keep things focused, common environment patterns are omitted, including:

  • Environment tagging and metadata (tags, description)
  • Region-specific deployment (region property)
  • Cluster and database provisioning within the environment
  • IAM permissions for FinSpace operations

These omissions are intentional: the goal is to illustrate how each environment feature is wired, not provide drop-in analytics modules. See the FinSpace Kx Environment resource reference for all available configuration options.

Let's create AWS FinSpace Kx Environments

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Getting Started & Basic Configuration
What's required to create a KX environment?
You need name and kmsKeyId (the KMS key ARN for encrypting data in the environment).
What region is used if I don't specify one?
The region defaults to the Region set in the provider configuration.
Why are availability zones important for my KX environment?
The availabilityZones output property shows which AWS Availability Zones the environment is available in, which is important when selecting VPC subnets for cluster creation.
Networking & Connectivity
How do I connect my KX environment to an internal network?
Configure transitGatewayConfiguration with transitGatewayId and routableCidrSpace to connect the environment to an internal network.
What's the purpose of customDnsConfigurations?
It sets up Route-53 outbound resolvers by specifying DNS server names and IP addresses.
How do I configure network ACL rules for transit gateway attachments?
Use attachmentNetworkAclConfigurations within transitGatewayConfiguration to specify rule number, protocol, action, CIDR block, and port ranges.
What does protocol '6' mean in network ACL configuration?
Protocol 6 represents TCP, as shown in the network ACL example.

Using a different cloud?

Explore analytics guides for other cloud providers: