Amazonite AWS SDK
Amazonite is an unofficial AWS SDK for Crystal, generated directly from AWS's own API models so
service coverage tracks AWS rather than a hand-maintained subset. It resolves credentials the same
way the official SDKs do (env vars, profiles, SSO, ECS, EC2 instance metadata) and refreshes
temporary credentials automatically, so a Client.new behaves the way you'd expect coming from
boto3 or the AWS SDK for JS/Go/etc.
API documentation is generated with crystal docs and published on every push to master.
Amazonite is not affiliated with, endorsed by, or sponsored by Amazon.com, Inc. or its affiliates. "AWS" and "Amazon" are trademarks of Amazon.com, Inc. or its affiliates.
- Typed clients and models generated from AWS's own API definitions, not maintained by hand
- Automatic credential resolution across env vars, profiles, SSO, ECS, and EC2 instance metadata
- Automatic refresh of temporary credentials (AssumeRole, SSO, ECS, EC2) as they near expiry
- 15 AWS services supported today, with integration tests for each - see Supported APIs
- API docs regenerated and published on every push to
master
Contents
Usage
Here's an example that creates a table in DynamoDB:
require "amazonite/dynamodb"
private alias DB = Amazonite::DynamoDB
model = DB::CreateTableInput.new(
"Music",
[
DB::AttributeDefinition.new("Artist", DB::ScalarAttributeType::S),
DB::AttributeDefinition.new("SongTitle", DB::ScalarAttributeType::S)
],
[
DB::KeySchemaElement.new("Artist", DB::KeyType::Hash),
DB::KeySchemaElement.new("SongTitle", DB::KeyType::Range)
],
provisioned_throughput: DB::ProvisionedThroughput.new(10, 5),
)
client = DB::Client.new # resolves credentials from the default provider chain
response = client.create_table(model)
puts response.http.status_code # 200
result = response.result
puts result.table_description.try &.table_name # Music
puts result.table_description.try &.attribute_definitions.try &.[0].attribute_name # Artist
Output:
200
Music
Artist
Credentials
Amazonite follows the same credential provider chain as the official AWS SDKs, so you generally don't
need to configure credentials yourself. Client.new/Config.new accept access_key_id/secret_access_key/region
directly, but if you leave them out, credentials are resolved automatically from the following sources, in order:
- Environment variables (
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKEN) - A static profile in
~/.aws/credentials(viaAWS_PROFILEorConfig.new(profile: "...")) role_arn/source_profilechaining in~/.aws/config(calls STSAssumeRole)- An SSO cached token from
aws sso login(calls SSOGetRoleCredentials) - ECS/Fargate container credentials (
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI/_FULL_URI) - EC2 instance metadata (IMDSv2) - set
AWS_EC2_METADATA_DISABLED=trueto skip this check on non-EC2 hosts (e.g. local development, CI) so it doesn't add latency to every client
Temporary credentials (from AssumeRole, SSO, ECS, or EC2) are refreshed automatically as they near expiry.
Supported APIs
| Name | Supported? |Integration Tests | Notes | | ------------- | :-------------: | :---------------: |------------- | | DynamoDB | ✅ |✅ | | | SSM | ✅ |✅ | | | SQS | ✅ |✅ | | | KMS | ✅ |✅ | | | Secrets Manager | ✅ |✅ | | | Lambda | ✅ |✅ | InvokeWithResponseStream isn't generated - uses event-stream framing, not a plain request/response | | SNS | ✅ |✅ | | | IAM | ✅ |✅ | | | CloudWatch | ✅ |✅ | | | STS | ✅ |✅ | | | CloudFormation | ✅ |✅ | | | API Gateway | ✅ |✅ | | | EventBridge | ✅ |✅ | | | CloudWatch Logs | ✅ |✅ | GetLogObject and StartLiveTail aren't generated - use event-stream framing, not a plain request/response | | Kinesis | ✅ |✅ | SubscribeToShard isn't generated - uses event-stream framing, not a plain request/response | | S3 | 🚫 | 🚫 | Consider using awscr-s3 |
For example usage, please look at the integration tests. If you need an API that is not listed here, please open an issue or pull request with the generated code.
Installation
-
Add the dependency to your
shard.yml:dependencies: amazonite: github: rjnienaber/amazonite -
Run
shards install
Development
Once you've cloned the repo, have a look at the scripts directory for some scripts that help with development. Some of them use the excellent watchexec tool to watch for changes.
./scripts/watch_specs.sh- watches for code changes and runs the specs
./scripts/watch_codegen.sh- watches for code changes and regenerates the code for apis
./scripts/watch_integration.cr- watches for code changes and executes integration tests
./scripts/regenerate.sh- regenerates every service and syncs the result from
tmp/intosrc/
- regenerates every service and syncs the result from
codegen/codegen.cr (built as bin/codegen, or run directly with crystal run codegen/codegen.cr --) accepts flags to point it at a different api-models-aws checkout, change the output directory, control log verbosity, and restrict which services/protocols get generated. Run it with -h for the full list, e.g.:
crystal run codegen/codegen.cr -- --models-dir ../api-models-aws --output-dir tmp --service dynamodb --service ssm --log-level debug
Releases
The Update AWS models workflow runs nightly. It pulls the latest
api-models-aws, regenerates every service and checks whether anything changed
beyond each module's VERSION constant (which tracks the submodule commit and so moves on every bump, service change or
not). If nothing did, the run stops there. Otherwise it pushes the regenerated code to automated/aws-models, runs the
full CI suite against that branch and - only if it passes - fast-forwards master, bumps the patch version in
shard.yml and tags a release, so the new version is picked up by the shard directories.
Contributing
- Fork it (https://github.com/rjnienaber/amazonite/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
Contributors
- Richard Nienaber - creator and maintainer