Sigaws, plug_sigaws: signature authentication for phoenix APIs

Just published sigaws, plug_sigaws and sigaws_quickstart_provider packages to Hex. You can use these to enable AWS signature (V4) authentication for your Phoenix API endpoints.

  • The sigaws library has support for both signing and verification of AWS V4 signatures.

  • The sigaws_quickstart_provider is sort of an out-of-the-box simple verification credential provider. The access key IDs and corresponding secrets needed for verification can be defined in a file when you use this provide. You can create your own provider by implementing the Sigaws.Provider behavior.

  • plug_sigaws makes use of sigaws for performing the verification. This plug should be added to your API pipeline. When signature version fails, this plug halts the pipeline.

There is a blog post that goes over how to use this.

Check this out. Any feedback appreciated.

4 Likes

sigaws v0.3.1 - AWS Signature V4 signing and verification library

This release mainly fixes the get-header-value-multiline test failure in
AWS Signature V4 testsuite. The following example shows the API call
with the data from this testcase.

url = "http://example.amazonaws.com/"

headers = %{
  "My-Header1" => "value1\n  value2\n     value3"
}

{:ok, %{} = sig_data, info} =
  Sigaws.sign_req(url,
    headers: headers,
    region: "us-east-1",
    service: "service",
    signed_at: "20150830T123600Z",
    access_key: "AKIDEXAMPLE",
    secret: "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY")

The signature data to be incuded in the HTTP request are returned in sig_data.
This map should be merged with headers map when making the HTTP request.
For example, here is how it would look like when using HTTPoison.

{:ok, resp} = HTTPoison.get(url, Map.merge(headers, sig_data)

BTW, the third item (info) in the tuple returned by Sigaws.sign_req
is a map that contains the canonical request and STS (string to sign)
computed during the signing process.

This link https://hexdocs.pm/sigaws/Sigaws.html
shows couple of examples of using the signing API.

2 Likes

sigaws v0.5.0 - AWS Signature V4 signing and verification library

This release fixes the issue that resulted in failure of the normalize-path tests in the AWS Signature V4 testsuite. (Check section 5.2 in RFC 3986).

OOTB the request path segments with . and .. are not normalized when computing the signature. If this is need by the AWS service you are talking to, you need to explictly pass normalized_path: true option to the Sigaws.sign_req or Sigaws.sign_url functions. The respective function doc are updated.

Only remaining tests from the AWS testsuite that don’t pass yet are:

  • post-vanilla-query-space
  • post-vanilla-query-nonunreserved
  • post-sts-token

Looks like the AWS testsuit result for the first two are wrong. Googling shows that these two are known issues. The third one is yet to be dealt with.

1 Like

sigaws v0.6.0 - AWS Signature V4 signing and verification library

This release enables AWS STS Secure Token Service related tests in the AWS testsuite. Here is the changelog:

v0.6.0

Fixes:

  • Enabled AWS Secure Token tests (post-sts-token). Use the AWS STS service to obtain
    temporary credentials and the corresponding session token. Use the temporary credentials
    to sign. The session token must be included as a request header or query string parameter
    X-Amz-Secure-Token.

    All AWS Signature V4 tests in the testsuite pass. (Exceptions: post-vanilla-query-nonunreserved
    and post-vanilla-query-space. These tests seem to be wrong.)

    AWS STS are supported only in request signing. They are not supported in the
    verifier (plug_sigaws).

    (AWS STS Ref)

Examples:

Signature to be passed as request headers

url = "https://ec2.amazonaws.com/Action=DescribeRegions&Version=2013-10-15"

{:ok, %{} = sig_data, _} =
  Sigaws.sign_req(url, region: "us-east-1", service: "ec2",
    access_key: System.get_env("AWS_ACCESS_KEY_ID"),
    secret:     System.get_env("AWS_SECRET_ACCESS_KEY"))

{:ok, resp} = HTTPoison.get(url, sig_data)

You can pass in request headers to be included in the signature. Make sure to merge the
signature with the headers before sending the request.

The same example is shown here making use of the temporary credentials obtained using
AWS STS Secure Token Service. Assuming the temporary credentials and the session
token are made available in environment variables:

url = "https://ec2.amazonaws.com/Action=DescribeRegions&Version=2013-10-15"
headers = %{"X-Amz-Secure-Token" => System.get_env("AWS_SESSION_TOKEN")}

{:ok, %{} = sig_data, _} =
  Sigaws.sign_req(url, region: "us-east-1", service: "ec2", headers: headers,
    access_key: System.get_env("AWS_ACCESS_KEY_ID"),
    secret:     System.get_env("AWS_SECRET_ACCESS_KEY"))

{:ok, resp} = HTTPoison.get(url, Map.merge(headers, sig_data))

Signature to be passed in query string (“presigned” URL)

url = "https://iam.amazonaws.com/Action=CreateUser&UserName=NewUser&Version=2010-05-08"

{:ok, %{} = sig_data, _} =
  Sigaws.sign_req(url, region: "us-east-1", service: "iam", body: :unsigned,
    access_key: System.get_env("AWS_ACCESS_KEY_ID"),
    secret: System.get_env("AWS_SECRET_ACCESS_KEY"))

presigned_url = Sigaws.Util.add_params_to_url(url, sig_data)

{:ok, resp} = HTTPoison.get(presigned_url)