AWS API Usage in Elisp

Here's some sample elisp code for signing Amazon Web Services (AWS) API requests. The value (first element) returned by (aws-sign4) is used in Authorization header while making a request. When the function is called with an expires value, it returns a URL which can be directly used in a browser.

(require 'aws-sign4)
 
(let ((*aws-credentials*
       (lambda ()
         (values "AKIAIOSFODNN7EXAMPLE" "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"))))
  (aws-sign4 :region "eu-west-1"
             :service "s3"
             :host "s3-eu-west-1.amazonaws.com"
             :path "/some-bucket/some-file"
             ))
 
(let ((*aws-credentials*
       (lambda ()
         (values "AKIAIOSFODNN7EXAMPLE" "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"))))
  (aws-sign4 :region "us-east-1"
             :service "iam"
             :host "iam.amazonaws.com"
             :params '(("Action" . "CreateUser")
               ("UserName" . "NewUser")
               ("Version" . "2010-05-08"))
             :expires 30))
 
;; Convenience function
;; aws-url-retrieve (url &optional auth-header region payload headers service method) 
;; Simple GET URL (default region: "us-east-1")
(aws-url-retrieve "https://iam.amazonaws.com?Action=CreateUser&UserName=NewUser&Version=2010-05-08")
 
;; GET URL with authentication header
(aws-url-retrieve "https://s3.amazonaws.com/" t nil nil `(,(cons "x-amz-content-sha256" (hash ""))))
 
;; DELETE s3 bucket test-axe in region us-east-1
(aws-url-retrieve "https://test-axe.s3.us-east-1.amazonaws.com/" t nil nil
          `(,(cons "x-amz-content-sha256" (hash "")))
          "s3"
          "DELETE")
 
;; POST URL - DynamoDB create table
(aws-url-retrieve "https://dynamodb.us-west-2.amazonaws.com/" t "us-west-2"
          (concat
           "{\"KeySchema\": [{\"KeyType\": \"HASH\",\"AttributeName\": \"Id\"}],"
           "\"TableName\": \"TestTable\",\"AttributeDefinitions\": [{\"AttributeName\": \"Id\",\"AttributeType\": \"S\"}],"
           "\"ProvisionedThroughput\": {\"WriteCapacityUnits\": 5,\"ReadCapacityUnits\": 5}}")
          `(,(cons "content-type" "application/x-amz-json-1.0")
            ,(cons "x-amz-target" "DynamoDB_20120810.CreateTable")
            ))
 
;; POST URL - DynamoDB delete table
(aws-url-retrieve "https://dynamodb.us-west-2.amazonaws.com/" t "us-west-2"
          (concat
           "{\"TableName\": \"TestTable\"}")
          `(,(cons "content-type" "application/x-amz-json-1.0")
            ,(cons "x-amz-target" "DynamoDB_20120810.DeleteTable")
            ))


Code

 

Key points

  • Requests are signed using a timestamp e.g. "20221018T072146Z". A timestamp older than 5 minutes is considered invalid. For testing, you might want to use a hard-coded timestamp using :request-date.
  • Each AWS service might need a different set of mandatory headers. Look up the documentation for the same.
     

List S3 buckets using AXE
 

References

Comments

Popular posts from this blog

HTML Renderer (Emacs)

Mozilla Readability in GNU Emacs

Data Visualization with GNU Emacs