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

GNU Emacs as a Comic Book Reader

Tinylisp and Multi-threaded Emacs

Data Visualization with GNU Emacs