Skip to content

Managed secret providers

AWS

SigV4 credentials and the boto3 bridge.

AWS managed secrets carry extra structure because Alter computes the full AWS Signature Version 4 (SigV4) signature per outgoing request. One stored AWS access key works against every AWS service — S3, Lambda, DynamoDB, Bedrock, CloudWatch — without any per-service configuration.

PropertyValue
Provider slugaws
Credential typeSigV4
Required credentialsAccess Key ID + Secret Access Key
Region / serviceAuto-detected from the request URL
  1. In AWS IAM, create or pick a user with least-privilege permissions and generate an access key.
  2. In the developer portal: Managed Secrets → Add Provider → AWS.
  3. Paste Access Key ID and Secret Access Key. No region or service configuration is needed.
  4. Save. A grant_id is returned.

Never use root account access keys. Always scope IAM permissions to the routes the application needs.

Calling AWS — app.request() (Python and TypeScript)

Section titled “Calling AWS — app.request() (Python and TypeScript)”

The default path. Pass the standard AWS hostname; Alter parses region and service from the URL and signs the request.

from alter_sdk import App, HttpMethod
async with App(api_key=os.environ["ALTER_API_KEY"]) as app:
# S3
r = await app.request(
HttpMethod.GET,
"https://s3.us-east-1.amazonaws.com/my-bucket/my-key",
grant_id=AWS_GRANT_ID,
)
# Bedrock — same credential, different service and region
r = await app.request(
HttpMethod.POST,
"https://bedrock-runtime.us-west-2.amazonaws.com/model/anthropic.claude-sonnet-4-6/invoke",
grant_id=AWS_GRANT_ID,
json={"prompt": "Hello"},
)
# Lambda
r = await app.request(
HttpMethod.POST,
"https://lambda.eu-west-1.amazonaws.com/2015-03-31/functions/my-func/invocations",
grant_id=AWS_GRANT_ID,
json={"key": "value"},
)
import { App, HttpMethod } from "@alter-ai/alter-sdk";
const app = new App({ apiKey: process.env.ALTER_API_KEY! });
try {
// S3
const s3 = await app.request(
HttpMethod.GET,
"https://s3.us-east-1.amazonaws.com/my-bucket/my-key",
{ grantId: AWS_GRANT_ID },
);
// Bedrock
const bedrock = await app.request(
HttpMethod.POST,
"https://bedrock-runtime.us-west-2.amazonaws.com/model/anthropic.claude-sonnet-4-6/invoke",
{ grantId: AWS_GRANT_ID, json: { prompt: "Hello" } },
);
} finally {
await app.close();
}

No AWS SDK dependency. SigV4 is computed by the Alter SDK using standard cryptographic libraries.

Calling AWS — boto3_client() (Python only)

Section titled “Calling AWS — boto3_client() (Python only)”

For applications that prefer the native boto3 API (response parsing, pagination, botocore.exceptions.ClientError):

Terminal window
pip install 'alter-sdk[aws]'
import asyncio
from alter_sdk import App
async def main():
async with App(api_key=os.environ["ALTER_API_KEY"]) as app:
s3 = await app.boto3_client(
"s3",
grant_id=AWS_GRANT_ID,
region_name="us-east-1",
reason="Listing objects for data pipeline",
)
# boto3 methods are synchronous — run in a thread from async code
resp = await asyncio.to_thread(
s3.list_objects_v2, Bucket="my-bucket", MaxKeys=10,
)
for obj in resp.get("Contents", []):
print(obj["Key"], obj["Size"])
# Same credential, different service
dynamo = await app.boto3_client("dynamodb", grant_id=AWS_GRANT_ID, region_name="us-east-1")
await asyncio.to_thread(
dynamo.put_item, TableName="MyTable", Item={"pk": {"S": "k1"}},
)
asyncio.run(main())

Every boto3 call routes through Alter — credential retrieval, SigV4 signing, policy enforcement, audit logging all happen on every call.

boto3_client() parameters:

ParameterTypeDefaultDescription
service_namestrAWS service (s3, dynamodb, bedrock-runtime, …).
grant_idstrThe AWS grant.
region_namestr | NoneNone — boto3 default (us-east-1)AWS region.
timeoutfloat | NoneNone — client timeout + 5s bufferTotal wall-clock timeout per call (seconds), covering token retrieval and the HTTP request.
reasonstr | NoneNoneAudit reason applied to every call from this client.
contextdict[str, str] | NoneNonePer-client audit context.

Error handling matches native boto3 (botocore.exceptions.ClientError for AWS errors like NoSuchBucket, AccessDenied; AlterSDKError for Alter-side issues).

For multi-GB responses (e.g., s3.get_object on large files), use app.request() with httpx streaming instead — boto3_client() buffers responses in memory.

Alter auto-detects region and service from these AWS hostname formats:

PatternExampleDetected
Standards3.us-east-1.amazonaws.comservice s3, region us-east-1
Hyphenated servicebedrock-runtime.us-west-2.amazonaws.comservice bedrock-runtime, region us-west-2
S3 virtual-hostedmy-bucket.s3.us-west-2.amazonaws.comservice s3, region us-west-2
PrivateLink (regional)vpce-xxx.monitoring.us-east-2.vpce.amazonaws.comservice monitoring, region us-east-2
PrivateLink (zonal)vpce-xxx-us-east-2c.monitoring.us-east-2.vpce.amazonaws.comservice monitoring, region us-east-2
GovClouds3.us-gov-west-1.amazonaws.comservice s3, region us-gov-west-1

For non-AWS custom domains (LocalStack, custom proxies), region and service cannot be auto-detected. Contact support to wire explicit configuration.

When the AWS access key rotates: regenerate in IAM, then update the stored value in the portal under Managed Secrets → AWS → Update credential. Every existing grant_id keeps working with the new key.