lib/aws_assume_role/cli/actions/console.rb
# frozen_string_literal: true
require_relative "includes"
require_relative "../../runner"
require "cgi"
require "json"
class AwsAssumeRole::Cli::Actions::Console < AwsAssumeRole::Cli::Actions::AbstractAction
include AwsAssumeRole::Ui
include AwsAssumeRole::Logging
FEDERATION_URL = "https://signin.aws.amazon.com/federation".freeze
CONSOLE_URL = "https://console.aws.amazon.com".freeze
GENERIC_SIGNIN_URL = "https://signin.aws.amazon.com/console".freeze
SIGNIN_URL = [FEDERATION_URL, "?Action=getSigninToken", "&Session=%s"].join
LOGIN_URL = [FEDERATION_URL, "?Action=login", "&Destination=%s", "&SigninToken=%s"].join
CommandSchema = proc do
required(:profile).maybe
optional(:region) { filled? > format?(REGION_REGEX) }
optional(:serial_number) { filled? > format?(MFA_REGEX) }
required(:role_arn).maybe
required(:role_session_name).maybe
required(:duration_seconds).maybe
rule(role_specification: %i[profile role_arn role_session_name duration_seconds]) do |p, r, s, d|
(p.filled? | p.empty? & r.filled?) & (r.filled? > s.filled? & d.filled?)
end
end
def try_federation(config)
credentials = try_for_credentials config.to_h
return unless credentials.set?
session = session_json(credentials)
signin_url = format SIGNIN_URL, CGI.escape(session)
sso_token = JSON.parse(URI.parse(signin_url).read)["SigninToken"]
format LOGIN_URL, CGI.escape(CONSOLE_URL), CGI.escape(sso_token)
rescue OpenURI::HTTPError
error "Error getting federated session, forming simple switch URL instead"
end
def session_json(credentials)
{
sessionId: credentials.credentials.access_key_id,
sessionKey: credentials.credentials.secret_access_key,
sessionToken: credentials.credentials.session_token,
}.to_json
end
def try_switch_url(config)
profile = AwsAssumeRole.shared_config.determine_profile(profile_name: config.profile)
config_section = AwsAssumeRole.shared_config.parsed_config[profile]
raise Aws::Errors::NoSuchProfileError if config_section.nil?
resolved_role_arn = config.role_arn || config_section.fetch("role_arn", nil)
return unless resolved_role_arn
components = resolved_role_arn.split(":")
account = components[4]
role = components[5].split("/").last
display_name = config.profile || "#{account}_#{role}"
format "https://signin.aws.amazon.com/switchrole?account=%s&roleName=%s&displayName=%s", account, role, display_name
end
def act_on(config)
final_url = try_federation(config) || try_switch_url(config) || CONSOLE_URL
Launchy.open final_url
rescue KeyError, Aws::Errors::NoSuchProfileError
error format(t("errors.NoSuchProfileError"), config.profile)
rescue Aws::Errors::MissingCredentialsError
error t("errors.MissingCredentialsError")
end
end