diff --git a/docs/config.json b/docs/config.json
index 2287bfa44e441..9c7a61b20484c 100644
--- a/docs/config.json
+++ b/docs/config.json
@@ -1147,8 +1147,12 @@
"slug": "/database-access/guides/",
"entries": [
{
- "title": "AWS DynamoDB",
- "slug": "/database-access/guides/aws-dynamodb/"
+ "title": "AWS Cross-Account",
+ "slug": "/database-access/guides/aws-cross-account/"
+ },
+ {
+ "title": "AWS DynamoDB",
+ "slug": "/database-access/guides/aws-dynamodb/"
},
{
"title": "AWS ElastiCache & MemoryDB",
diff --git a/docs/pages/database-access/guides/aws-cross-account.mdx b/docs/pages/database-access/guides/aws-cross-account.mdx
new file mode 100644
index 0000000000000..b9c9045f28bbb
--- /dev/null
+++ b/docs/pages/database-access/guides/aws-cross-account.mdx
@@ -0,0 +1,243 @@
+---
+title: AWS Cross-Account Database Access
+description: How to connect AWS databases in external AWS accounts to Teleport.
+---
+
+
+ AWS cross-account database access is available starting from Teleport `13.0`.
+
+
+You can deploy the Teleport Database Service with AWS IAM credentials in one
+AWS account and use an AWS IAM role to grant Teleport access to databases in
+another AWS account.
+
+When the Teleport Database Service needs to discover, configure, or retrieve
+short-lived authentication tokens for AWS databases, it uses credentials for an
+AWS IAM identity to make requests to the AWS API.
+To access resources across AWS accounts, you can configure the Teleport Database
+Service to assume an AWS role in another account before it uses the AWS API
+for further actions.
+
+This is not limited to a single AWS role:
+the Teleport Database Service can be configured to connect databases in its own
+AWS account and multiple external AWS accounts at the same time.
+
+You will need to configure the Teleport Database Service to assume an AWS IAM
+role and ensure that AWS IAM permissions are configured to allow the
+`AssumeRole` call.
+
+
+You should also check that your network configuration in AWS allows the
+Teleport Database Service to connect to the databases.
+
+This guide does not cover AWS network configuration, because it depends on your
+specific AWS network setup and the kind(s) of AWS databases you wish to connect
+to Teleport. For more information, see:
+[how to connect your database](../guides.mdx#how-to-connect-your-database-to-teleport).
+
+
+## Teleport configuration
+
+The Teleport Database Service must be configured to assume an external AWS IAM
+role and, optionally, pass an external ID when it assumes that role.
+The configured AWS IAM role will be assumed via an AWS STS `AssumeRole` call
+before the Teleport Database Service uses the AWS API to discover, configure, or retrieve
+short-lived authentication tokens for AWS databases.
+
+An "external ID" is used to address what AWS calls
+[the confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html).
+When you configure the Teleport Database Service to use an external ID, it will
+include that external ID when it calls AWS STS `AssumeRole`.
+The external AWS IAM role's trust policy will be used to verify that the
+correct external ID was provided in the `AssumeRole` call.
+For information about when you should use an external ID, see:
+[purpose of an AWS external ID](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user_externalid.html#external-id-purpose).
+
+AWS database discovery config, static database config, and dynamic database
+config all support the `assume_role_arn` and `external_id` settings.
+
+
+
+Modify your Teleport Database Service configuration file to assume an external
+AWS IAM role when it is discovering AWS databases.
+
+```yaml
+# This example configuration will discover AWS RDS databases in us-west-1
+# within AWS account `222222222222` by assuming the external AWS IAM role
+# "example-role".
+db_service:
+ enabled: "yes"
+ aws:
+ - types: ["rds"]
+ regions: ["us-west-1"]
+ assume_role_arn: "arn:aws:iam::222222222222:role/example-role"
+ external_id: "example-external-id"
+```
+
+Restart the Teleport Database Service for the configuration file changes to take
+effect.
+
+
+The AWS IAM role used to discover a database will also be used by the Teleport
+Database Service to provide access to that database.
+
+
+
+
+Modify your Teleport Database Service configuration file to statically register
+an AWS database in an external account and proxy connections to it.
+
+```yaml
+# This example configuration will statically register an RDS PostgreSQL instance
+# in us-west-1 within AWS account `222222222222` by assuming an external AWS
+# IAM role "example-role".
+db_service:
+ enabled: "yes"
+ databases:
+ - name: "rds-postgres"
+ protocol: "postgres"
+ uri: "rds-postgres.abcdef012345.us-west-1.rds.amazonaws.com:5432"
+ aws:
+ assume_role_arn: "arn:aws:iam::222222222222:role/example-role"
+ external_id: "example-external-id"
+```
+
+Restart the Teleport Database Service for the configuration file changes to take
+effect.
+
+
+
+Create a dynamic database resource to dynamically register an AWS database
+in an external account and proxy connections to it.
+
+```yaml
+# This example configuration will dynamically register an RDS PostgreSQL instance
+# in us-west-1 within AWS account `222222222222`.
+# Teleport Database Service agents that match its labels with resource selectors
+# will proxy the database by assuming the configured external AWS IAM role.
+kind: db
+version: v3
+metadata:
+ name: "rds-postgres"
+ description: "Example dynamic database resource"
+ labels:
+ env: "dev"
+spec:
+ protocol: "postgres"
+ uri: "rds-postgres.abcdef012345.us-west-1.rds.amazonaws.com:5432"
+ aws:
+ # Note that account_id must match the AWS account ID in `assume_role_arn`.
+ # Dynamic database resources do not derive `account_id` from
+ # `assume_role_arn` automatically (unlike static configuration).
+ account_id: "222222222222"
+ assume_role_arn: "arn:aws:iam::222222222222:role/example-role"
+ external_id: "example-external-id"
+```
+
+Save the configuration to a file like `database.yaml` and create it with `tctl`:
+```code
+$ tctl create database.yaml
+```
+For more information about database registration using dynamic database
+resources, see: [Dynamic Registration](dynamic-registration.mdx).
+
+
+
+
+## Teleport AWS IAM identity
+
+In order to assume an AWS IAM role, the Teleport Database Service will need
+credentials for an AWS IAM identity of its own.
+
+(!docs/pages/includes/aws-credentials.mdx service="the Database Service"!)
+
+## AWS IAM permissions
+
+AWS IAM policies must be configured for both the Teleport Database Service's
+AWS IAM identity and the external AWS IAM role:
+- The Teleport Database Service's AWS IAM identity must have permission to
+ assume the external role.
+- The external AWS IAM role's trust policy must trust the Teleport Database
+ Service's AWS IAM identity.
+
+
+ Unlike assuming a role within the same AWS account, when an AWS IAM role is
+ in a different AWS account than the IAM identity that attempts to assume it,
+ the role's trust policy alone is not sufficient to allow assuming the role.
+
+ For more details, see:
+ [AWS cross-account policy evaluation](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html#policy-eval-cross-account).
+
+
+(!docs/pages/includes/database-access/aws-bootstrap.mdx attachToRole="teleport-db-service" attachToUser="teleport-db-service"!)
+
+Specifically, the Teleport Database Service's AWS IAM identity must be granted
+`sts:AssumeRole` permission for the external AWS IAM role. For example:
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": "sts:AssumeRole",
+ "Resource": "arn:aws:iam::222222222222:role/example-role"
+ }
+ ]
+}
+```
+
+You will also need to configure permissions for the external AWS IAM role,
+specific to the type of database(s) that it will be used to access.
+
+For example, suppose `assume_role_arn` is set to
+`arn:aws:iam::222222222222:role/example-role` -
+you can bootstrap permissions for it automatically by running the following
+command with AWS credentials for account `222222222222` configured in your
+shell:
+```code
+$ teleport db configure bootstrap \
+ -c /etc/teleport.yaml \
+ --attach-to-role "example-role"
+```
+
+## AWS IAM trust policy
+
+Modify the external AWS IAM role's trust policy to allow the Teleport Database
+Service's AWS IAM identity as a trusted principal. If you require an external
+ID, provide a condition in the statement that allows the action only when
+the correct external ID is given.
+
+For example, if the Teleport Database Service will be deployed to an EC2
+instance with an attached role `teleport-db-service` in AWS account
+`123456789012`, and you want to require an external ID to assume the external
+role, then the trust policy might look like:
+```json
+{
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Sid": "Statement1",
+ "Effect": "Allow",
+ "Principal": {
+ "AWS": "arn:aws:iam::123456789012:role/teleport-db-service"
+ },
+ "Action": "sts:AssumeRole",
+ "Condition": {
+ "StringEquals": {
+ "sts:ExternalId": "example-external-id"
+ }
+ }
+ }
+ ]
+}
+```
+
+## Next steps
+
+- Get started by [connecting](../guides.mdx) your database.
diff --git a/docs/pages/includes/aws-credentials.mdx b/docs/pages/includes/aws-credentials.mdx
index 0504c784fad7c..eea6a9c44c212 100644
--- a/docs/pages/includes/aws-credentials.mdx
+++ b/docs/pages/includes/aws-credentials.mdx
@@ -8,7 +8,10 @@ Instance Metadata Service method. 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.
+Metadata Service to fetch credentials.
+
+The EC2 instance should be configured to use an EC2 instance profile. For more
+information, see: [Using Instance Profiles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html).
diff --git a/docs/pages/includes/database-access/aws-bootstrap.mdx b/docs/pages/includes/database-access/aws-bootstrap.mdx
index 9b25f7ac7cc53..49c638d50c2fe 100644
--- a/docs/pages/includes/database-access/aws-bootstrap.mdx
+++ b/docs/pages/includes/database-access/aws-bootstrap.mdx
@@ -1,3 +1,5 @@
+{{ attachToRole="TeleportRole" attachToUser="TeleportUser" account="123456789012" }}
+
Teleport can bootstrap IAM permissions for the Database Service based on its
configuration using the `teleport db configure bootstrap` command. You can use
this command in automatic or manual mode:
@@ -8,8 +10,6 @@ this command in automatic or manual mode:
- In manual mode, Teleport will print required IAM policies. You can then create
and attach them manually using the AWS management console.
-Run one of the following commands on your Database Service node:
-
Use this command to bootstrap the permissions automatically when
@@ -17,7 +17,7 @@ Run one of the following commands on your Database Service node:
credentials file).
```code
- $ teleport db configure bootstrap -c /etc/teleport.yaml --attach-to-user TeleportUser
+ $ teleport db configure bootstrap -c /etc/teleport.yaml --attach-to-user {{ attachToUser }}
```
@@ -27,18 +27,43 @@ Run one of the following commands on your Database Service node:
instance with an attached IAM role).
```code
- $ teleport db configure bootstrap -c /etc/teleport.yaml --attach-to-role TeleportRole
+ $ teleport db configure bootstrap -c /etc/teleport.yaml --attach-to-role {{ attachToRole }}
+ ```
+
+
+
+ Use this command to display required IAM policies which you will then create in your AWS console:
+
+ ```code
+ $ teleport db configure bootstrap -c /etc/teleport.yaml --manual --attach-to-user arn:aws:iam::{{ account }}:user/{{ attachToUser }}
```
-
+
Use this command to display required IAM policies which you will then create in your AWS console:
```code
- $ teleport db configure bootstrap -c /etc/teleport.yaml --manual
+ $ teleport db configure bootstrap -c /etc/teleport.yaml --manual --attach-to-role arn:aws:iam::{{ account }}:role/{{ attachToRole }}
```
+
+When `assume_role_arn` is configured for databases or AWS matchers,
+`teleport db configure bootstrap` will determine permissions required for the
+bootstrap target AWS IAM identity using the following logic:
+- When the target does not match `assume_role_arn` in any database resource or
+ AWS matcher in the configuration file, the target is assumed to be the
+ Teleport Database Service's AWS IAM identity and permissions are bootstrapped
+ for all the configured static databases and AWS matchers.
+- When an `--attach-to-role` target matches an `assume_role_arn` setting for
+ static databases or AWS matchers in the configuration file, permissions will
+ be bootstrapped only for those static databases or AWS matchers.
+
+You will need to run the bootstrap command once with the Teleport Database
+Service's IAM identity as the policy attachment target, and once for each AWS
+IAM role that is used for `assume_role_arn`.
+
+
See the full `bootstrap` command
[reference](../../database-access/reference/cli.mdx#teleport-db-configure-bootstrap).
diff --git a/docs/pages/includes/database-access/guides.mdx b/docs/pages/includes/database-access/guides.mdx
index 532000f88a04a..6bae54d8913bd 100644
--- a/docs/pages/includes/database-access/guides.mdx
+++ b/docs/pages/includes/database-access/guides.mdx
@@ -32,3 +32,4 @@
- [GUI clients](../../connect-your-client/gui-clients.mdx): Configure database graphical clients.
- [Dynamic Registration](../../database-access/guides/dynamic-registration.mdx): Register/unregister databases without restarting Teleport.
- [High Availability](../../database-access/guides/ha.mdx): Deploy database access in HA configuration.
+- [AWS Cross-Account Access](../../database-access/guides/aws-cross-account.mdx): Connect AWS databases in external AWS accounts.