Class: AwsMfa
- Inherits:
-
Object
- Object
- AwsMfa
- Defined in:
- lib/aws_mfa.rb,
lib/aws_mfa/errors.rb
Defined Under Namespace
Classes: Errors
Instance Attribute Summary collapse
-
#aws_config_dir ⇒ Object
readonly
Returns the value of attribute aws_config_dir.
Instance Method Summary collapse
- #execute ⇒ Object
- #export_credentials(credentials) ⇒ Object
- #find_aws_config ⇒ Object
-
#initialize ⇒ AwsMfa
constructor
A new instance of AwsMfa.
- #load_arn(profile = 'default') ⇒ Object
- #load_arn_from_aws(profile = 'default') ⇒ Object
- #load_arn_from_file(arn_file) ⇒ Object
- #load_credentials(arn, profile = 'default') ⇒ Object
- #load_credentials_from_aws(arn, profile = 'default') ⇒ Object
- #load_credentials_from_file(credentials_file) ⇒ Object
- #mfa_devices(profile = 'default') ⇒ Object
- #print_credentials(credentials) ⇒ Object
- #request_code_from_user ⇒ Object
- #token_not_expired?(credentials_file) ⇒ Boolean
- #unset_environment ⇒ Object
- #validate_aws_installed ⇒ Object
- #which(cmd) ⇒ Object
- #write_arn_to_file(arn_file, arn) ⇒ Object
- #write_credentials_to_file(credentials_file, credentials) ⇒ Object
Constructor Details
#initialize ⇒ AwsMfa
Returns a new instance of AwsMfa.
7 8 9 10 |
# File 'lib/aws_mfa.rb', line 7 def initialize validate_aws_installed @aws_config_dir = find_aws_config end |
Instance Attribute Details
#aws_config_dir ⇒ Object (readonly)
Returns the value of attribute aws_config_dir.
5 6 7 |
# File 'lib/aws_mfa.rb', line 5 def aws_config_dir @aws_config_dir end |
Instance Method Details
#execute ⇒ Object
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/aws_mfa.rb', line 154 def execute profile = 'default' profile_index = ARGV.index('--profile') if (!profile_index.nil?) profile = ARGV.delete_at(profile_index + 1) ARGV.delete_at(profile_index) end arn = load_arn(profile) credentials = load_credentials(arn, profile) if ARGV.empty? print_credentials(credentials) else export_credentials(credentials) exec(*ARGV) end end |
#export_credentials(credentials) ⇒ Object
147 148 149 150 151 152 |
# File 'lib/aws_mfa.rb', line 147 def export_credentials(credentials) ENV['AWS_SECRET_ACCESS_KEY'] = credentials['SecretAccessKey'] ENV['AWS_ACCESS_KEY_ID'] = credentials['AccessKeyId'] ENV['AWS_SESSION_TOKEN'] = credentials['SessionToken'] ENV['AWS_SECURITY_TOKEN'] = credentials['SessionToken'] end |
#find_aws_config ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/aws_mfa.rb', line 16 def find_aws_config if ENV['AWS_CREDENTIAL_FILE'] aws_config_file = ENV['AWS_CREDENTIAL_FILE'] aws_config_dir = File.dirname(aws_config_file) else aws_config_dir = File.join(ENV['HOME'], '.aws') aws_config_file = File.join(aws_config_dir, 'config') end unless File.readable?(aws_config_file) raise Errors::ConfigurationNotFound, 'Aws configuration not found. You must run `aws configure`' end aws_config_dir end |
#load_arn(profile = 'default') ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/aws_mfa.rb', line 44 def load_arn(profile='default') arn_file_name = 'mfa_device' if (! profile.eql? 'default') arn_file_name = "#{profile}_#{arn_file_name}" end arn_file = File.join(aws_config_dir, arn_file_name) if File.readable?(arn_file) arn = load_arn_from_file(arn_file) else arn = load_arn_from_aws(profile) write_arn_to_file(arn_file, arn) end arn end |
#load_arn_from_aws(profile = 'default') ⇒ Object
65 66 67 68 69 70 71 72 |
# File 'lib/aws_mfa.rb', line 65 def load_arn_from_aws(profile='default') puts 'Fetching MFA devices for your account...' if mfa_devices(profile).any? mfa_devices(profile).first.fetch('SerialNumber') else raise Errors::DeviceNotFound, 'No MFA devices were found for your account' end end |
#load_arn_from_file(arn_file) ⇒ Object
61 62 63 |
# File 'lib/aws_mfa.rb', line 61 def load_arn_from_file(arn_file) File.read(arn_file) end |
#load_credentials(arn, profile = 'default') ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/aws_mfa.rb', line 83 def load_credentials(arn, profile='default') credentials_file_name = 'mfa_credentials' if (! profile.eql? 'default') credentials_file_name = "#{profile}_#{credentials_file_name}" end credentials_file = File.join(aws_config_dir, credentials_file_name) if File.readable?(credentials_file) && token_not_expired?(credentials_file) credentials = load_credentials_from_file(credentials_file) else credentials = load_credentials_from_aws(arn, profile) write_credentials_to_file(credentials_file, credentials) end JSON.parse(credentials).fetch('Credentials') end |
#load_credentials_from_aws(arn, profile = 'default') ⇒ Object
104 105 106 107 108 |
# File 'lib/aws_mfa.rb', line 104 def load_credentials_from_aws(arn, profile='default') code = request_code_from_user unset_environment `aws --profile #{profile} --output json sts get-session-token --serial-number #{arn} --token-code #{code}` end |
#load_credentials_from_file(credentials_file) ⇒ Object
100 101 102 |
# File 'lib/aws_mfa.rb', line 100 def load_credentials_from_file(credentials_file) File.read(credentials_file) end |
#mfa_devices(profile = 'default') ⇒ Object
74 75 76 |
# File 'lib/aws_mfa.rb', line 74 def mfa_devices(profile='default') @mfa_devices ||= JSON.parse(`aws --profile #{profile} --output json iam list-mfa-devices`).fetch('MFADevices') end |
#print_credentials(credentials) ⇒ Object
140 141 142 143 144 145 |
# File 'lib/aws_mfa.rb', line 140 def print_credentials(credentials) puts "export AWS_SECRET_ACCESS_KEY='#{credentials['SecretAccessKey']}'" puts "export AWS_ACCESS_KEY_ID='#{credentials['AccessKeyId']}'" puts "export AWS_SESSION_TOKEN='#{credentials['SessionToken']}'" puts "export AWS_SECURITY_TOKEN='#{credentials['SessionToken']}'" end |
#request_code_from_user ⇒ Object
114 115 116 117 118 119 |
# File 'lib/aws_mfa.rb', line 114 def request_code_from_user puts 'Enter the 6-digit code from your MFA device:' code = $stdin.gets.chomp raise Errors::InvalidCode, 'That is an invalid MFA code' unless code =~ /^\d{6}$/ code end |
#token_not_expired?(credentials_file) ⇒ Boolean
128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/aws_mfa.rb', line 128 def token_not_expired?(credentials_file) # default is 12 hours expiration_period = 12 * 60 * 60 mtime = File.stat(credentials_file).mtime now = Time.new if now - mtime < expiration_period true else false end end |
#unset_environment ⇒ Object
121 122 123 124 125 126 |
# File 'lib/aws_mfa.rb', line 121 def unset_environment ENV.delete('AWS_SECRET_ACCESS_KEY') ENV.delete('AWS_ACCESS_KEY_ID') ENV.delete('AWS_SESSION_TOKEN') ENV.delete('AWS_SECURITY_TOKEN') end |
#validate_aws_installed ⇒ Object
12 13 14 |
# File 'lib/aws_mfa.rb', line 12 def validate_aws_installed raise Errors::CommandNotFound, 'Could not find the aws command' unless which('aws') end |
#which(cmd) ⇒ Object
33 34 35 36 37 38 39 40 41 42 |
# File 'lib/aws_mfa.rb', line 33 def which(cmd) exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : [''] ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| exts.each { |ext| exe = File.join(path, "#{cmd}#{ext}") return exe if File.executable? exe } end return nil end |
#write_arn_to_file(arn_file, arn) ⇒ Object
78 79 80 81 |
# File 'lib/aws_mfa.rb', line 78 def write_arn_to_file(arn_file, arn) File.open(arn_file, 'w') { |f| f.print arn } puts "Using MFA device #{arn}. To change this in the future edit #{arn_file}." end |
#write_credentials_to_file(credentials_file, credentials) ⇒ Object
110 111 112 |
# File 'lib/aws_mfa.rb', line 110 def write_credentials_to_file(credentials_file, credentials) File.open(credentials_file, 'w') { |f| f.print credentials } end |