class AliyunSDK::STS::Protocol

Protocol implements the STS Open API which is low-level. User should refer to {STS::Client} for normal use.

Constants

API_VERSION
ENDPOINT
FORMAT
SIGNATURE_METHOD
SIGNATURE_VERSION

Public Class Methods

new(config) click to toggle source
# File lib/aliyun_sdk/sts/protocol.rb, line 21
def initialize(config)
  @config = config
end

Public Instance Methods

assume_role(role, session, policy = nil, duration = 3600) click to toggle source

Assume a role @param role [String] the role arn @param session [String] the session name @param policy [STS::Policy] the policy @param duration [Fixnum] the duration seconds for the

requested token

@return [STS::Token] the sts token

# File lib/aliyun_sdk/sts/protocol.rb, line 32
def assume_role(role, session, policy = nil, duration = 3600)
  logger.info("Begin assume role, role: #{role}, session: #{session}, "\
              "policy: #{policy}, duration: #{duration}")

  params = {
    'Action' => 'AssumeRole',
    'RoleArn' => role,
    'RoleSessionName' => session,
    'DurationSeconds' => duration.to_s
  }
  params.merge!({'Policy' => policy.serialize}) if policy

  body = do_request(params)
  doc = parse_xml(body)

  creds_node = doc.at_css("Credentials")
  creds = {
    session_name: session,
    access_key_id: get_node_text(creds_node, 'AccessKeyId'),
    access_key_secret: get_node_text(creds_node, 'AccessKeySecret'),
    security_token: get_node_text(creds_node, 'SecurityToken'),
    expiration: get_node_text(
      creds_node, 'Expiration') { |x| Time.parse(x) },
  }

  logger.info("Done assume role, creds: #{creds}")

  Token.new(creds)
end

Private Instance Methods

do_request(params) click to toggle source

Do HTTP POST request with specified params @param params [Hash] the parameters to STS @return [String] the response body @raise [ServerError] raise errors if the server responds with errors

# File lib/aliyun_sdk/sts/protocol.rb, line 73
def do_request(params)
  query = params.merge(
    {'Format' => FORMAT,
     'Version' => API_VERSION,
     'AccessKeyId' => @config.access_key_id,
     'SignatureMethod' => SIGNATURE_METHOD,
     'SignatureVersion' => SIGNATURE_VERSION,
     'SignatureNonce' => signature_nonce,
     'Timestamp' => Time.now.utc.iso8601})

  signature = Util.get_signature('POST', query, @config.access_key_secret)
  query.merge!({'Signature' => signature})

  r = RestClient::Request.execute(
    :method => 'POST',
    :url => @config.endpoint || ENDPOINT,
    :payload => query
  ) do |response, request, result, &blk|

    if response.code >= 300
      e = ServerError.new(response)
      logger.error(e.to_s)
      raise e
    else
      response.return!(request, result, &blk)
    end
  end

  logger.debug("Received HTTP response, code: #{r.code}, headers: "\
               "#{r.headers}, body: #{r.body}")
  r.body
end
get_node_text(node, tag) { |value| ... } click to toggle source

Get the text of a xml node @param node [Nokogiri::XML::Node] the xml node @param tag [String] the node tag @yield [String] the node text is given to the block

# File lib/aliyun_sdk/sts/protocol.rb, line 121
def get_node_text(node, tag, &block)
  n = node.at_css(tag) if node
  value = n.text if n
  block && value ? yield(value) : value
end
parse_xml(content) click to toggle source

Parse body content to xml document @param content [String] the xml content @return [Nokogiri::XML::Document] the parsed document

# File lib/aliyun_sdk/sts/protocol.rb, line 109
def parse_xml(content)
  doc = Nokogiri::XML(content) do |config|
    config.options |= Nokogiri::XML::ParseOptions::NOBLANKS
  end

  doc
end
signature_nonce() click to toggle source

Generate a random signature nonce @return [String] a random string

# File lib/aliyun_sdk/sts/protocol.rb, line 65
def signature_nonce
  (rand * 1_000_000_000).to_s
end