The aws:glue/connection:Connection resource, part of the Pulumi AWS provider, stores connection metadata for Glue jobs to access databases, data warehouses, and other data sources. This guide focuses on four capabilities: JDBC database connections with inline and secret-based credentials, VPC networking for private database access, custom connectors for specialized databases, and cloud data warehouse and search service integration.
Connections reference Secrets Manager secrets, VPC infrastructure, and external data sources that must exist separately. The examples are intentionally small. Combine them with your own VPC configuration, secrets, and data sources.
Connect to a JDBC database with inline credentials
ETL jobs often need to read from or write to relational databases. Glue connections store JDBC URLs and credentials so jobs can access databases without embedding connection details in job code.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.glue.Connection("example", {
name: "example",
connectionProperties: {
JDBC_CONNECTION_URL: "jdbc:mysql://example.com/exampledatabase",
PASSWORD: "examplepassword",
USERNAME: "exampleusername",
},
});
import pulumi
import pulumi_aws as aws
example = aws.glue.Connection("example",
name="example",
connection_properties={
"JDBC_CONNECTION_URL": "jdbc:mysql://example.com/exampledatabase",
"PASSWORD": "examplepassword",
"USERNAME": "exampleusername",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/glue"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := glue.NewConnection(ctx, "example", &glue.ConnectionArgs{
Name: pulumi.String("example"),
ConnectionProperties: pulumi.StringMap{
"JDBC_CONNECTION_URL": pulumi.String("jdbc:mysql://example.com/exampledatabase"),
"PASSWORD": pulumi.String("examplepassword"),
"USERNAME": pulumi.String("exampleusername"),
},
})
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.Glue.Connection("example", new()
{
Name = "example",
ConnectionProperties =
{
{ "JDBC_CONNECTION_URL", "jdbc:mysql://example.com/exampledatabase" },
{ "PASSWORD", "examplepassword" },
{ "USERNAME", "exampleusername" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.glue.Connection;
import com.pulumi.aws.glue.ConnectionArgs;
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 Connection("example", ConnectionArgs.builder()
.name("example")
.connectionProperties(Map.ofEntries(
Map.entry("JDBC_CONNECTION_URL", "jdbc:mysql://example.com/exampledatabase"),
Map.entry("PASSWORD", "examplepassword"),
Map.entry("USERNAME", "exampleusername")
))
.build());
}
}
resources:
example:
type: aws:glue:Connection
properties:
name: example
connectionProperties:
JDBC_CONNECTION_URL: jdbc:mysql://example.com/exampledatabase
PASSWORD: examplepassword
USERNAME: exampleusername
The connectionProperties map holds the JDBC URL, username, and password. Glue jobs reference this connection by name to access the database. The JDBC_CONNECTION_URL specifies the database endpoint and database name; USERNAME and PASSWORD provide authentication.
Reference credentials from Secrets Manager
Production deployments avoid hardcoding credentials by storing them in Secrets Manager and referencing the secret from the connection.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = aws.secretsmanager.getSecret({
name: "example-secret",
});
const exampleConnection = new aws.glue.Connection("example", {
name: "example",
connectionProperties: {
JDBC_CONNECTION_URL: "jdbc:mysql://example.com/exampledatabase",
SECRET_ID: example.then(example => example.name),
},
});
import pulumi
import pulumi_aws as aws
example = aws.secretsmanager.get_secret(name="example-secret")
example_connection = aws.glue.Connection("example",
name="example",
connection_properties={
"JDBC_CONNECTION_URL": "jdbc:mysql://example.com/exampledatabase",
"SECRET_ID": example.name,
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/glue"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/secretsmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := secretsmanager.LookupSecret(ctx, &secretsmanager.LookupSecretArgs{
Name: pulumi.StringRef("example-secret"),
}, nil)
if err != nil {
return err
}
_, err = glue.NewConnection(ctx, "example", &glue.ConnectionArgs{
Name: pulumi.String("example"),
ConnectionProperties: pulumi.StringMap{
"JDBC_CONNECTION_URL": pulumi.String("jdbc:mysql://example.com/exampledatabase"),
"SECRET_ID": pulumi.String(example.Name),
},
})
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 = Aws.SecretsManager.GetSecret.Invoke(new()
{
Name = "example-secret",
});
var exampleConnection = new Aws.Glue.Connection("example", new()
{
Name = "example",
ConnectionProperties =
{
{ "JDBC_CONNECTION_URL", "jdbc:mysql://example.com/exampledatabase" },
{ "SECRET_ID", example.Apply(getSecretResult => getSecretResult.Name) },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.secretsmanager.SecretsmanagerFunctions;
import com.pulumi.aws.secretsmanager.inputs.GetSecretArgs;
import com.pulumi.aws.glue.Connection;
import com.pulumi.aws.glue.ConnectionArgs;
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) {
final var example = SecretsmanagerFunctions.getSecret(GetSecretArgs.builder()
.name("example-secret")
.build());
var exampleConnection = new Connection("exampleConnection", ConnectionArgs.builder()
.name("example")
.connectionProperties(Map.ofEntries(
Map.entry("JDBC_CONNECTION_URL", "jdbc:mysql://example.com/exampledatabase"),
Map.entry("SECRET_ID", example.name())
))
.build());
}
}
resources:
exampleConnection:
type: aws:glue:Connection
name: example
properties:
name: example
connectionProperties:
JDBC_CONNECTION_URL: jdbc:mysql://example.com/exampledatabase
SECRET_ID: ${example.name}
variables:
example:
fn::invoke:
function: aws:secretsmanager:getSecret
arguments:
name: example-secret
Instead of USERNAME and PASSWORD properties, the SECRET_ID property points to a Secrets Manager secret containing credentials. Glue retrieves credentials at runtime, keeping them out of connection metadata. This extends the basic JDBC pattern with secure credential management.
Connect to databases in private VPC subnets
RDS instances and other databases often run in private subnets without public endpoints. VPC connections allow Glue jobs to reach these resources through elastic network interfaces.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.glue.Connection("example", {
name: "example",
connectionProperties: {
JDBC_CONNECTION_URL: `jdbc:mysql://${exampleAwsRdsCluster.endpoint}/exampledatabase`,
PASSWORD: "examplepassword",
USERNAME: "exampleusername",
},
physicalConnectionRequirements: {
availabilityZone: exampleAwsSubnet.availabilityZone,
securityGroupIdLists: [exampleAwsSecurityGroup.id],
subnetId: exampleAwsSubnet.id,
},
});
import pulumi
import pulumi_aws as aws
example = aws.glue.Connection("example",
name="example",
connection_properties={
"JDBC_CONNECTION_URL": f"jdbc:mysql://{example_aws_rds_cluster['endpoint']}/exampledatabase",
"PASSWORD": "examplepassword",
"USERNAME": "exampleusername",
},
physical_connection_requirements={
"availability_zone": example_aws_subnet["availabilityZone"],
"security_group_id_lists": [example_aws_security_group["id"]],
"subnet_id": example_aws_subnet["id"],
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/glue"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := glue.NewConnection(ctx, "example", &glue.ConnectionArgs{
Name: pulumi.String("example"),
ConnectionProperties: pulumi.StringMap{
"JDBC_CONNECTION_URL": pulumi.Sprintf("jdbc:mysql://%v/exampledatabase", exampleAwsRdsCluster.Endpoint),
"PASSWORD": pulumi.String("examplepassword"),
"USERNAME": pulumi.String("exampleusername"),
},
PhysicalConnectionRequirements: &glue.ConnectionPhysicalConnectionRequirementsArgs{
AvailabilityZone: pulumi.Any(exampleAwsSubnet.AvailabilityZone),
SecurityGroupIdLists: pulumi.StringArray{
exampleAwsSecurityGroup.Id,
},
SubnetId: pulumi.Any(exampleAwsSubnet.Id),
},
})
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.Glue.Connection("example", new()
{
Name = "example",
ConnectionProperties =
{
{ "JDBC_CONNECTION_URL", $"jdbc:mysql://{exampleAwsRdsCluster.Endpoint}/exampledatabase" },
{ "PASSWORD", "examplepassword" },
{ "USERNAME", "exampleusername" },
},
PhysicalConnectionRequirements = new Aws.Glue.Inputs.ConnectionPhysicalConnectionRequirementsArgs
{
AvailabilityZone = exampleAwsSubnet.AvailabilityZone,
SecurityGroupIdLists = new[]
{
exampleAwsSecurityGroup.Id,
},
SubnetId = exampleAwsSubnet.Id,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.glue.Connection;
import com.pulumi.aws.glue.ConnectionArgs;
import com.pulumi.aws.glue.inputs.ConnectionPhysicalConnectionRequirementsArgs;
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 Connection("example", ConnectionArgs.builder()
.name("example")
.connectionProperties(Map.ofEntries(
Map.entry("JDBC_CONNECTION_URL", String.format("jdbc:mysql://%s/exampledatabase", exampleAwsRdsCluster.endpoint())),
Map.entry("PASSWORD", "examplepassword"),
Map.entry("USERNAME", "exampleusername")
))
.physicalConnectionRequirements(ConnectionPhysicalConnectionRequirementsArgs.builder()
.availabilityZone(exampleAwsSubnet.availabilityZone())
.securityGroupIdLists(exampleAwsSecurityGroup.id())
.subnetId(exampleAwsSubnet.id())
.build())
.build());
}
}
resources:
example:
type: aws:glue:Connection
properties:
name: example
connectionProperties:
JDBC_CONNECTION_URL: jdbc:mysql://${exampleAwsRdsCluster.endpoint}/exampledatabase
PASSWORD: examplepassword
USERNAME: exampleusername
physicalConnectionRequirements:
availabilityZone: ${exampleAwsSubnet.availabilityZone}
securityGroupIdLists:
- ${exampleAwsSecurityGroup.id}
subnetId: ${exampleAwsSubnet.id}
The physicalConnectionRequirements block places Glue’s network interface in your subnet with specified security groups. The subnetId determines which subnet hosts the interface; securityGroupIdLists controls network access rules. Glue creates and manages the network interface automatically when jobs use this connection.
Define and use custom JDBC connectors
Glue supports custom connectors for databases not covered by built-in connection types. Teams define a template connection with the connector JAR location, then reference it from actual connections.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
// Define the custom connector using the connection_type of `CUSTOM` with the match_criteria of `template_connection`
// Example here being a snowflake jdbc connector with a secret having user and password as keys
const example = aws.secretsmanager.getSecret({
name: "example-secret",
});
const example1 = new aws.glue.Connection("example1", {
name: "example1",
connectionType: "CUSTOM",
connectionProperties: {
CONNECTOR_CLASS_NAME: "net.snowflake.client.jdbc.SnowflakeDriver",
CONNECTION_TYPE: "Jdbc",
CONNECTOR_URL: "s3://example/snowflake-jdbc.jar",
JDBC_CONNECTION_URL: "[[\"default=jdbc:snowflake://example.com/?user=${user}&password=${password}\"],\",\"]",
},
matchCriterias: ["template-connection"],
});
// Reference the connector using match_criteria with the connector created above.
const example2 = new aws.glue.Connection("example2", {
name: "example2",
connectionType: "CUSTOM",
connectionProperties: {
CONNECTOR_CLASS_NAME: "net.snowflake.client.jdbc.SnowflakeDriver",
CONNECTION_TYPE: "Jdbc",
CONNECTOR_URL: "s3://example/snowflake-jdbc.jar",
JDBC_CONNECTION_URL: "jdbc:snowflake://example.com/?user=${user}&password=${password}",
SECRET_ID: example.then(example => example.name),
},
matchCriterias: [
"Connection",
example1.name,
],
});
import pulumi
import pulumi_aws as aws
# Define the custom connector using the connection_type of `CUSTOM` with the match_criteria of `template_connection`
# Example here being a snowflake jdbc connector with a secret having user and password as keys
example = aws.secretsmanager.get_secret(name="example-secret")
example1 = aws.glue.Connection("example1",
name="example1",
connection_type="CUSTOM",
connection_properties={
"CONNECTOR_CLASS_NAME": "net.snowflake.client.jdbc.SnowflakeDriver",
"CONNECTION_TYPE": "Jdbc",
"CONNECTOR_URL": "s3://example/snowflake-jdbc.jar",
"JDBC_CONNECTION_URL": "[[\"default=jdbc:snowflake://example.com/?user=${user}&password=${password}\"],\",\"]",
},
match_criterias=["template-connection"])
# Reference the connector using match_criteria with the connector created above.
example2 = aws.glue.Connection("example2",
name="example2",
connection_type="CUSTOM",
connection_properties={
"CONNECTOR_CLASS_NAME": "net.snowflake.client.jdbc.SnowflakeDriver",
"CONNECTION_TYPE": "Jdbc",
"CONNECTOR_URL": "s3://example/snowflake-jdbc.jar",
"JDBC_CONNECTION_URL": "jdbc:snowflake://example.com/?user=${user}&password=${password}",
"SECRET_ID": example.name,
},
match_criterias=[
"Connection",
example1.name,
])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/glue"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/secretsmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
// Define the custom connector using the connection_type of `CUSTOM` with the match_criteria of `template_connection`
// Example here being a snowflake jdbc connector with a secret having user and password as keys
example, err := secretsmanager.LookupSecret(ctx, &secretsmanager.LookupSecretArgs{
Name: pulumi.StringRef("example-secret"),
}, nil)
if err != nil {
return err
}
example1, err := glue.NewConnection(ctx, "example1", &glue.ConnectionArgs{
Name: pulumi.String("example1"),
ConnectionType: pulumi.String("CUSTOM"),
ConnectionProperties: pulumi.StringMap{
"CONNECTOR_CLASS_NAME": pulumi.String("net.snowflake.client.jdbc.SnowflakeDriver"),
"CONNECTION_TYPE": pulumi.String("Jdbc"),
"CONNECTOR_URL": pulumi.String("s3://example/snowflake-jdbc.jar"),
"JDBC_CONNECTION_URL": pulumi.String("[[\"default=jdbc:snowflake://example.com/?user=${user}&password=${password}\"],\",\"]"),
},
MatchCriterias: pulumi.StringArray{
pulumi.String("template-connection"),
},
})
if err != nil {
return err
}
// Reference the connector using match_criteria with the connector created above.
_, err = glue.NewConnection(ctx, "example2", &glue.ConnectionArgs{
Name: pulumi.String("example2"),
ConnectionType: pulumi.String("CUSTOM"),
ConnectionProperties: pulumi.StringMap{
"CONNECTOR_CLASS_NAME": pulumi.String("net.snowflake.client.jdbc.SnowflakeDriver"),
"CONNECTION_TYPE": pulumi.String("Jdbc"),
"CONNECTOR_URL": pulumi.String("s3://example/snowflake-jdbc.jar"),
"JDBC_CONNECTION_URL": pulumi.String("jdbc:snowflake://example.com/?user=${user}&password=${password}"),
"SECRET_ID": pulumi.String(example.Name),
},
MatchCriterias: pulumi.StringArray{
pulumi.String("Connection"),
example1.Name,
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
// Define the custom connector using the connection_type of `CUSTOM` with the match_criteria of `template_connection`
// Example here being a snowflake jdbc connector with a secret having user and password as keys
var example = Aws.SecretsManager.GetSecret.Invoke(new()
{
Name = "example-secret",
});
var example1 = new Aws.Glue.Connection("example1", new()
{
Name = "example1",
ConnectionType = "CUSTOM",
ConnectionProperties =
{
{ "CONNECTOR_CLASS_NAME", "net.snowflake.client.jdbc.SnowflakeDriver" },
{ "CONNECTION_TYPE", "Jdbc" },
{ "CONNECTOR_URL", "s3://example/snowflake-jdbc.jar" },
{ "JDBC_CONNECTION_URL", "[[\"default=jdbc:snowflake://example.com/?user=${user}&password=${password}\"],\",\"]" },
},
MatchCriterias = new[]
{
"template-connection",
},
});
// Reference the connector using match_criteria with the connector created above.
var example2 = new Aws.Glue.Connection("example2", new()
{
Name = "example2",
ConnectionType = "CUSTOM",
ConnectionProperties =
{
{ "CONNECTOR_CLASS_NAME", "net.snowflake.client.jdbc.SnowflakeDriver" },
{ "CONNECTION_TYPE", "Jdbc" },
{ "CONNECTOR_URL", "s3://example/snowflake-jdbc.jar" },
{ "JDBC_CONNECTION_URL", "jdbc:snowflake://example.com/?user=${user}&password=${password}" },
{ "SECRET_ID", example.Apply(getSecretResult => getSecretResult.Name) },
},
MatchCriterias = new[]
{
"Connection",
example1.Name,
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.secretsmanager.SecretsmanagerFunctions;
import com.pulumi.aws.secretsmanager.inputs.GetSecretArgs;
import com.pulumi.aws.glue.Connection;
import com.pulumi.aws.glue.ConnectionArgs;
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) {
// Define the custom connector using the connection_type of `CUSTOM` with the match_criteria of `template_connection`
// Example here being a snowflake jdbc connector with a secret having user and password as keys
final var example = SecretsmanagerFunctions.getSecret(GetSecretArgs.builder()
.name("example-secret")
.build());
var example1 = new Connection("example1", ConnectionArgs.builder()
.name("example1")
.connectionType("CUSTOM")
.connectionProperties(Map.ofEntries(
Map.entry("CONNECTOR_CLASS_NAME", "net.snowflake.client.jdbc.SnowflakeDriver"),
Map.entry("CONNECTION_TYPE", "Jdbc"),
Map.entry("CONNECTOR_URL", "s3://example/snowflake-jdbc.jar"),
Map.entry("JDBC_CONNECTION_URL", "[[\"default=jdbc:snowflake://example.com/?user=${user}&password=${password}\"],\",\"]")
))
.matchCriterias("template-connection")
.build());
// Reference the connector using match_criteria with the connector created above.
var example2 = new Connection("example2", ConnectionArgs.builder()
.name("example2")
.connectionType("CUSTOM")
.connectionProperties(Map.ofEntries(
Map.entry("CONNECTOR_CLASS_NAME", "net.snowflake.client.jdbc.SnowflakeDriver"),
Map.entry("CONNECTION_TYPE", "Jdbc"),
Map.entry("CONNECTOR_URL", "s3://example/snowflake-jdbc.jar"),
Map.entry("JDBC_CONNECTION_URL", "jdbc:snowflake://example.com/?user=${user}&password=${password}"),
Map.entry("SECRET_ID", example.name())
))
.matchCriterias(
"Connection",
example1.name())
.build());
}
}
resources:
example1:
type: aws:glue:Connection
properties:
name: example1
connectionType: CUSTOM
connectionProperties:
CONNECTOR_CLASS_NAME: net.snowflake.client.jdbc.SnowflakeDriver
CONNECTION_TYPE: Jdbc
CONNECTOR_URL: s3://example/snowflake-jdbc.jar
JDBC_CONNECTION_URL: '[["default=jdbc:snowflake://example.com/?user=$${user}&password=$${password}"],","]'
matchCriterias:
- template-connection
# Reference the connector using match_criteria with the connector created above.
example2:
type: aws:glue:Connection
properties:
name: example2
connectionType: CUSTOM
connectionProperties:
CONNECTOR_CLASS_NAME: net.snowflake.client.jdbc.SnowflakeDriver
CONNECTION_TYPE: Jdbc
CONNECTOR_URL: s3://example/snowflake-jdbc.jar
JDBC_CONNECTION_URL: jdbc:snowflake://example.com/?user=$${user}&password=$${password}
SECRET_ID: ${example.name}
matchCriterias:
- Connection
- ${example1.name}
variables:
# Define the custom connector using the connection_type of `CUSTOM` with the match_criteria of `template_connection`
# Example here being a snowflake jdbc connector with a secret having user and password as keys
example:
fn::invoke:
function: aws:secretsmanager:getSecret
arguments:
name: example-secret
The first connection (example1) acts as a template with connectionType set to CUSTOM and matchCriterias containing “template-connection”. It specifies the CONNECTOR_CLASS_NAME (JDBC driver class), CONNECTOR_URL (S3 path to JAR), and a parameterized JDBC_CONNECTION_URL. The second connection (example2) references the template via matchCriterias and provides actual credentials through SECRET_ID.
Connect to OpenSearch for search and analytics
Data pipelines that need to query or index documents in OpenSearch use Spark-based connections with authentication and endpoint configuration.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.secretsmanager.Secret("example", {name: "example-secret"});
const exampleSecretVersion = new aws.secretsmanager.SecretVersion("example", {
secretId: example.id,
secretString: JSON.stringify({
"opensearch.net.http.auth.user": "exampleusername",
"opensearch.net.http.auth.pass": "examplepassword",
}),
});
const exampleConnection = new aws.glue.Connection("example", {
name: "example",
connectionType: "OPENSEARCH",
connectionProperties: {
SparkProperties: pulumi.jsonStringify({
secretId: example.name,
"opensearch.nodes": "https://search-exampledomain-ixlmh4jieahrau3bfebcgp8cnm.us-east-1.es.amazonaws.com",
"opensearch.port": "443",
"opensearch.aws.sigv4.region": "us-east-1",
"opensearch.nodes.wan.only": "true",
"opensearch.aws.sigv4.enabled": "true",
}),
},
});
import pulumi
import json
import pulumi_aws as aws
example = aws.secretsmanager.Secret("example", name="example-secret")
example_secret_version = aws.secretsmanager.SecretVersion("example",
secret_id=example.id,
secret_string=json.dumps({
"opensearch.net.http.auth.user": "exampleusername",
"opensearch.net.http.auth.pass": "examplepassword",
}))
example_connection = aws.glue.Connection("example",
name="example",
connection_type="OPENSEARCH",
connection_properties={
"SparkProperties": pulumi.Output.json_dumps({
"secretId": example.name,
"opensearch.nodes": "https://search-exampledomain-ixlmh4jieahrau3bfebcgp8cnm.us-east-1.es.amazonaws.com",
"opensearch.port": "443",
"opensearch.aws.sigv4.region": "us-east-1",
"opensearch.nodes.wan.only": "true",
"opensearch.aws.sigv4.enabled": "true",
}),
})
package main
import (
"encoding/json"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/glue"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/secretsmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := secretsmanager.NewSecret(ctx, "example", &secretsmanager.SecretArgs{
Name: pulumi.String("example-secret"),
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"opensearch.net.http.auth.user": "exampleusername",
"opensearch.net.http.auth.pass": "examplepassword",
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = secretsmanager.NewSecretVersion(ctx, "example", &secretsmanager.SecretVersionArgs{
SecretId: example.ID(),
SecretString: pulumi.String(json0),
})
if err != nil {
return err
}
_, err = glue.NewConnection(ctx, "example", &glue.ConnectionArgs{
Name: pulumi.String("example"),
ConnectionType: pulumi.String("OPENSEARCH"),
ConnectionProperties: pulumi.StringMap{
"SparkProperties": example.Name.ApplyT(func(name string) (pulumi.String, error) {
var _zero pulumi.String
tmpJSON1, err := json.Marshal(map[string]interface{}{
"secretId": name,
"opensearch.nodes": "https://search-exampledomain-ixlmh4jieahrau3bfebcgp8cnm.us-east-1.es.amazonaws.com",
"opensearch.port": "443",
"opensearch.aws.sigv4.region": "us-east-1",
"opensearch.nodes.wan.only": "true",
"opensearch.aws.sigv4.enabled": "true",
})
if err != nil {
return _zero, err
}
json1 := string(tmpJSON1)
return pulumi.String(json1), nil
}).(pulumi.StringOutput),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.SecretsManager.Secret("example", new()
{
Name = "example-secret",
});
var exampleSecretVersion = new Aws.SecretsManager.SecretVersion("example", new()
{
SecretId = example.Id,
SecretString = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["opensearch.net.http.auth.user"] = "exampleusername",
["opensearch.net.http.auth.pass"] = "examplepassword",
}),
});
var exampleConnection = new Aws.Glue.Connection("example", new()
{
Name = "example",
ConnectionType = "OPENSEARCH",
ConnectionProperties =
{
{ "SparkProperties", Output.JsonSerialize(Output.Create(new Dictionary<string, object?>
{
["secretId"] = example.Name,
["opensearch.nodes"] = "https://search-exampledomain-ixlmh4jieahrau3bfebcgp8cnm.us-east-1.es.amazonaws.com",
["opensearch.port"] = "443",
["opensearch.aws.sigv4.region"] = "us-east-1",
["opensearch.nodes.wan.only"] = "true",
["opensearch.aws.sigv4.enabled"] = "true",
})) },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.secretsmanager.Secret;
import com.pulumi.aws.secretsmanager.SecretArgs;
import com.pulumi.aws.secretsmanager.SecretVersion;
import com.pulumi.aws.secretsmanager.SecretVersionArgs;
import com.pulumi.aws.glue.Connection;
import com.pulumi.aws.glue.ConnectionArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 Secret("example", SecretArgs.builder()
.name("example-secret")
.build());
var exampleSecretVersion = new SecretVersion("exampleSecretVersion", SecretVersionArgs.builder()
.secretId(example.id())
.secretString(serializeJson(
jsonObject(
jsonProperty("opensearch.net.http.auth.user", "exampleusername"),
jsonProperty("opensearch.net.http.auth.pass", "examplepassword")
)))
.build());
var exampleConnection = new Connection("exampleConnection", ConnectionArgs.builder()
.name("example")
.connectionType("OPENSEARCH")
.connectionProperties(Map.of("SparkProperties", example.name().applyValue(_name -> serializeJson(
jsonObject(
jsonProperty("secretId", _name),
jsonProperty("opensearch.nodes", "https://search-exampledomain-ixlmh4jieahrau3bfebcgp8cnm.us-east-1.es.amazonaws.com"),
jsonProperty("opensearch.port", "443"),
jsonProperty("opensearch.aws.sigv4.region", "us-east-1"),
jsonProperty("opensearch.nodes.wan.only", "true"),
jsonProperty("opensearch.aws.sigv4.enabled", "true")
)))))
.build());
}
}
resources:
example:
type: aws:secretsmanager:Secret
properties:
name: example-secret
exampleSecretVersion:
type: aws:secretsmanager:SecretVersion
name: example
properties:
secretId: ${example.id}
secretString:
fn::toJSON:
opensearch.net.http.auth.user: exampleusername
opensearch.net.http.auth.pass: examplepassword
exampleConnection:
type: aws:glue:Connection
name: example
properties:
name: example
connectionType: OPENSEARCH
connectionProperties:
SparkProperties:
fn::toJSON:
secretId: ${example.name}
opensearch.nodes: https://search-exampledomain-ixlmh4jieahrau3bfebcgp8cnm.us-east-1.es.amazonaws.com
opensearch.port: '443'
opensearch.aws.sigv4.region: us-east-1
opensearch.nodes.wan.only: 'true'
opensearch.aws.sigv4.enabled: 'true'
The connectionType is OPENSEARCH, and SparkProperties contains a JSON document with OpenSearch-specific settings. The opensearch.nodes property specifies the domain endpoint; opensearch.aws.sigv4.enabled enables AWS signature authentication. Credentials come from the referenced Secrets Manager secret.
Connect to Snowflake data warehouses
Analytics teams often load data into Snowflake for querying and reporting. Glue connections to Snowflake use Spark properties with role and URL configuration.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.secretsmanager.Secret("example", {name: "example-secret"});
const exampleSecretVersion = new aws.secretsmanager.SecretVersion("example", {
secretId: example.id,
secretString: JSON.stringify({
sfUser: "exampleusername",
sfPassword: "examplepassword",
}),
});
const exampleConnection = new aws.glue.Connection("example", {
name: "example",
connectionType: "SNOWFLAKE",
connectionProperties: {
SparkProperties: pulumi.jsonStringify({
secretId: example.name,
sfRole: "EXAMPLEETLROLE",
sfUrl: "exampleorg-exampleconnection.snowflakecomputing.com",
}),
},
});
import pulumi
import json
import pulumi_aws as aws
example = aws.secretsmanager.Secret("example", name="example-secret")
example_secret_version = aws.secretsmanager.SecretVersion("example",
secret_id=example.id,
secret_string=json.dumps({
"sfUser": "exampleusername",
"sfPassword": "examplepassword",
}))
example_connection = aws.glue.Connection("example",
name="example",
connection_type="SNOWFLAKE",
connection_properties={
"SparkProperties": pulumi.Output.json_dumps({
"secretId": example.name,
"sfRole": "EXAMPLEETLROLE",
"sfUrl": "exampleorg-exampleconnection.snowflakecomputing.com",
}),
})
package main
import (
"encoding/json"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/glue"
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/secretsmanager"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
example, err := secretsmanager.NewSecret(ctx, "example", &secretsmanager.SecretArgs{
Name: pulumi.String("example-secret"),
})
if err != nil {
return err
}
tmpJSON0, err := json.Marshal(map[string]interface{}{
"sfUser": "exampleusername",
"sfPassword": "examplepassword",
})
if err != nil {
return err
}
json0 := string(tmpJSON0)
_, err = secretsmanager.NewSecretVersion(ctx, "example", &secretsmanager.SecretVersionArgs{
SecretId: example.ID(),
SecretString: pulumi.String(json0),
})
if err != nil {
return err
}
_, err = glue.NewConnection(ctx, "example", &glue.ConnectionArgs{
Name: pulumi.String("example"),
ConnectionType: pulumi.String("SNOWFLAKE"),
ConnectionProperties: pulumi.StringMap{
"SparkProperties": example.Name.ApplyT(func(name string) (pulumi.String, error) {
var _zero pulumi.String
tmpJSON1, err := json.Marshal(map[string]interface{}{
"secretId": name,
"sfRole": "EXAMPLEETLROLE",
"sfUrl": "exampleorg-exampleconnection.snowflakecomputing.com",
})
if err != nil {
return _zero, err
}
json1 := string(tmpJSON1)
return pulumi.String(json1), nil
}).(pulumi.StringOutput),
},
})
if err != nil {
return err
}
return nil
})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.SecretsManager.Secret("example", new()
{
Name = "example-secret",
});
var exampleSecretVersion = new Aws.SecretsManager.SecretVersion("example", new()
{
SecretId = example.Id,
SecretString = JsonSerializer.Serialize(new Dictionary<string, object?>
{
["sfUser"] = "exampleusername",
["sfPassword"] = "examplepassword",
}),
});
var exampleConnection = new Aws.Glue.Connection("example", new()
{
Name = "example",
ConnectionType = "SNOWFLAKE",
ConnectionProperties =
{
{ "SparkProperties", Output.JsonSerialize(Output.Create(new Dictionary<string, object?>
{
["secretId"] = example.Name,
["sfRole"] = "EXAMPLEETLROLE",
["sfUrl"] = "exampleorg-exampleconnection.snowflakecomputing.com",
})) },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.secretsmanager.Secret;
import com.pulumi.aws.secretsmanager.SecretArgs;
import com.pulumi.aws.secretsmanager.SecretVersion;
import com.pulumi.aws.secretsmanager.SecretVersionArgs;
import com.pulumi.aws.glue.Connection;
import com.pulumi.aws.glue.ConnectionArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 Secret("example", SecretArgs.builder()
.name("example-secret")
.build());
var exampleSecretVersion = new SecretVersion("exampleSecretVersion", SecretVersionArgs.builder()
.secretId(example.id())
.secretString(serializeJson(
jsonObject(
jsonProperty("sfUser", "exampleusername"),
jsonProperty("sfPassword", "examplepassword")
)))
.build());
var exampleConnection = new Connection("exampleConnection", ConnectionArgs.builder()
.name("example")
.connectionType("SNOWFLAKE")
.connectionProperties(Map.of("SparkProperties", example.name().applyValue(_name -> serializeJson(
jsonObject(
jsonProperty("secretId", _name),
jsonProperty("sfRole", "EXAMPLEETLROLE"),
jsonProperty("sfUrl", "exampleorg-exampleconnection.snowflakecomputing.com")
)))))
.build());
}
}
resources:
example:
type: aws:secretsmanager:Secret
properties:
name: example-secret
exampleSecretVersion:
type: aws:secretsmanager:SecretVersion
name: example
properties:
secretId: ${example.id}
secretString:
fn::toJSON:
sfUser: exampleusername
sfPassword: examplepassword
exampleConnection:
type: aws:glue:Connection
name: example
properties:
name: example
connectionType: SNOWFLAKE
connectionProperties:
SparkProperties:
fn::toJSON:
secretId: ${example.name}
sfRole: EXAMPLEETLROLE
sfUrl: exampleorg-exampleconnection.snowflakecomputing.com
The connectionType is SNOWFLAKE, and SparkProperties contains Snowflake-specific settings. The sfUrl property specifies the Snowflake account URL; sfRole defines the role Glue assumes when connecting. Credentials (sfUser and sfPassword) are stored in the referenced Secrets Manager secret.
Beyond these examples
These snippets focus on specific connection-level features: JDBC and custom connector configuration, Secrets Manager integration, VPC networking for private resources, and cloud data warehouse and search service connections. They’re intentionally minimal rather than full ETL pipelines.
The examples may reference pre-existing infrastructure such as Secrets Manager secrets with database credentials, VPC subnets and security groups and RDS clusters, S3 buckets for custom connector JARs, and OpenSearch domains and Snowflake accounts. They focus on configuring the connection rather than provisioning everything around it.
To keep things focused, common connection patterns are omitted, including:
- Kafka and MongoDB connection types
- Network connection type for VPC peering
- Athena federated query properties (athenaProperties)
- Connection validation and testing
These omissions are intentional: the goal is to illustrate how each connection feature is wired, not provide drop-in ETL modules. See the Glue Connection resource reference for all available configuration options.
Let's configure AWS Glue Connections
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Connection Types & Configuration
SparkProperties key within connectionProperties containing a JSON document. Use pulumi.jsonStringify() to create this JSON.athenaProperties for Athena-specific settings like lambda_function_arn and spill_bucket, while most other connection types use connectionProperties.Authentication & Secrets
SECRET_ID in connectionProperties to your secret name instead of using PASSWORD and USERNAME keys.SECRET_ID or secretId within SparkProperties.VPC & Networking
physicalConnectionRequirements with availabilityZone, securityGroupIdLists, and subnetId properties.Custom Connectors & Advanced Configuration
connectionType: "CUSTOM" and matchCriterias: ["template-connection"]. Then reference it in other connections using matchCriterias: ["Connection", templateName].matchCriterias define selection criteria for connections. For custom connectors, use ["template-connection"] to define a template, then ["Connection", templateName] to reference it.Immutability & Limitations
catalogId and name are immutable. Changing either requires replacing the entire connection resource.Using a different cloud?
Explore analytics guides for other cloud providers: