sigaws v0.7.2 Sigaws
A library to sign and verify HTTP requests using AWS Signature V4.
Sigaws
does not dictate how you compose and send HTTP requests. You can use
HTTPoison
or any other HTTP client to do that. The signing functions in this
library work with the HTTP request information provided and return an
Elixir map containing signature related parameters/headers. Similarly,
the verification works with the request information and a provider to
perform verification.
Take look at plug_sigaws
, a plug built using this library. This plug can be
added to your API pipeline to protect your API endpoints. It can also be added
to browser pipelines to protect access to web resources using “presigned”
URLs with access expiration.
Examples
Signature to be passed as request headers
url = "http://api.endpoint.host:5000/somthing?a=10&b=20"
headers = %{"header1" => "value1", "header2" => "value2"}
{:ok, %{} = sig_data, _} =
Sigaws.sign_req(url,
headers: headers,
region: "delta-quad",
service: "my-service",
access_key: "some-access-key",
secret: "some-secret")
{:ok, resp} = HTTPoison.get(url, Map.merge(headers, sig_data))
Signature to be passed in query string (“presigned” URL)
url = "http://api.endpoint.host:5000/somthing?a=10&b=20"
{:ok, %{} = sig_data, _} =
Sigaws.sign_url(url,
body: :unsigned,
expires_in: 5 * 60, # 5 minutes
region: "delta-quad",
service: "my-service",
access_key: "some-access-key",
secret: "some-secret")
presigned_url = Sigaws.Util.add_params_to_url(url, sig_data)
Signature Verification
The verification process relies on a provider module that implements
Sigaws.Provider
behavior. The provider is expected to supply the signing
key based on the information present in the context (primarily the access key).
{:ok, %Sigaws.Ctxt{} = ctxt} =
Sigaws.Verify(conn.request_path,
method: conn.method,
params: conn.query_params,
headers: conn.req_headers,
body: get_raw_body(conn),
provider: SigawsQuickStartProvider)
Checkout this
Blog post
that shows how to protect Phoenix built REST APIs using plug_sigaws
and
sigaws_quickstart_provider
Hex packages.
Link to this section Summary
Functions
Sign the given HTTP request and return the signature data to be treated as request headers
Presign the given URL and return the signature data to be treated as query parameters
Verify the signature of the given HTTP request data
Link to this section Functions
sign_req(binary(), keyword()) :: {:ok, map(), map()} | {:error, atom(), binary()}
Sign the given HTTP request and return the signature data to be treated as request headers.
Name | Description |
---|---|
:method | A string value — GET , POST , PUT , etc (defaults to GET ) |
:params | A map of query parameters — merged with the query string in the given url (defaults to an empty map) |
:headers | A map of request headers (defaults to an empty map) |
:body | A string value (use appropriate encoder) or :unsigned or {:content_hash, hash} (defaults to an empty string) |
:signed_at | DateTime in UTC or a string in the form YYYMMDDTHHmmSSZ (defults to current time in UTC) |
:expires_in | Optional expiration in seconds since the signing time |
:region | A string value |
:service | A string value |
:access_key | Access key ID used for signing (defaults to AWS_ACCESS_KEY_ID environment variable) |
:signing_key | A signing key can be provided instead of a secret key |
:secret | Used when signing key is not provided (defaults to AWS_SECRET_ACCESS_KEY environment variable) |
:normalize_path | Refer to Section 5.2 in RFC 3986 (default is false ) |
When there are no errors in signing, this function returns: {:ok, sig_data, info}
The signature data returned in sig_data
map include the following:
X-Amz-Algorithm
X-Amz-Date
X-Amz-SignedHeaders
Authorization
The third item info
is also a map. When the MIX environment is either :dev
or :test
, this info map contains the canonical request (c_req
) and the
string to sign (sts
) computed during the signature generation. In all other
MIX environments (including :prod
) this info will be an empty map.
Error Returns |
---|
{:error, :invalid_input, _} |
{:error, :invalid_data, _} |
sign_url(binary(), keyword()) :: {:ok, map(), map()} | {:error, atom(), binary()}
Presign the given URL and return the signature data to be treated as query parameters.
Refer to sign_req/2
for the named input that can be passed along with the URL.
The returned sig_data
should be merged with any existing query parameters in
the URL while sending the request to the server. (Checkout the examples
at the top.)
When there are no errors in signing, this function returns: {:ok, sig_data, info}
The sig_data
map returned includes the following query parameters:
X-Amz-Algorithm
X-Amz-Content-Sha256
X-Amz-Credential
X-Amz-Date
X-Amz-SignedHeaders
X-Amz-Signature
verify(binary(), keyword()) :: {:ok, Sigaws.Ctxt.t()} | {:error, atom(), binary()}
Verify the signature of the given HTTP request data.
The request data passed should include the signature information either in
query parameters (presigned request) or in the request headers. Presence of
X-Amz-Credential
or X-Amz-Signature
in the query parameters leads to
treatment of the request as a “presigned” request. If not, the signature
data are expected to be in the Authorization
and other headers.
Name | Description |
---|---|
:method | Optional string value — GET , POST , PUT , etc (defaults to GET ) |
:query_string | Optional string value (defaults to empty string) |
:params | Optinal query parameters (defaults to empty map) |
:headers | Optional request headers (defaults to empty map) |
:body | Optional raw body — not decoded values such as JSON (defaults to empty string) |
:provider | Module that implements Sigaws.Provider behavior — required |
:normalize_path | Refer to Section 5.2 in RFC 3986 (default is false ) |
Upon successful signature verification this function returns {:ok, %Sigaws.Ctxt{} = ctxt}
. The returned context Sigaws.Ctx
can be used to make further policy
decisions if desired.
Error Returns |
---|
{:error, :invalid_input, _} |
{:error, :invalid_data, _} |
{:error, :missing_data, _} |
{:error, :verification_failed, ""} |
{:error, :mismatched, "X-Amz-Date"} |