class Akamai::Edgegrid::HTTP

Akamai::Edgegrid::HTTP {OPEN} client

Akamai::Edgegrid::HTTP provides a subclass of Net::HTTP that adds EdgeGrid authentication support as specified at developer.akamai.com/introduction/Client_Auth.html

Example:

>> require 'akamai/edgegrid'
>> require 'net/http'
>> require 'uri'
>> require 'json'

>> baseuri = URI('https://akaa-xxxxxxxxxxxx.luna.akamaiapis.net/')
>> http = Akamai::Edgegrid::HTTP.new(address, port)
>> http.setup_edgegrid(
      :client_token => 'ccccccccc',
      :client_secret => 'ssssssssssssssssss',
      :access_token => 'aaaaaaaaaaaaaa'
   )
>> request = Net::HTTP::Get.new URI.join(
      baseuri.to_s, '/diagnostic-tools/v1/locations'
   ).to_s
>> response = http.request(request)
>> puts JSON.parse(response.body)['locations'][0]
=> "Hongkong, Hong Kong

Attributes

host[RW]
section[RW]

Public Class Methods

eg_timestamp() click to toggle source

returns the current time in the format understood by Edgegrid

# File lib/akamai/edgegrid.rb, line 161
def self.eg_timestamp()
  return Time.now.utc.strftime('%Y%m%dT%H:%M:%S+0000')
end
new(address, port) click to toggle source

Creates a new Akamai::Edgegrid::HTTP object (takes same options as Net::HTTP)

Calls superclass method
# File lib/akamai/edgegrid.rb, line 91
def initialize(address, port)
  @host = address
  super(address, port)
  if port == 80
    @use_ssl = false
  else
    @use_ssl = true
    @verify_mode = OpenSSL::SSL::VERIFY_PEER
  end
end
new_nonce() click to toggle source

returns a new nonce (unique identifier)

# File lib/akamai/edgegrid.rb, line 166
def self.new_nonce()
  return SecureRandom.uuid
end

Private Class Methods

base64_hmac_sha256(data, key) click to toggle source
# File lib/akamai/edgegrid.rb, line 76
def self.base64_hmac_sha256(data, key)
  return Base64.encode64(
    OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, key, data)
  ).strip()
end
base64_sha256(data) click to toggle source
# File lib/akamai/edgegrid.rb, line 82
def self.base64_sha256(data)
  return Base64.encode64(
      OpenSSL::Digest::SHA256.new.digest(data)
  ).strip()
end

Public Instance Methods

canonicalize_headers(request) click to toggle source

Returns the @headers_to_sign in normalized form

# File lib/akamai/edgegrid.rb, line 110
def canonicalize_headers(request)
  return @headers_to_sign.select { |header| 
    request.key?(header) 
  }.map { |header|
    "#{header.downcase}:#{request[header].strip.gsub(%r{\s+}, ' ')}"
  }.join("\t")
end
make_auth_header(request, timestamp, nonce) click to toggle source

Returns the computed Authorization header for the given request, timestamp and nonce

# File lib/akamai/edgegrid.rb, line 218
def make_auth_header(request, timestamp, nonce)
  auth_header = "EG1-HMAC-SHA256 " + [
    "client_token" => @client_token,
    "access_token" => @access_token,
    "timestamp" => timestamp,
    "nonce" => nonce
  ].map {|kvp|
    kvp.keys.map { |k| k + "=" + kvp[k] }
  }.join(';') + ';'

  @log.debug("unsigned authorization header: #{auth_header}")

  signed_auth_header = auth_header + 'signature=' + sign_request(
    request, timestamp, auth_header
  )
  @log.debug("signed authorization header: #{signed_auth_header}")

  return signed_auth_header
end
make_content_hash(request) click to toggle source

Returns a hash of the HTTP POST body

# File lib/akamai/edgegrid.rb, line 119
def make_content_hash(request) 
  if request.method == 'POST' and request.body and request.body.length > 0
    body = request.body
    if body.length > @max_body
      @log.debug("data length #{body.length} is larger than maximum #{@max_body}")
      body = body[0..@max_body-1]
      @log.debug("data truncated to #{body.length} for computing the hash")
    end

    return self.class.base64_sha256(body)
  end
  return ""
end
make_data_to_sign(request, auth_header) click to toggle source

Returns a string with all data that will be signed

# File lib/akamai/edgegrid.rb, line 134
def make_data_to_sign(request, auth_header)
  url = URI(request.path)
  data_to_sign = [
    request.method,
    url.scheme,
    request.key?('host') ? request['host'] : url.host,
    url.request_uri,
    canonicalize_headers(request),
    make_content_hash(request),
    auth_header
  ].join("\t")

  @log.debug("data to sign: #{data_to_sign.gsub("\t", '\\t')}")
  return data_to_sign
end
make_signing_key(timestamp) click to toggle source

Creates a signing key based on the secret and timestamp

# File lib/akamai/edgegrid.rb, line 103
def make_signing_key(timestamp)
  signing_key = self.class.base64_hmac_sha256(timestamp, @client_secret)
  @log.debug("signing key: #{signing_key}")
  return signing_key
end
orig_request(req, body=nil, &block)
Alias for: request
request(req, body=nil, &block) click to toggle source

Same as Net::HTTP.request but with 'Authorization' header for {OPEN} Edgegrid added to the given request

# File lib/akamai/edgegrid.rb, line 240
def request(req, body=nil, &block)
  timestamp = self.class.eg_timestamp()
  nonce = self.class.new_nonce()
  req['Authorization'] = make_auth_header(req, timestamp, nonce)
  return orig_request(req, body, &block)
end
Also aliased as: orig_request
setup_edgegrid(opts) click to toggle source

Configures Akamai::Edgegrid::HTTP for use

Options

  • :client_token - Client Token from “Credentials” Manage API UI

  • :client_secret - Client Secret from “Credentials” Manage API UI

  • :access_token - Access Token from “Authorizations” Manage API UI

  • :headers_to_sign - List of headers (in order) that will be signed. This info is provided by individual APIs (default [])

  • :max_body - Maximum POST body size accepted. This info is provided by individual APIs (default 2048)

  • :debug - Enable extra logging (default 'false')

# File lib/akamai/edgegrid.rb, line 179
def setup_edgegrid(opts)
  @client_token = opts[:client_token]
  @client_secret = opts[:client_secret]
  @access_token = opts[:access_token]

  @headers_to_sign = opts[:headers_to_sign]
  @headers_to_sign ||= []

  @max_body = opts[:max_body]
  @max_body ||= 2048

  if opts[:debug]
    @log = Logger.new(STDERR)
  else
    @log = Logger.new('/dev/null')
  end
end
setup_from_edgerc(opts) click to toggle source
# File lib/akamai/edgegrid.rb, line 197
def setup_from_edgerc(opts)
  edgerc_path = opts[:filename] || File.expand_path('~/.edgerc')
  @section = opts[:section] || "default"
  if File.exist?(edgerc_path) 
    file = IniFile.load(edgerc_path)
    data = file[@section]
    @client_token = data["client_token"]
    @client_secret =  data["client_secret"]
    @access_token = data["access_token"]
    @max_body = data["max_body"] || 2048
    @headers_to_sign = opts[:headers_to_sign] || []
  end

  if opts[:debug]
    @log = Logger.new(STDERR)
  else
    @log = Logger.new('/dev/null')
  end
end
sign_request(request, timestamp, auth_header) click to toggle source

Returns a signature of the given request, timestamp and auth_header

# File lib/akamai/edgegrid.rb, line 151
def sign_request(request, timestamp, auth_header)
  return self.class.base64_hmac_sha256(
    make_data_to_sign(request, auth_header),
    make_signing_key(timestamp)
  )
end