Search…
aws_sign_string
The aws_sign_String statement is used to generate an AWS4-HMAC-SHA256 signature, used as the signature component of the Authorization HTTP header when calling the AWS API.

Syntax

aws_sign_stringvarNameusingsecret_key date region service

Details

The authentication method used by AWS requires the generation of an authorization signature which is derived from a secret key known to the client along with specific elements of the query being made to the API.
This is a fairly involved process and a full step-by-step walkthrough is provided by Amazon on the following pages (these should be read in the order listed below):
The aws_sign_string statement is used to generate the final signature as detailed on the calculate signature page listed above.
Note that in order to use this statement it is necessary to have the following strings available:
    1.
    A string to sign, obtained by following the process creating a string to sign, containing meta-data about the request being made
    2.
    A secret_key, obtained from Amazon which is used by any client application authorising against their API
    3.
    The date associated with the API request, in YYYYMMDD format
    4.
    The AWS region associated with the API request (for example eu-central-1)
    5.
    The AWS service being accessed (for example s3)
The aws_sign_string statement will use these inputs to generate the HMAC-SHA256 signature which is a component of the Authorization header when connecting to the API itself.
The varName parameter is the name of a variable containing the string to sign. After executing aws_sign_string the contents of this same variable will have been updated to the base-16 encoded signature value.
If there are any errors in the string to sign, _date, AWS region or AWS service strings used as input to aws_sign_string then a signature will still be generated, but the AWS API will reject the request. In this case it is necessary to review the process by which these strings were created as per the AWS guide provided above.

Example

The following is an example USE script that implements everything described above.
1
#################################################################
2
# This USE script will download a file from an S3 bucket #
3
# #
4
# It takes three parameters: #
5
# 1) The name of the bucket #
6
# 2) The name of the object to download #
7
# 3) The name of the file to save the downloaded object as #
8
# #
9
# Created: 13th Jan 2018 #
10
# Author: Eddy Deegan #
11
# --------------------------------------------------------------#
12
# NOTES: #
13
# - This script hardcodes the Region as eu-central-1 but this #
14
# can easily be changed or made a parameter as required #
15
#################################################################
16
17
if (${ARGC} != 3) {
18
print This script requires the following parameters:
19
print bucketName objectName saveFilename
20
terminate
21
}
22
23
# Set this to 1 to enable a debug trace output when the script is run
24
var DEBUG = 0
25
26
# This is the text that appears to the left and right of debug headings
27
var banner = ________
28
29
######################################################################
30
# Customer specific values here (these can be encrypted if required) #
31
# #
32
var bucket = "${ARG_1}"
33
var s3_object = "${ARG_2}"
34
var AWS_Region = "eu-central-1"
35
var AWS_Service = "s3"
36
encrypt var access_key = <YOUR ACCESS KEY>
37
encrypt var secret_key = <YOUR SECRET KEY>
38
# #
39
# End customer specific values #
40
######################################################################
41
42
# This is the SHA256 hash of an empty string (required if making a request with no body)
43
var hashed_empty_string = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
44
45
#########################################################################################
46
# SETUP #
47
# Create a number of variables to represent the various components that the steps #
48
# below are going to use in order to construct a correct AWS request #
49
#---------------------------------------------------------------------------------------#
50
# This is the request syntax for retrieving an object from a bucket: #
51
# GET /<ObjectName> HTTP/1.1 #
52
# Host: <BucketName>.s3.amazonaws.com #
53
# Date: date #
54
# Authorization: authorization string #
55
#########################################################################################
56
57
var HTTP_Method = GET
58
var URI = ${s3_object}
59
var query_params # Must have an empty variable for 'no query parameters'
60
var host = ${bucket}.s3-${AWS_Region}.amazonaws.com
61
var date = ${OSI_TIME_UTC}
62
63
# Initialise config variables specific to this script
64
var save_path = "system/extracted"
65
var save_file = ${ARG_3}
66
67
#########################################################################################
68
# STEP 1 #
69
# Create a canonical request as documented at #
70
# at https://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html #
71
#########################################################################################
72
73
# 1a) Canonical Headers string
74
# - This is part of the Canonical Request string which will be generated below.
75
# - The Canonical Headers are a list of all HTTP headers (including values but
76
# with the header names in lowercase) separated by newline characters and in
77
# alphabetical order
78
79
var canonical_headers = "date:${date}${NEWLINE}host:${host}${NEWLINE}x-amz-content-sha256:${hashed_empty_string}${NEWLINE}"
80
if (${DEBUG} == 1) {
81
print ${NEWLINE}${banner} Canonical Headers ${banner}${NEWLINE}${canonical_headers}
82
}
83
84
# 1b) Signed Headers string
85
# - This is a list of the header names that were used to create the Canonical Headers,
86
# separated by a semicolon
87
# - This list MUST be in alphabetical order
88
# - NOTE: There is no trailing newline on this variable (we need to use it both with and without
89
# a newline later so we explicitly add a ${NEWLINE} when we need to)
90
91
var signed_headers = "date;host;x-amz-content-sha256"
92
if (${DEBUG} == 1) {
93
print ${banner} Signed Headers ${banner}${NEWLINE}${signed_headers}${NEWLINE}
94
}
95
96
# 1c) Canonical Request
97
# - The above are now combined to form a Canonical Request, which is created as follows:
98
# - HTTPRequestMethod + '\n' + URI + '\n' + QueryString + '\n' + CanonicalHeaders + '\n' +
99
# SignedHeaders + '\n' + Base16 encoded SHA256 Hash of any body content
100
# - Note that the Canonical Headers are followed by an extra newline (they have one already)
101
102
var canonical_request = "${HTTP_Method}${NEWLINE}/${URI}${NEWLINE}${query_params}${NEWLINE}${canonical_headers}${NEWLINE}${signed_headers}${NEWLINE}${hashed_empty_string}"
103
if (${DEBUG} == 1) {
104
print ${banner} Canonical Request ${banner}${NEWLINE}${canonical_request}${NEWLINE}
105
}
106
107
# 1d) Hash of the Canonical Request
108
# - This is an SHA256 hash of the Canonical Request string
109
110
hash sha256 canonical_request as hashed_canonical_request
111
112
######################################################################################
113
# STEP 2 #
114
# Create a 'string to sign' as documented at #
115
# at https://docs.aws.amazon.com/general/latest/gr/sigv4-create-string-to-sign.html #
116
#------------------------------------------------------------------------------------#
117
# In a nutshell this is the following components separated by newlines: #
118
# 2a) Hash algorithm designation #
119
# 2b) UTC date in YYYYMMDD'T'HHMMSS'Z' format #
120
# 2c) credential scope (date/region/service/"aws4_request") #
121
# 2d) base16-encoded hashed canonical request #
122
######################################################################################
123
124
# Extract the yyyyMMdd from the UTC time
125
match yyyyMMdd "(.{8})" ${date}
126
var yyyyMMdd = ${yyyyMMdd.RESULT}
127
128
var string_to_sign = AWS4-HMAC-SHA256${NEWLINE}${date}${NEWLINE}${yyyyMMdd}/${AWS_Region}/${AWS_Service}/aws4_request${NEWLINE}${hashed_canonical_request}
129
if (${DEBUG} == 1) {
130
print ${banner} String to sign ${banner}${NEWLINE}${string_to_sign}${NEWLINE}
131
}
132
133
######################################################################################
134
# STEP 3 #
135
# Calculate the signature for AWS Signature Version 4 as documented at: #
136
# at https://docs.aws.amazon.com/general/latest/gr/sigv4-calculate-signature.html #
137
# #
138
######################################################################################
139
140
# 3a) Derive a signing key and apply it to the string to sign
141
# Use the secret access key to create the following hash-based auth codes:
142
# a) ksecret (our secret access key)
143
# b) kDate = HMAC("AWS4" + kSecret, Date) NOTE: yyyyMMdd only
144
# c) kRegion = HMAC(kDate, Region)
145
# d) kService = HMAC(kRegion, Service)
146
# e) kSigning = HMAC(kService, "aws4_request")
147
# f) HMAC the string_to_sign with the key derived using steps a - e
148
149
var signature = ${string_to_sign}
150
151
if (${DEBUG} == 1) {
152
print ${banner}Deriving Signing Key using these parameters${banner}${NEWLINE}${secret_key} ${yyyyMMdd} ${AWS_Region} ${AWS_Service}${NEWLINE}${NEWLINE}
153
}
154
155
# The following statement takes care of all the details listed above
156
# Notes:
157
# - The word 'signature' in the statement below is the NAME of a variable and
158
# NOT a reference to its contents
159
# - The contents of this variable are the string to sign, and after the statement
160
# has completed these contents will have been modified to be the authorization
161
# signature for that string
162
#
163
AWS_sign_string signature using ${secret_key} ${yyyyMMdd} ${AWS_Region} ${AWS_Service}
164
165
######################################################################################
166
# STEP 4 #
167
# Add the signing information to the request as documented at: #
168
# https://docs.aws.amazon.com/general/latest/gr/sigv4-add-signature-to-request.html #
169
# #
170
######################################################################################
171
172
var credential_scope = "${yyyyMMdd}/${AWS_Region}/${AWS_Service}/aws4_request"
173
if (${DEBUG} == 1) {
174
print ${banner} Credential Scope ${banner}${NEWLINE}${credential_scope}${NEWLINE}${NEWLINE}
175
}
176
177
var auth_header = "Authorization: AWS4-HMAC-SHA256 Credential=${access_key}/${credential_scope}, SignedHeaders=${signed_headers}, Signature=${signature}"
178
179
if (${DEBUG} == 1) {
180
print ${banner} Authorization Header ${banner}${NEWLINE}${auth_header}${NEWLINE}
181
}
182
set http_header ${auth_header}
183
184
#######################################################
185
# STEP 5 #
186
# Execute the query #
187
#-----------------------------------------------------#
188
# Note that all the headers that were included in the #
189
# signed_headers created in STEP 1 must be set before #
190
# the request is executed #
191
#######################################################
192
193
set http_header "Date: ${date}"
194
set http_header "x-amz-content-sha256: ${hashed_empty_string}"
195
set http_savefile ${save_path}/${save_file}
196
197
set http_progress yes
198
print "Downloading ${host}/${URI}:"
199
http GET https://${host}/${URI}
200
print ${NEWLINE}Done
Copied!
Last modified 2yr ago
Export as PDF
Copy link