Class: AWSUDO::IdentityProvider

Inherits:
Object
  • Object
show all
Defined in:
lib/awsudo/identity_provider.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, name, username, password) ⇒ IdentityProvider

Returns a new instance of IdentityProvider.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/awsudo/identity_provider.rb', line 29

def initialize(url, name, username, password)
  @idp_login_url = url
  @saml_provider_name = name
  @username = username
  @password = password
  @logger   = AWSUDO.logger
  begin
    URI.parse @idp_login_url
  rescue
    raise "`#{@idp_login_url.inspect}' is not a valid IDP login URL"
  end
  if @saml_provider_name.nil? || @saml_provider_name.strip.empty?
    raise "`#{@saml_provider_name.inspect}' is not a valid SAML provider name"
  end
end

Instance Attribute Details

#idp_login_urlObject

Returns the value of attribute idp_login_url.



14
15
16
# File 'lib/awsudo/identity_provider.rb', line 14

def 
  @idp_login_url
end

#loggerObject

Returns the value of attribute logger.



15
16
17
# File 'lib/awsudo/identity_provider.rb', line 15

def logger
  @logger
end

#passwordObject

Returns the value of attribute password.



15
16
17
# File 'lib/awsudo/identity_provider.rb', line 15

def password
  @password
end

#saml_provider_nameObject

Returns the value of attribute saml_provider_name.



14
15
16
# File 'lib/awsudo/identity_provider.rb', line 14

def saml_provider_name
  @saml_provider_name
end

#usernameObject

Returns the value of attribute username.



15
16
17
# File 'lib/awsudo/identity_provider.rb', line 15

def username
  @username
end

Class Method Details

.new_from_config(config, username, password) ⇒ Object



24
25
26
27
# File 'lib/awsudo/identity_provider.rb', line 24

def self.new_from_config(config, username, password)
  new(config['IDP_LOGIN_URL'], config['SAML_PROVIDER_NAME'],
           username, password)
end

.stsObject



17
18
19
20
21
22
# File 'lib/awsudo/identity_provider.rb', line 17

def self.sts
  return @sts unless @sts.nil?
  @sts = Aws::STS::Client.new(
    credentials: Aws::Credentials.new('a', 'b', 'c'),
    region:      'us-east-1')
end

Instance Method Details

#assume_role(role_arn) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/awsudo/identity_provider.rb', line 75

def assume_role(role_arn)
  logger.debug {"role_arn: <#{role_arn}>"}
  base_arn = role_arn[/^arn:aws:iam::\d+:/]
  principal_arn = "#{base_arn}saml-provider/#{saml_provider_name}"
  logger.debug {"principal_arn: <#{principal_arn}>"}
  saml_assertion = get_saml_response
  logger.debug {"saml_assertion: <#{Base64.decode64 saml_assertion}>"}
  if saml_assertion.empty?
    raise 'Unable to get SAML assertion (failed authentication?)'
  end
  self.class.sts.assume_role_with_saml(
    role_arn: role_arn,
    principal_arn: principal_arn,
    saml_assertion: saml_assertion).credentials.to_h
end

#get_saml_responseObject



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/awsudo/identity_provider.rb', line 49

def get_saml_response
  req = saml_request
  res = nil
  uri = URI.parse()

  loop do
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.verify_mode = OpenSSL::SSL::VERIFY_PEER

    res = http.request(req)
    logger.debug {"Location: <#{res['Location']}>"}
    logger.debug {"Headers: <#{res.to_hash.inspect}>"}
    logger.debug {"Body: <#{res.body.inspect}>"}

    break if res['Location'].nil?

    uri = URI.parse(res['Location'])
    req = Net::HTTP::Get.new(uri.request_uri)
    req['Cookie'] = res['Set-Cookie']
  end

  doc = Nokogiri::HTML(res.body)
  doc.xpath('/html/body//form/input[@name = "SAMLResponse"]/@value').to_s
end

#saml_requestObject



45
46
47
# File 'lib/awsudo/identity_provider.rb', line 45

def saml_request
  raise "should be implemented by subclass"
end