Simplifying Zero Trust Security for AWS with Teleport
Jan 23
Virtual
Register Now
Teleport logoTry For Free
Fork me on GitHub

Teleport

Amazon DynamoDB using the Teleport Application Service

You can configure the Teleport Application Service to enable secure access to Amazon DynamoDB.

This guide will help you to:

  • Install the Teleport Application Service.
  • Set up the Teleport Application Service to access the AWS Console and API.
  • Connect to your DynamoDB databases through the Teleport Application Service.
Recommendation: Use the Teleport Database Service

The Teleport Application Service enables secure access to DynamoDB via its integration with the AWS management console and API. This is an alternative to accessing DynamoDB through the Teleport Database service, as described in our Database Access with AWS DynamoDB guide.

The Application Service's integration with AWS is not designed specifically for DynamoDB, while the Database Service has a purpose-built DynamoDB integration. As a result, we recommend using the Database Service to enable secure access to DynamoDB.

It is worth noting that the Database Service will allow you to connect with GUI clients, whereas the Application Service does not. On the other hand, a single Application Service configuration can access DynamoDB across regions, while database resources must be configured for each region with DynamoDB databases.

Prerequisites

  • AWS account with DynamoDB databases.
  • IAM permissions to create IAM roles.
  • aws Command Line Interface (CLI) tool installed in PATH.
  • A host, e.g., an EC2 instance, where you will run the Teleport Application Service.
  • A running Teleport cluster version 16.4.12 or above. If you want to get started with Teleport, sign up for a free trial or set up a demo environment.

  • The tctl admin tool and tsh client tool.

    Visit Installation for instructions on downloading tctl and tsh.

  • To check that you can connect to your Teleport cluster, sign in with tsh login, then verify that you can run tctl commands using your current credentials. For example:
    tsh login --proxy=teleport.example.com --user=[email protected]
    tctl status

    Cluster teleport.example.com

    Version 16.4.12

    CA pin sha256:abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678abdc1245efgh5678

    If you can connect to the cluster and run the tctl status command, you can use your current credentials to run subsequent tctl commands from your workstation. If you host your own Teleport cluster, you can also run tctl commands on the computer that hosts the Teleport Auth Service for full permissions.
Not yet a Teleport user?

If you have not yet deployed the Auth Service and Proxy Service, you should follow one of our getting started guides or try our Teleport application access interactive learning track.

We will assume your Teleport cluster is accessible at teleport.example.com and *.teleport.example.com. You can substitute the address of your Teleport Proxy Service. (For Teleport Cloud customers, this will be similar to mytenant.teleport.sh.)

DNS and Teleport-protected applications

Teleport assigns a subdomain to each application you configure for Application Access. For example, if you enroll Grafana as a resource, Teleport assigns the resource to the grafana.teleport.example.com subdomain.

If you host the Teleport cluster on your own network, you should update your DNS configuration to account for application subdomains. You can update DNS in one of two ways:

  • Create a single DNS address (A) or canonical name (CNAME) record using wildcard substitution for the subdomain name. For example, create a DNS record with the name *.teleport.example.com.
  • Create a separate DNS address (A) or canonical name (CNAME) record for each application subdomain.

Modifying DNS ensures that the certificate authority—for example, Let's Encrypt—can issue a certificate for each subdomain and that clients can verify Teleport hosts regardless of the application they are accessing.

If you use the Teleport cloud platform, no DNS updates are needed because your Teleport cluster automatically provides the subdomains and signed TLS certificates for your applications under your tenant address.

Step 1/5. Create an IAM role for DynamoDB access

Create an IAM role that provides access to your DynamoDB resources. Teleport Application Service will assume this IAM role on behalf of the Teleport user that accesses these DynamoDB resources.

There are several methods to create an IAM role:

Visit the Roles page of the AWS Console, then press "Create Role".

Select the "AWS account" option, which creates a default trust policy to allow other entities in this account to assume this role:

Press "Next". Find the AWS-managed policy AmazonDynamoDBFullAccess and then select the policy:

Press "Next". Enter role name ExampleTeleportDynamoDBRole and press "Create role":

Create a file with the following trust policy. Replace aws-account-id with your AWS Account ID:

cat > trust-relationship.json <<EOF{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::aws-account-id:root" }, "Action": "sts:AssumeRole" } ]}EOF

Create an IAM role with name ExampleTeleportDynamoDBRole:

aws iam create-role --role-name ExampleTeleportDynamoDBRole --assume-role-policy-document file://trust-relationship.json

Attach managed policy AmazonDynamoDBFullAccess to the role:

aws iam attach-role-policy --role-name ExampleTeleportDynamoDBRole --policy-arn arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess

Add the following resources to your Terraform deployment. Replace aws-account-id with your AWS Account ID:

cat > teleport_iam_role_ExampleTeleportDynamoDBRole.tf <<EOFresource "aws_iam_role" "teleport-ExampleTeleportDynamoDBRole" { name = "ExampleTeleportDynamoDBRole" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Principal = { AWS = "arn:aws:iam::aws-account-id:root" } Action = "sts:AssumeRole" }, ] })}resource "aws_iam_role_policy_attachment" "teleport-ExampleTeleportDynamoDBRole-AmazonDynamoDBFullAccess" { role = aws_iam_role.teleport-ExampleTeleportDynamoDBRole.name policy_arn = "arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess"}EOF

Then terraform apply.

Apply least-privilege permissions

AmazonDynamoDBFullAccess may provide too much access for your intentions. To use a different IAM policy to reduce permissions, see Managing access permissions to your Amazon DynamoDB Resources for more details.

Step 2/5. Configure the Teleport IAM role mapping

Give your Teleport users permissions to assume IAM roles in your Teleport cluster.

You can do this by creating a Teleport role with the aws_role_arns field listing the IAM role ARN created in the previous step. Create a file called aws-dynamodb-access.yaml with the following content:

cat > aws-dynamodb-access.yaml <<EOFkind: roleversion: v5metadata: name: aws-dynamodb-accessspec: allow: app_labels: '*': '*' aws_role_arns: - arn:aws:iam::aws-account-id:role/ExampleTeleportDynamoDBRoleEOF

Remember to replace aws-account-id with your AWS Account ID.

The aws_role_arns field supports template variables so they can be populated dynamically based on your users' identity provider attributes. Here are some examples:

Use {{internal.aws_role_arns}} in the role definition:

kind: role
version: v5
metadata:
  name: aws-dynamodb-access
spec:
  allow:
    app_labels:
      '*': '*'
    aws_role_arns: ['{{internal.aws_role_arns}}']

Then specify the IAM roles through user traits:

kind: user
version: v2
metadata:
  name: alice
spec:
  roles: ['aws-dynamodb-access']
  traits:
    aws_role_arns: ['arn:aws:iam:123456789000:role/role_for_alice']
---
kind: user
version: v2
metadata:
  name: bob
spec:
  roles: ['aws-dynamodb-access']
  traits:
    aws_role_arns: ['arn:aws:iam:123456789000:role/role_for_bob']

Let's assume that an IAM role has been created for each Teleport user, and the name of the IAM role corresponds to their Email addresses without the Email domain suffix.

Then aws_role_arns can be templated with external.email:

kind: role
version: v5
metadata:
  name: aws-dynamodb-access
spec:
  allow:
    app_labels:
      '*': '*'
    aws_role_arns: ['arn:aws:iam:123456789000:role/{{email.local(external.email)}}']

See Role Templates for details.

Create the new role:

tctl create -f aws-dynamodb-access.yaml

Assign the aws-dynamodb-access role to your Teleport user by running the appropriate commands for your authentication provider:

  1. Retrieve your local user's roles as a comma-separated list:

    ROLES=$(tsh status -f json | jq -r '.active.roles | join(",")')
  2. Edit your local user to add the new role:

    tctl users update $(tsh status -f json | jq -r '.active.username') \ --set-roles "${ROLES?},aws-dynamodb-access"
  3. Sign out of the Teleport cluster and sign in again to assume the new role.

  1. Open your github authentication connector in a text editor:

    tctl edit github/github
  2. Edit the github connector, adding aws-dynamodb-access to the teams_to_roles section.

    The team you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the team must include your user account and should be the smallest team possible within your organization.

    Here is an example:

      teams_to_roles:
        - organization: octocats
          team: admins
          roles:
            - access
    +       - aws-dynamodb-access
    
  3. Apply your changes by saving closing the file in your editor.

  4. Sign out of the Teleport cluster and sign in again to assume the new role.

  1. Retrieve your saml configuration resource:

    tctl get --with-secrets saml/mysaml > saml.yaml

    Note that the --with-secrets flag adds the value of spec.signing_key_pair.private_key to the saml.yaml file. Because this key contains a sensitive value, you should remove the saml.yaml file immediately after updating the resource.

  2. Edit saml.yaml, adding aws-dynamodb-access to the attributes_to_roles section.

    The attribute you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the group must include your user account and should be the smallest group possible within your organization.

    Here is an example:

      attributes_to_roles:
        - name: "groups"
          value: "my-group"
          roles:
            - access
    +       - aws-dynamodb-access
    
  3. Apply your changes:

    tctl create -f saml.yaml
  4. Sign out of the Teleport cluster and sign in again to assume the new role.

  1. Retrieve your oidc configuration resource:

    tctl get oidc/myoidc --with-secrets > oidc.yaml

    Note that the --with-secrets flag adds the value of spec.signing_key_pair.private_key to the oidc.yaml file. Because this key contains a sensitive value, you should remove the oidc.yaml file immediately after updating the resource.

  2. Edit oidc.yaml, adding aws-dynamodb-access to the claims_to_roles section.

    The claim you should map to this role depends on how you have designed your organization's role-based access controls (RBAC). However, the group must include your user account and should be the smallest group possible within your organization.

    Here is an example:

      claims_to_roles:
        - name: "groups"
          value: "my-group"
          roles:
            - access
    +       - aws-dynamodb-access
    
  3. Apply your changes:

    tctl create -f oidc.yaml
  4. Sign out of the Teleport cluster and sign in again to assume the new role.

Step 3/5. Install the Teleport Application Service

Generate a token

A join token is required to authorize a Teleport Application Service instance to join the cluster. Generate a short-lived join token and save the output of the command:

tctl tokens add \ --type=app \ --app-name=aws \ --app-uri=https://console.aws.amazon.com/console/home

On the host where you will run the Teleport Application Service, copy the token to a file called /tmp/token.

non-standard AWS regions

Replace https://console.aws.amazon.com with https://console.amazonaws-us-gov.com for AWS GovCloud (US) regions or https://console.amazonaws.cn for AWS China regions.

Install and start Teleport

Install Teleport on the host where you will run the Teleport Application Service. See our Installation page for options besides Linux servers.

Install Teleport on your Linux server:

  1. Assign edition to one of the following, depending on your Teleport edition:

    EditionValue
    Teleport Enterprise Cloudcloud
    Teleport Enterprise (Self-Hosted)enterprise
    Teleport Community Editionoss
  2. Get the version of Teleport to install. If you have automatic agent updates enabled in your cluster, query the latest Teleport version that is compatible with the updater:

    TELEPORT_DOMAIN=example.teleport.com
    TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/automaticupgrades/channel/default/version | sed 's/v//')"

    Otherwise, get the version of your Teleport cluster:

    TELEPORT_DOMAIN=example.teleport.com
    TELEPORT_VERSION="$(curl https://$TELEPORT_DOMAIN/v1/webapi/ping | jq -r '.server_version')"
  3. Install Teleport on your Linux server:

    curl https://cdn.teleport.dev/install-v16.4.12.sh | bash -s ${TELEPORT_VERSION} edition

    The installation script detects the package manager on your Linux server and uses it to install Teleport binaries. To customize your installation, learn about the Teleport package repositories in the installation guide.

Edit the Teleport configuration file (/etc/teleport.yaml) to include the following information, adjusting the value of proxy_server to specify the host and port of your Teleport Proxy Service:

version: v3
teleport:
  join_params:
    token_name: "/tmp/token"
    method: token
  proxy_server: "teleport.example.com:443"
auth_service:
  enabled: off
proxy_service:
  enabled: off
ssh_service:
  enabled: off
app_service:
  enabled: true
  apps:
  - name: aws
    uri: https://console.aws.amazon.com/home/home

Grant the Teleport Application Service access to credentials that it can use to authenticate to AWS.

  • If you are running the Teleport Application Service on an EC2 instance, you may use the EC2 Instance Metadata Service method
  • If you are running the Teleport Application Service in Kubernetes, you can use IAM Roles for Service Accounts (IRSA)
  • Otherwise, you must use environment variables

Teleport will detect when it is running on an EC2 instance and use the Instance Metadata Service to fetch credentials.

The EC2 instance should be configured to use an EC2 instance profile. For more information, see: Using Instance Profiles.

Refer to IAM Roles for Service Accounts (IRSA) to set up an OIDC provider in AWS and configure an AWS IAM role that allows the pod's service account to assume the role.

Teleport's built-in AWS client reads credentials from the following environment variables:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_DEFAULT_REGION

When you start the Teleport Application Service, the service reads environment variables from a file at the path /etc/default/teleport. Obtain these credentials from your organization. Ensure that /etc/default/teleport has the following content, replacing the values of each variable:

AWS_ACCESS_KEY_ID=00000000000000000000
AWS_SECRET_ACCESS_KEY=0000000000000000000000000000000000000000
AWS_DEFAULT_REGION=<YOUR_REGION>

Teleport's AWS client loads credentials from different sources in the following order:

  • Environment Variables
  • Shared credentials file
  • Shared configuration file (Teleport always enables shared configuration)
  • EC2 Instance Metadata (credentials only)

While you can provide AWS credentials via a shared credentials file or shared configuration file, you will need to run the Teleport Application Service with the AWS_PROFILE environment variable assigned to the name of your profile of choice.

If you have a specific use case that the instructions above do not account for, consult the documentation for the AWS SDK for Go for a detailed description of credential loading behavior.

Configure the Teleport Application Service to start automatically when the host boots up by creating a systemd service for it. The instructions depend on how you installed the Teleport Application Service.

On the host where you will run the Teleport Application Service, enable and start Teleport:

sudo systemctl enable teleport
sudo systemctl start teleport

On the host where you will run the Teleport Application Service, create a systemd service configuration for Teleport, enable the Teleport service, and start Teleport:

sudo teleport install systemd -o /etc/systemd/system/teleport.service
sudo systemctl enable teleport
sudo systemctl start teleport

You can check the status of the Teleport Application Service with systemctl status teleport and view its logs with journalctl -fu teleport.

non-standard AWS regions

For non-standard AWS regions such as AWS GovCloud (US) regions and AWS China regions, please set the corresponding region in the AWS_REGION environment variable or in the AWS credentials file so that the Application Service can use the correct STS endpoint.

Step 4/5. Give Teleport permissions to assume roles

Next, attach the following policy to the IAM role or IAM user the Teleport Application Service instance is using, which allows the Application Service to assume the IAM roles:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "*"
    }
  ]
}
Tip

You can make the policy more strict by providing specific IAM role resource ARNs in the "Resource" field instead of using a wildcard.

Step 5/5. Connect

Once the Application Service has started and joined the cluster, you can start connecting to your DynamoDB database.

Using AWS Management Console

Log in to the Teleport Web UI at https://teleport.example.com (replace with your Proxy Service's public address).

Navigate to the Applications tab in your Teleport cluster's control panel and click on the Launch button for the AWS application. This will bring up an IAM role selector:

Click on the role ExampleTeleportDynamoDBRole and you will get redirected to the AWS Management Console, signed in with the selected role.

In the console's top-right corner, you should see that you're logged in through federated login and the name of your assumed IAM role is ExampleTeleportDynamoDBRole/<teleport-username> where the session name is your Teleport username.

Using AWS CLI

Log into the previously configured AWS app on your desktop:

tsh apps login --aws-role ExampleTeleportDynamoDBRole aws
Logged into AWS app aws. Example AWS CLI command:
tsh aws s3 ls

The --aws-role flag allows you to specify the AWS IAM role to assume when accessing the AWS API. You can either provide a role name like --aws-role ExampleTeleportDynamoDBRole or a full role ARN like arn:aws:iam::123456789000:role/ExampleTeleportDynamoDBRole.

Now you can use the tsh aws command like the native aws command-line tool:

tsh aws dynamodb list-tables

To log out of the aws application and remove credentials:

tsh apps logout aws

Using other DynamoDB applications

First, log into the previously configured AWS app if you haven't already done so:

tsh apps login --aws-role ExampleTeleportDynamoDBRole aws

To connect your DynamoDB application, you can start either a local HTTPS proxy or a local AWS Service Endpoint proxy.

By default, starting the AWS app proxy creates a local HTTPS proxy server that forwards AWS requests to the Teleport Proxy Service, enabling you to access AWS applications.

Now, use the following command to start the proxy your applications will be connecting to:

tsh proxy aws -p 23456
Started AWS proxy on http://127.0.0.1:23456.
Use the following credentials and HTTPS proxy setting to connect to the proxy: AWS_ACCESS_KEY_ID=abcd1234-this-is-an-example AWS_SECRET_ACCESS_KEY=zyxw9876-this-is-an-example AWS_CA_BUNDLE=<local-ca-bundle-path> HTTPS_PROXY=http://127.0.0.1:23456

Use the displayed AWS credentials and HTTPS proxy settings when configuring your application.

For example, you can assign the AWS credentials and the HTTPS proxy address to environment variables for Python AWS SDK:

export AWS_ACCESS_KEY_ID=abcd1234-this-is-an-example
export AWS_SECRET_ACCESS_KEY=zyxw9876-this-is-an-example
export AWS_CA_BUNDLE=<local-ca-bundle-path>
export HTTPS_PROXY=http://127.0.0.1:23456
python3
>>> import boto3>>> boto3.client('dynamodb').list_tables(){'TableNames': ['my-dynamodb-table'], 'ResponseMetadata': {...}}

If your application cannot use a HTTPS proxy, start the AWS app proxy with the --endpoint-url flag to create a local server that can be used as an AWS Service Endpoint.

tsh proxy aws --endpoint-url -p 23457
Started AWS proxy which serves as an AWS endpoint URL at https://localhost:23457
In addition to the endpoint URL, use the following credentials to connect to the proxy: AWS_ACCESS_KEY_ID=abcd1234-this-is-an-example AWS_SECRET_ACCESS_KEY=zyxw9876-this-is-an-example AWS_CA_BUNDLE=<local-ca-bundle-path>

For example, to connect the GUI tool dynamodb-admin to the local AWS Service Endpoint proxy:

export AWS_ACCESS_KEY_ID=abcd1234-this-is-an-example
export AWS_SECRET_ACCESS_KEY=zyxw9876-this-is-an-example
export NODE_EXTRA_CA_CERTS=<local-ca-bundle-path>
export DYNAMO_ENDPOINT=https://127.0.0.1:23457
dynamodb-admin
database endpoint: https://127.0.0.1:23457region: ca-central-1accessKey: <access-key-id>
dynamodb-admin listening on http://localhost:8001 (alternatively http://0.0.0.0:8001)

To log out of the aws application and remove credentials:

tsh apps logout aws

Next steps