Skip to main content

Overview

An AWS resource lets users access AWS APIs through the Formal Connector without giving them credentials for the upstream IAM role. Users continue to send requests to standard AWS service endpoints, such as ec2.us-west-2.amazonaws.com. The Formal Endpoint routes those requests to the Connector, where Formal evaluates policy and records the activity. The Connector then re-signs allowed requests with the IAM identity selected by a Native User. That Native User can select an assumed role or the Connector’s ambient AWS identity. The AWS CLI and SDKs require an access key ID and secret access key to sign requests. However, these client-side credentials can be placeholders. They only produce the initial signature, which the Connector replaces before the request reaches AWS. Set up this request path in five parts. Create the AWS resource, configure the Connector’s AWS identity, and configure a Native User. Then make the resource reachable through a Connector listener and route traffic through the Formal Endpoint. The Connector requires an authenticated Formal identity for this request path. It rejects requests that do not resolve an authenticated Formal identity.

Create an AWS resource

The resource hostname determines which AWS endpoints it covers. Set it to amazonaws.com with port 443 to cover standard service endpoints across all commercial AWS regions:
To limit access to one region, use a narrower suffix such as us-east-1.amazonaws.com. Update the Formal Endpoint network rule to match that suffix. AWS partitions with other domain suffixes require separate resources and network rules.

Configure the Connector’s AWS identity

Before configuring a Native User, give the Connector an AWS region and ambient AWS identity. The Connector loads both through the AWS SDK for Go default configuration. Set AWS_REGION in the Connector’s deployment environment. This is the default region for AWS SDK operations:
On AWS, configure the ambient identity with an ECS task role, an EC2 instance profile, or an EKS IAM role for service accounts (IRSA). The SDK loads these credentials automatically. For other deployments, use environment variables or mount a shared AWS credentials file:
Restart or redeploy the Connector after changing its environment.
The Connector requires credentials that AWS recognizes. Do not use the client-side placeholder credentials configured later in this guide.
Choose AWS IAM to use this ambient identity. Choose AWS IAM Role to assume another role.

Configure the upstream AWS identity

Every signed request must resolve a Native User. Add one after creating the AWS resource. The Control Plane opens the Add Native User wizard automatically: AWS Native User picker with AWS IAM credential methods
  1. Select an AWS IAM authentication method:
    • AWS IAM uses the Connector’s ambient AWS identity.
    • AWS IAM Role assumes the IAM role you specify.
  2. Enter a unique Label, such as aws-role.
  3. Enter a descriptive Username. Generic AWS API Resources do not use it when signing requests.
  4. For AWS IAM Role, enter the role ARN.
  5. Create the Native User.
  6. Configure Default Native User with the Native User’s ID.
AWS IAM Role Native User configuration If you skipped the wizard, open the Resource’s Authentication tab and click Add User. See Select a default Native User for selection examples.
Resources using legacy Native Users store iam or a role ARN in the secret field. See legacy IAM authentication.
In Terraform, use the aws_iam block for the Connector’s ambient identity:
Use aws_iam_role to assume a role:
To select between the two Native Users:
The selection above uses the assumed role for members of aws-admins and the Connector’s ambient identity for everyone else. For an assumed role, both sides of the role assumption must allow it. The Connector’s ambient identity needs permission to call sts:AssumeRole. The upstream role’s trust policy must also trust that identity. The AWS identity used to sign the request defines the maximum permissions available through the resource. The resolved Native User explicitly selects an assumed role or the Connector’s ambient identity. Formal policies can narrow that access further. Create additional Native Users for different AWS access levels. Use the Resource’s default Native User selection to choose one for each Formal identity.
The Connector does not use ambient AWS credentials as a fallback. A signed request fails when no Native User resolves, its configuration is invalid, or its role cannot be assumed.

Make the resource reachable through a Connector

The Formal Endpoint needs a Connector and listener port to which it can forward the intercepted request. A network rule alone does not create this route. In the Control Plane:
  1. Go to InfrastructureConnectors and open the Connector that should proxy the AWS resource.
  2. Open Listeners, select New Listener, enter a Name and available Port, then create the listener. Port 8080 is reserved for Connector health checks.
  3. Open the listener and select New Rule.
  4. Set the rule type to Resource, select the AWS resource, and create the rule.
  5. Confirm the AWS resource appears under the Connector’s Resources tab (Reachable Resources).
See Listeners and Rules for more background. The equivalent Terraform configuration is:
The port can be any available Connector listener port other than 8080.

Route traffic through the Formal Endpoint

The final part of the request path is a Formal Endpoint network rule. Network rules require the transparent proxy to be installed and enabled. Complete the transparent proxy setup before creating the rule. One AWS resource can cover many service hostnames. The rule must preserve each request’s hostname so the Connector knows which AWS service to contact. For a resource scoped to amazonaws.com, create a rule that:
  • Matches amazonaws.com and hosts ending in .amazonaws.com.
  • Selects the AWS resource.
  • Enables Forward to Connector.
Forward to Connector must be enabled. Without it, the Formal Endpoint treats amazonaws.com as the upstream host instead of forwarding the original AWS service hostname to the Connector.
The equivalent CEL configuration is:
Replace <AWS_RESOURCE_NAME> with the name of the AWS resource you created. Create the rule under InfrastructureNetwork Rules, and set its status to Active. New rules default to Draft and do not route traffic until activated.

Configure the AWS CLI

With the resource, Native User, Connector listener, and network rule in place, create a dedicated AWS CLI profile. Give the profile placeholder credentials and configure it to trust the Formal Endpoint’s CA certificate:
Change us-east-1 to the region you normally use. Keep the placeholder credentials as shown: the Formal Endpoint authenticates your Formal identity, while the Connector supplies the AWS identity used upstream. Do not configure an endpoint_url or pass --endpoint-url to individual commands. The AWS CLI must use standard service endpoints. This allows the Formal Endpoint network rule to preserve and route each service hostname. Verify the connection with AWS STS:
The returned ARN should identify the IAM identity selected by the resolved Native User. You can now use the formal-aws profile with other AWS CLI commands. Formal will route, evaluate, and record each request in the same way.

Troubleshoot InvalidClientTokenId

If AWS returns InvalidClientTokenId while using the placeholder credentials, first verify the Formal route rather than replacing the placeholders:
  1. Confirm the transparent proxy is enabled:
  2. Confirm the network rule is Active, selects the AWS resource, and has Forward to Connector enabled.
  3. Confirm you are logged in to the Formal Endpoint with formal auth login.
  4. Confirm the Resource’s default Native User selection selects a Native User for your Formal identity.
  5. Confirm the resource appears under the Connector’s Reachable Resources. After adding a listener rule, allow up to one minute for the Formal Endpoint’s reachability data to refresh. Restart the Formal Endpoint if the mapping still does not update.
  6. On macOS, inspect ~/Library/Logs/Formal/main.log. The message catchall: failed to resolve connector forwarding target means the Formal Endpoint cannot find a Connector listener that reaches the selected resource.
When the transparent proxy is configured to fail open, an unresolved Connector route can pass the placeholder-signed request to AWS. AWS then reports a credential error even though the underlying problem is Formal routing.