> ## Documentation Index
> Fetch the complete documentation index at: https://namespace.so/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Workload Federation with AWS

Namespace relies on Workload Identity Federation to allow Namespace to interact
with different systems, instead of relying on pre-shared keys which can be more
easily compromised.

## Accessing Namespace resources from AWS

Identity Federation with AWS allows your AWS-based workloads to identify
themselves to Namespace using short-lived secure credentials.

To enable this federation, we rely on [AWS Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/getting-started-with-identity-pools.html) to establish a [OpenID Connect provider](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html), and then we configure your Namespace workspace to trust
that AWS Cognito Identity Pool.

<Steps titleSize="h3">
  <Step title="Create an AWS Cognito Identity Pool">
    1. Open the **Cognito** console at [https://console.aws.amazon.com/cognito/](https://console.aws.amazon.com/cognito/) and click on **Create identity pool** in the section **Identity pools**.
    2. Check the options **Authenticated Access** and **Custom developer provider**.
    3. Select an existing IAM role to use with Cognito, or create a new one.

           <Info>
             AWS requires you to associate an IAM role with the identity pool. The role can have minimal permissions as the pool will be used to access Namespace resources, not AWS resources.
           </Info>
    4. Under **Developer provider name** enter `namespace.so`.
    5. Pick an arbitrary name for the identity pool and create the identity pool.

    AWS will print the ID of the new identity pool. It's of the format
    `{region}:{guid}`.
  </Step>

  <Step title="Establish a trust relationship in Namespace">
    1. Open the [**Dashboard**](https://cloud.namespace.so/workspace/settings) and copy your Workspace ID.
    2. Use the [CLI](/docs/reference/cli/installation) to establish the trust relationship:

       ```bash theme={null}
       nsc auth trust-aws-cognito-identity-pool \
           --aws_region <region> \
           --identity_pool <guid> \
           --tenant_id <workspace-id>
       ```
  </Step>

  <Step title="Obtain Namespace credentials from a AWS workload">
    Using an IAM role with permissions to access the Cognito Identity Pool, you can obtain Namespace credentials as follows:

    ```bash theme={null}
    nsc auth exchange-aws-cognito-token \
        --aws_region <region> \
        --identity_pool <guid> \
        --tenant_id <workspace-id>
    ```

    This command should succeed with the name of workspace you've signed in to. It
    stores a short-lived token that will be used automatically in subsequent calls.

    When testing locally, you can select an AWS profile by passing `--aws_profile`.
  </Step>
</Steps>

## Accessing Namespace resources using STS Web Identity

AWS STS Web Identity Federation is a simpler alternative to Cognito that issues
short-lived OIDC tokens directly from your AWS account, without requiring an
identity pool. Any AWS workload with an IAM role (EC2, Lambda, ECS, etc.) can
use this approach.

<Steps titleSize="h3">
  <Step title="Enable outbound web identity federation">
    This is a one-time setting per AWS account. It enables STS to issue OIDC tokens
    on behalf of your AWS principals.

    ```bash theme={null}
    export AWS_PROFILE=<your-aws-profile>

    aws --profile "$AWS_PROFILE" iam enable-outbound-web-identity-federation
    ```

    Note the `IssuerIdentifier` in the response. You can retrieve it again at any time:

    ```bash theme={null}
    aws --profile "$AWS_PROFILE" iam get-outbound-web-identity-federation-info
    ```
  </Step>

  <Step title="Grant your IAM role permission to call GetWebIdentityToken">
    Your workload's IAM role needs permission to obtain tokens. Add an inline policy
    to the role:

    ```bash theme={null}
    aws --profile "$AWS_PROFILE" iam put-role-policy \
      --role-name <your-workload-role> \
      --policy-name allow-get-web-identity-token \
      --policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
          "Effect": "Allow",
          "Action": "sts:GetWebIdentityToken",
          "Resource": "*"
        }]
      }'
    ```
  </Step>

  <Step title="Establish a trust relationship in Namespace">
    Use the issuer URL and account ID to configure Namespace to trust tokens from
    your AWS account:

    ```bash theme={null}
    ISSUER=$(aws --profile "$AWS_PROFILE" iam get-outbound-web-identity-federation-info \
      --query IssuerIdentifier --output text)
    ACCOUNT=$(aws --profile "$AWS_PROFILE" sts get-caller-identity --query Account --output text)

    nsc auth trust-relationships add \
      --issuer "$ISSUER" \
      --subject-match "arn:aws:iam::${ACCOUNT}:role/<your-workload-role>"
    ```

    To trust any role in the account, use a wildcard:

    ```bash theme={null}
      --subject-match "arn:aws:iam::${ACCOUNT}:role/*"
    ```
  </Step>

  <Step title="Authenticate from your workload">
    From within your AWS workload (no additional instance setup required — the AWS
    CLI picks up credentials from the instance metadata automatically):

    ```bash theme={null}
    TOKEN=$(aws sts get-web-identity-token \
      --audience https://federation.namespaceapis.com \
      --signing-algorithm ES384 \
      --region us-east-1 \
      --query WebIdentityToken --output text)

    nsc auth exchange-oidc-token --token "$TOKEN"
    ```

    `--audience` and `--signing-algorithm` are required by the API. Both `ES384`
    (ECDSA P-384) and `RS256` are accepted; `ES384` is recommended. `--region`
    must point to a regional STS endpoint — the global endpoint does not support
    this call. `--query WebIdentityToken --output text` is a CLI convenience to
    extract just the token string from the JSON response.
  </Step>
</Steps>

## Accessing AWS resources from Namespace

Identity Federation with AWS allows your Namespace workloads to identify
themselves to AWS using short-lived secure credentials.

To enable this federation, create an IAM OIDC identity provider for Namespace federation in the AWS Management Console.

<Steps titleSize="h3">
  <Step title="Create a Namespace OIDC identity provider">
    1. Open the IAM console at [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/) and in the
       navigation pane, choose **Identity providers**, and click **Add provider**.
    2. Select **OpenID Connect** as a **Provider type** and fill in `https://federation.namespaceapis.com` as the **Provider URL**.

           <Info>
             The expected thumbprint is `a053375bfe84e8b748782c7cee15827a6af5a405`.
           </Info>
    3. For **Audience**, type `sts.amazonaws.com`.
    4. Verify the information that you have provided. When you are done choose Add provider.

    Note down the ARN of your newly created identity provider. It is of the form `arn:aws:iam::<aws-account-id>:oidc-provider/federation.namespaceapis.com`.
  </Step>

  <Step title="Create a IAM role for federated access">
    1. Open the IAM console at [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/).
    2. In the navigation pane, choose **Roles** and click **Create role**.
    3. Select the **Custom trust policy** role type, using the following JSON template as the policy:

       ```json theme={null}
       {
       	"Version": "2012-10-17",
       	"Statement": [
       		{
       			"Effect": "Allow",
       			"Action": "sts:AssumeRoleWithWebIdentity",
       			"Principal": {
       				"Federated": "<identity-provider-arn>"
       			},
       			"Condition": {
       				"StringLike": {
       					"federation.namespaceapis.com:aud": "sts.amazonaws.com",
       					"federation.namespaceapis.com:sub": "<workspace-id>/*"
       				}
       			}
       		}
       	]
       }
       ```

       Replace `<identity-provider-arn>` with the ARN of the new identity provider, and `<workspace-id>` with your complete Namespace workspace identifier (found in the [**Dashboard**](https://cloud.namespace.so/workspace/settings)). The workspace ID includes the `tenant_` prefix; for example, `tenant_123456789ab`.
    4. Choose **Next** and add the desired permissions policies for your federated workloads.
  </Step>

  <Step title="Accessing AWS resources from a Namespace workload">
    1. Obtain AWS credentials.

       ```bash theme={null}
       nsc aws assume-role --role_arn <role-arn> --write_env aws.env
       ```

       In this command, `<role-arn>` is the ARN of the IAM role created for federated access.
    2. Apply the obtained credentials.

       ```bash theme={null}
       source aws.env
       ```
    3. Access AWS resources.

       ```bash theme={null}
       aws s3 cp test.txt s3://amzn-s3-demo-bucket/test2.txt
       ```
  </Step>
</Steps>

## Pulling private ECR images on instances

When creating an instance through the Compute API, you can pull private images from
[Amazon ECR](https://docs.aws.amazon.com/AmazonECR/latest/userguide/what-is-ecr.html) by having Namespace
federate with AWS to obtain a [ECR authorization token](https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_GetAuthorizationToken.html) automatically.

The resolved token is used both to pull the instance's own container images and is written into the
guest's Docker/nerdctl configuration (`/root/.docker/config.json`), so subsequent `docker pull` and
`nerdctl pull` commands from inside the instance authenticate to the same registries.

This builds on the federated IAM role created in [Accessing AWS resources from Namespace](#accessing-aws-resources-from-namespace).

<Steps titleSize="h3">
  <Step title="Grant the IAM role permission to pull from ECR">
    Attach a policy to the federated role allowing it to obtain an authorization token and pull images:

    ```bash theme={null}
    aws iam put-role-policy \
      --role-name <your-federated-role> \
      --policy-name allow-ecr-pull \
      --policy-document '{
        "Version": "2012-10-17",
        "Statement": [{
          "Effect": "Allow",
          "Action": [
            "ecr:GetAuthorizationToken",
            "ecr:BatchCheckLayerAvailability",
            "ecr:GetDownloadUrlForLayer",
            "ecr:BatchGetImage"
          ],
          "Resource": "*"
        }]
      }'
    ```

    <Info>
      `ecr:GetAuthorizationToken` must be granted on `"Resource": "*"`. The remaining actions may be scoped to specific repository ARNs.
    </Info>
  </Step>

  <Step title="Reference the registry when creating an instance">
    Set `additional_registries` on the `CreateInstance` request, keyed by your ECR host
    (`<account-id>.dkr.ecr.<region>.amazonaws.com`). Namespace infers the AWS region from this host,
    assumes the role via the trust relationship configured above, and uses the resulting token to pull
    the image:

    ```json theme={null}
    {
    	"containers": [
    		{
    			"name": "app",
    			"image_ref": "<account-id>.dkr.ecr.<region>.amazonaws.com/my-repo:latest"
    		}
    	],
    	"additional_registries": {
    		"<account-id>.dkr.ecr.<region>.amazonaws.com": {
    			"authentication": {
    				"ecr_token_from_aws_federation": {
    					"role_arn": "arn:aws:iam::<aws-account-id>:role/<your-federated-role>"
    				}
    			}
    		}
    	}
    }
    ```

    The registry host key must exactly match the ECR host in `image_ref`. See the [`AdditionalRegistry.Authenticator`](https://buf.build/namespace/cloud/docs/main%3Anamespace.cloud.compute.v1beta#namespace.cloud.compute.v1beta.AdditionalRegistry.Authenticator)
    reference for all available authentication options.
  </Step>
</Steps>
