Class: Miasma::Contrib::AwsApiCore::SignatureV4
- Includes:
- Bogo::Logger::Helpers
- Defined in:
- lib/miasma/contrib/aws.rb
Overview
AWS signature version 4
Instance Attribute Summary collapse
-
#access_key ⇒ String
readonly
Access key.
- #hmac ⇒ Hmac readonly
-
#region ⇒ String
readonly
Region.
-
#service ⇒ String
readonly
Service.
Instance Method Summary collapse
-
#algorithm ⇒ String
Signature algorithm.
-
#build_canonical_request(http_method, path, opts) ⇒ String
Build the canonical request string used for signing.
-
#canonical_headers(headers) ⇒ String
Build the canonical header string used for signing.
-
#canonical_payload(options) ⇒ String
Build the canonical payload string used for signing.
-
#canonical_query(params) ⇒ String
Build the canonical query string used for signing.
-
#credential_scope ⇒ String
Credential scope for request.
-
#generate(http_method, path, opts) ⇒ String
Generate the signature string for AUTH.
-
#generate_signature(http_method, path, opts) ⇒ String
Generate the signature.
-
#generate_url(http_method, path, opts) ⇒ String
Generate URL with signed params.
-
#hashed_canonical_request(request) ⇒ String
Generate the hash of the canonical request.
-
#initialize(access_key, secret_key, region, service) ⇒ self
constructor
Create new signature generator.
-
#sign_request(request) ⇒ String
Sign the request.
-
#signed_headers(headers) ⇒ String
List of headers included in signature.
Methods inherited from Signature
Constructor Details
#initialize(access_key, secret_key, region, service) ⇒ self
Create new signature generator
178 179 180 181 182 183 |
# File 'lib/miasma/contrib/aws.rb', line 178 def initialize(access_key, secret_key, region, service) @hmac = Hmac.new("sha256", secret_key) @access_key = access_key @region = region @service = service end |
Instance Attribute Details
#access_key ⇒ String (readonly)
Returns access key.
165 166 167 |
# File 'lib/miasma/contrib/aws.rb', line 165 def access_key @access_key end |
#region ⇒ String (readonly)
Returns region.
167 168 169 |
# File 'lib/miasma/contrib/aws.rb', line 167 def region @region end |
#service ⇒ String (readonly)
Returns service.
169 170 171 |
# File 'lib/miasma/contrib/aws.rb', line 169 def service @service end |
Instance Method Details
#algorithm ⇒ String
Returns signature algorithm.
263 264 265 |
# File 'lib/miasma/contrib/aws.rb', line 263 def algorithm "AWS4-HMAC-SHA256" end |
#build_canonical_request(http_method, path, opts) ⇒ String
Build the canonical request string used for signing
291 292 293 294 295 296 297 298 299 300 301 302 303 |
# File 'lib/miasma/contrib/aws.rb', line 291 def build_canonical_request(http_method, path, opts) unless path.start_with?("/") path = "/#{path}" end [ http_method.to_s.upcase, path, canonical_query(opts[:params]), canonical_headers(opts[:headers]), signed_headers(opts[:headers]), canonical_payload(opts), ].join("\n") end |
#canonical_headers(headers) ⇒ String
Build the canonical header string used for signing
321 322 323 324 325 326 327 |
# File 'lib/miasma/contrib/aws.rb', line 321 def canonical_headers(headers) headers ||= {} headers = Hash[headers.sort_by(&:first)] headers.map do |key, value| [key.downcase, value.chomp].join(":") end.join("\n") << "\n" end |
#canonical_payload(options) ⇒ String
Build the canonical payload string used for signing
343 344 345 346 347 348 349 350 351 352 353 354 355 |
# File 'lib/miasma/contrib/aws.rb', line 343 def canonical_payload() body = .fetch(:body, "") if [:json] body = MultiJson.dump([:json]) elsif [:form] body = URI.encode_www_form([:form]) end if body == "UNSIGNED-PAYLOAD" body else hmac.hexdigest_of(body) end end |
#canonical_query(params) ⇒ String
Build the canonical query string used for signing
309 310 311 312 313 314 315 |
# File 'lib/miasma/contrib/aws.rb', line 309 def canonical_query(params) params ||= {} params = Hash[params.sort_by(&:first)] query = params.map do |key, value| "#{safe_escape(key)}=#{safe_escape(value)}" end.join("&") end |
#credential_scope ⇒ String
Returns credential scope for request.
268 269 270 271 272 273 274 275 |
# File 'lib/miasma/contrib/aws.rb', line 268 def credential_scope [ Time.now.utc.strftime("%Y%m%d"), region, service, "aws4_request", ].join("/") end |
#generate(http_method, path, opts) ⇒ String
Generate the signature string for AUTH
191 192 193 194 195 |
# File 'lib/miasma/contrib/aws.rb', line 191 def generate(http_method, path, opts) signature = generate_signature(http_method, path, opts) "#{algorithm} Credential=#{access_key}/#{credential_scope}, " \ "SignedHeaders=#{signed_headers(opts[:headers])}, Signature=#{signature}" end |
#generate_signature(http_method, path, opts) ⇒ String
Generate the signature
226 227 228 229 230 231 232 233 234 235 236 237 |
# File 'lib/miasma/contrib/aws.rb', line 226 def generate_signature(http_method, path, opts) to_sign = [ algorithm, opts.to_smash.fetch(:headers, "X-Amz-Date", AwsApiCore.time_iso8601), credential_scope, hashed_canonical_request( can_req = build_canonical_request(http_method, path, opts) ), ].join("\n") logger.debug("generating signature for `#{to_sign.inspect}`") signature = sign_request(to_sign) end |
#generate_url(http_method, path, opts) ⇒ String
Generate URL with signed params
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/miasma/contrib/aws.rb', line 203 def generate_url(http_method, path, opts) opts[:params].merge!( Smash.new( "X-Amz-SignedHeaders" => signed_headers(opts[:headers]), "X-Amz-Algorithm" => algorithm, "X-Amz-Credential" => "#{access_key}/#{credential_scope}", ) ) signature = generate_signature( http_method, path, opts.merge(:body => "UNSIGNED-PAYLOAD") ) params = opts[:params].merge("X-Amz-Signature" => signature) logger.debug("url generation parameters `#{params.inspect}`") "https://#{opts[:headers]["Host"]}/#{path}?#{canonical_query(params)}" end |
#hashed_canonical_request(request) ⇒ String
Generate the hash of the canonical request
281 282 283 |
# File 'lib/miasma/contrib/aws.rb', line 281 def hashed_canonical_request(request) hmac.hexdigest_of(request) end |
#sign_request(request) ⇒ String
Sign the request
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
# File 'lib/miasma/contrib/aws.rb', line 243 def sign_request(request) key = hmac.sign( "aws4_request", hmac.sign( service, hmac.sign( region, hmac.sign( Time.now.utc.strftime("%Y%m%d"), "AWS4#{hmac.key}" ) ) ) ) signature = hmac.hex_sign(request, key) logger.debug("generated signature `#{signature.inspect}`") signature end |
#signed_headers(headers) ⇒ String
List of headers included in signature
333 334 335 336 337 |
# File 'lib/miasma/contrib/aws.rb', line 333 def signed_headers(headers) headers ||= {} headers.sort_by(&:first).map(&:first). map(&:downcase).join(";") end |