Module: Awskeyring::Awsapi

Defined in:
lib/awskeyring/awsapi.rb

Overview

AWS API methods for Awskeyring

Constant Summary collapse

ADMIN_POLICY =

Admin policy as json

{
  Version: '2012-10-17',
  Statement: [{
    Action: '*',
    Resource: '*',
    Effect: 'Allow'
  }]
}.to_json.freeze
AWS_SIGNIN_URL =

AWS Signin url

'https://signin.aws.amazon.com/federation'.freeze
AWS_ENV_VARS =

AWS Env vars

%w[
  AWS_ACCESS_KEY_ID
  AWS_ACCESS_KEY
  AWS_SECRET_ACCESS_KEY
  AWS_SECRET_KEY
  AWS_SECURITY_TOKEN
  AWS_SESSION_TOKEN
].freeze
TWELVE_HOUR =

Twelve hours in seconds

(60 * 60 * 12)
ONE_HOUR =

One hour in seconds

(60 * 60 * 1)
ONE_DAY =

Days in seconds

(24 * 60 * 60)

Class Method Summary collapse

Class Method Details

.get_cred_json(key:, secret:, token:, expiry:) ⇒ String

Genarates AWS CLI compatible JSON see credential_process in AWS Docs

Parameters:

  • key (String)

    The aws_access_key_id

  • secret (String)

    The aws_secret_access_key

  • token (String)

    The aws_session_token

  • expiry (String)

    expiry time

Returns:

  • (String)

    credential_process json



104
105
106
107
108
109
110
111
112
# File 'lib/awskeyring/awsapi.rb', line 104

def self.get_cred_json(key:, secret:, token:, expiry:)
  JSON.pretty_generate(
    Version: 1,
    AccessKeyId: key,
    SecretAccessKey: secret,
    SessionToken: token,
    Expiration: expiry
  )
end

.get_env_array(params = {}) ⇒ Hash

Generates Environment Variables for the AWS CLI

Parameters:

  • params (Hash) (defaults to: {})

    including

    String

    account The aws_access_key_id

    String

    secret The aws_secret_access_key

    String

    token The aws_session_token

Returns:

  • (Hash)

    env_var hash



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/awskeyring/awsapi.rb', line 121

def self.get_env_array(params = {})
  env_var = {}
  env_var['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
  env_var['AWS_ACCOUNT_NAME'] = params[:account] if params[:account]

  if params[:key]
    env_var['AWS_ACCESS_KEY_ID'] = params[:key]
    env_var['AWS_ACCESS_KEY'] = params[:key]
  end

  if params[:secret]
    env_var['AWS_SECRET_ACCESS_KEY'] = params[:secret]
    env_var['AWS_SECRET_KEY'] = params[:secret]
  end

  if params[:token]
    env_var['AWS_SECURITY_TOKEN'] = params[:token]
    env_var['AWS_SESSION_TOKEN'] = params[:token]
  end
  env_var
end

.get_login_url(key:, secret:, token:, path:, user:) ⇒ String

Retrieves an AWS Console login url

Parameters:

  • key (String)

    The aws_access_key_id

  • secret (String)

    The aws_secret_access_key

  • token (String)

    The aws_session_token

  • user (String)

    The local username

  • path (String)

    within the Console to access

Returns:

  • (String)

    login_url to access



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/awskeyring/awsapi.rb', line 167

def self.(key:, secret:, token:, path:, user:) # rubocop:disable Metrics/MethodLength
  console_url = "https://console.aws.amazon.com/#{path}/home"

  if token
    session_json = {
      sessionId: key,
      sessionKey: secret,
      sessionToken: token
    }.to_json
  else
    ENV['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
    sts = Aws::STS::Client.new(access_key_id: key,
                               secret_access_key: secret)

    session = sts.get_federation_token(name: user,
                                       policy: ADMIN_POLICY,
                                       duration_seconds: TWELVE_HOUR)
    session_json = {
      sessionId: session.credentials[:access_key_id],
      sessionKey: session.credentials[:secret_access_key],
      sessionToken: session.credentials[:session_token]
    }.to_json
  end

  destination_param = '&Destination=' + CGI.escape(console_url)

  AWS_SIGNIN_URL + '?Action=login' + token_param(session_json: session_json) + destination_param
end

.get_token(params = {}) ⇒ Hash

Retrieves a temporary session token from AWS

Parameters:

  • params (Hash) (defaults to: {})

    including key The aws_access_key_id secret The aws_secret_access_key user The local username mfa The users MFA arn code The MFA code duration time in seconds until expiry role_arn ARN of the role to assume

Returns:

  • (Hash)

    with the new credentials key The aws_access_key_id secret The aws_secret_access_key token The aws_session_token expiry expiry time



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/awskeyring/awsapi.rb', line 55

def self.get_token(params = {}) # rubocop:disable  Metrics/AbcSize, Metrics/MethodLength
  ENV['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
  sts = Aws::STS::Client.new(access_key_id: params[:key], secret_access_key: params[:secret])

  params[:mfa] = nil unless params[:code]
  begin
    response =
      if params[:role_arn]
        sts.assume_role(
          duration_seconds: params[:duration].to_i,
          role_arn: params[:role_arn],
          role_session_name: params[:user],
          serial_number: params[:mfa],
          token_code: params[:code]
        )
      elsif params[:code]
        sts.get_session_token(
          duration_seconds: params[:duration].to_i,
          serial_number: params[:mfa],
          token_code: params[:code]
        )
      else
        sts.get_federation_token(
          name: params[:user],
          policy: ADMIN_POLICY,
          duration_seconds: params[:duration]
        )
      end
  rescue Aws::STS::Errors::AccessDenied => e
    warn e.to_s
    exit 1
  end

  {
    key: response.credentials[:access_key_id],
    secret: response.credentials[:secret_access_key],
    token: response.credentials[:session_token],
    expiry: response.credentials[:expiration]
  }
end

.regionString

Get the current region

Returns:

  • (String)

    current configured region



213
214
215
216
217
# File 'lib/awskeyring/awsapi.rb', line 213

def self.region
  keys = %w[AWS_REGION AMAZON_REGION AWS_DEFAULT_REGION]
  region = ENV.values_at(*keys).compact.first
  region || Aws.shared_config.region(profile: 'default')
end

.retry_backoff(&block) ⇒ Object

Retry the call with backoff

Parameters:

  • block (Block)

    the block to retry.



256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/awskeyring/awsapi.rb', line 256

def self.retry_backoff(&block)
  retries ||= 1
  begin
    yield block
  rescue Aws::IAM::Errors::InvalidClientTokenId => err
    if retries < 4
      sleep 2**retries
      retries += 1
      retry
    end
    warn err.message
    exit 1
  end
end

.rotate(account:, key:, secret:, key_message:) ⇒ String

Rotates the AWS access keys

Parameters:

  • key (String)

    The aws_access_key_id

  • secret (String)

    The aws_secret_access_key

  • account (String)

    the associated account name.

Returns:

  • (String)

    key The aws_access_key_id

  • (String)

    secret The aws_secret_access_key

  • (String)

    account the associated account name.



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/awskeyring/awsapi.rb', line 227

def self.rotate(account:, key:, secret:, key_message:) # rubocop:disable  Metrics/MethodLength
  ENV['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
  iam = Aws::IAM::Client.new(access_key_id: key, secret_access_key: secret)

  if iam.list_access_keys[:access_key_metadata].length > 1
    warn key_message
    exit 1
  end

  new_key = iam.create_access_key
  iam = Aws::IAM::Client.new(
    access_key_id: new_key[:access_key][:access_key_id],
    secret_access_key: new_key[:access_key][:secret_access_key]
  )
  retry_backoff do
    iam.delete_access_key(
      access_key_id: key
    )
  end
  {
    account: ,
    key: new_key[:access_key][:access_key_id],
    secret: new_key[:access_key][:secret_access_key]
  }
end

.verify_cred(key:, secret:) ⇒ Object

Verify Credentials are active and valid

Parameters:

  • key (String)

    The aws_access_key_id

  • secret (String)

    The aws_secret_access_key



147
148
149
150
151
152
153
154
155
156
157
# File 'lib/awskeyring/awsapi.rb', line 147

def self.verify_cred(key:, secret:)
  begin
    ENV['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
    sts = Aws::STS::Client.new(access_key_id: key, secret_access_key: secret)
    sts.get_caller_identity
  rescue Aws::Errors::ServiceError => err
    warn err.to_s
    exit 1
  end
  true
end