Skip to content
/ erliam Public

erlang library for caching credentials and signing AWS API requests

License

Notifications You must be signed in to change notification settings

AdRoll/erliam

Folders and files

NameName
Last commit message
Last commit date

Latest commit

e419337 · Apr 2, 2024

History

78 Commits
Feb 3, 2023
Mar 6, 2023
Nov 24, 2020
Apr 7, 2022
Mar 31, 2017
Apr 22, 2020
Oct 10, 2017
Dec 22, 2021
Feb 23, 2021
Dec 22, 2021
Feb 23, 2021
Apr 2, 2024
May 13, 2019
Mar 1, 2022
Dec 22, 2021

Repository files navigation

erliam

erlang library for caching credentials and signing AWS API requests.

usage

  1. Add erliam to application dependencies or do application:start(erliam).

  2. Call erliam:credentials() to obtain latest cached credentials (stored in ets and automatically refreshed before expiry).

  3. Call awsv4:headers(Credentials, Parameters) to obtain awsv4-signed request headers to use in AWS API calls.

If not using instance metadata, set aws_access_key and aws_secret_key in erliam application environment to your long-term credentials; these will be used to obtain a session token periodically.

example

Fetch an object from S3

> application:start(erliam).
> QueryParams = #{"prefix" => "some/prefix/",
                  "delimiter" => "/",
                  "list-type" => "2",
                  "encoding-type" => "url"}.
> Headers = awsv4:headers(erliam:credentials(),
                          #{service => "s3",
                            region => "us-west-2",
                            host => "bucketname.s3.amazonaws.com",
                            path => "/",
                            query_params => QueryParams}).
> httpc:request(get, {lists:flatten("https://bucketname.s3.amazonaws.com/?" ++
                                    awsv4:canonical_query(QueryParams)), Headers}, [], []).

{ok, {{"HTTP/1.1", 200, "OK"},
 [{"date", "Fri, 02 Jun 2017 23:26:21 GMT"},
  {"server", "AmazonS3"},
  {"content-length", "496"},
  {"content-type", "application/xml"},
  {"x-amz-id-2", "SOME-ID"},
  {"x-amz-request-id", "SOME-OTHER-ID"},
  {"x-amz-bucket-region", "us-west-2"}],
 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<ListBucketResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>bucketname</Name>..."}}

Encrypt plaintext using KMS

> application:start(erliam).
> QueryParams = #{}.
> KeyId = <<"xxxx-xxxx-xxxx-xxxx-xxxxxxxxxx">>
> RequestBody = jiffy:encode(#{<<"EncryptionContext">> => #{<<"application">> => <<"thing encryptor">>},
                               <<"KeyId">> => KeyId,
                               <<"Plaintext">> => base64:encode(<<"setec astronomy">>)}).
> SignedHeaders = #{"content-type" => "application/x-amz-json-1.1"}.
> Headers = awsv4:headers(erliam:credentials(),
                          #{service => "kms",
                            target_api => "TrentService.Encrypt",
                            method => "POST",
                            region => "us-east-1",
                            query_params => QueryParams,
                            signed_headers => SignedHeaders},
                          RequestBody).
> httpc:request(post, {lists:flatten(["https://kms.us-east-1.amazonaws.com", "/?",
                                      awsv4:canonical_query(QueryParams)]),
                       Headers,
                       proplists:get_value("content-type", Headers), RequestBody}, [], []).

{ok, {{"HTTP/1.1", 200, "OK"},
     [{"content-length", "307"},
      {"content-type", "application/x-amz-json-1.1"},
      {"x-amzn-requestid", "xxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"}],
     "{\"CiphertextBlob\":\"B64ENCODED CIPHERTEXT\",\"KeyId\":\"KEY ARN\"}"}}