aws-mfa 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. data/bin/aws-mfa +120 -0
  2. metadata +48 -0
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'json'
4
+
5
+ class AwsMfa
6
+ def initialize
7
+ @aws_config_dir = validate_aws_install
8
+ end
9
+
10
+ def validate_aws_install
11
+ unless which('aws')
12
+ puts 'Could not find the aws command'
13
+ exit 1
14
+ end
15
+
16
+ if ENV['AWS_CREDENTIAL_FILE']
17
+ aws_config_file = ENV['AWS_CREDENTIAL_FILE']
18
+ aws_config_dir = File.dirname(aws_config_file)
19
+ else
20
+ aws_config_dir = File.join(ENV['HOME'], '.aws')
21
+ aws_config_file = File.join(aws_config_dir, 'config')
22
+ end
23
+
24
+ unless File.readable?(aws_config_file)
25
+ puts 'Aws configuration not found. You must run `aws cli configure`'
26
+ exit 1
27
+ end
28
+
29
+ aws_config_dir
30
+ end
31
+
32
+ # http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
33
+ def which(cmd)
34
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
35
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
36
+ exts.each { |ext|
37
+ exe = File.join(path, "#{cmd}#{ext}")
38
+ return exe if File.executable? exe
39
+ }
40
+ end
41
+ return nil
42
+ end
43
+
44
+ def load_arn
45
+ arn_file = File.join(@aws_config_dir, 'mfa_device')
46
+
47
+ if File.readable?(arn_file)
48
+ arn = File.read(arn_file)
49
+ else
50
+ puts 'Fetching MFA devices for your account...'
51
+ mfa_devices = JSON.parse(`aws iam list-mfa-devices`).fetch('MFADevices')
52
+ if mfa_devices.any?
53
+ arn = mfa_devices.first.fetch('SerialNumber')
54
+ puts "Using MFA device #{arn}. To change this in the future edit #{arn_file}."
55
+ File.open(arn_file, 'w') { |f| f.print arn }
56
+ else
57
+ abort 'No MFA devices were found for your account'
58
+ end
59
+ end
60
+ arn
61
+ end
62
+
63
+ def get_credentials(arn)
64
+ credentials_file = File.join(@aws_config_dir, 'mfa_credentials')
65
+
66
+ if File.readable?(credentials_file) && token_not_expired?(credentials_file)
67
+ credentials = JSON.parse(File.read(credentials_file))
68
+ else
69
+ puts 'Enter the 6-digit code from your MFA device:'
70
+ code = $stdin.gets.chomp
71
+ unless code =~ /^\d{6}$/
72
+ puts 'That is an invalid MFA code'
73
+ exit 1
74
+ end
75
+ credentials_raw = `aws sts get-session-token --serial-number #{arn} --token-code #{code}`
76
+ credentials = JSON.parse(credentials_raw)
77
+ File.open(credentials_file, 'w') { |f| f.print credentials_raw }
78
+ end
79
+
80
+ credentials['Credentials']
81
+ end
82
+
83
+ def token_not_expired?(credentials_file)
84
+ # default is 12 hours
85
+ expiration_period = 12 * 60 * 60
86
+ mtime = File.stat(credentials_file).mtime
87
+ now = Time.new
88
+ if now - mtime < expiration_period
89
+ true
90
+ else
91
+ false
92
+ end
93
+ end
94
+
95
+ def print_credentials(credentials)
96
+ puts "export AWS_SECRET_ACCESS_KEY='#{credentials['SecretAccessKey']}'"
97
+ puts "export AWS_ACCESS_KEY_ID='#{credentials['AccessKeyId']}'"
98
+ puts "export AWS_SESSION_TOKEN='#{credentials['SessionToken']}'"
99
+ end
100
+
101
+ def export_credentials(credentials)
102
+ ENV['AWS_SECRET_ACCESS_KEY'] = credentials['SecretAccessKey']
103
+ ENV['AWS_ACCESS_KEY_ID'] = credentials['AccessKeyId']
104
+ ENV['AWS_SESSION_TOKEN'] = credentials['SessionToken']
105
+ end
106
+
107
+ def execute
108
+ arn = load_arn
109
+ credentials = get_credentials(arn)
110
+ if ARGV.empty?
111
+ print_credentials(credentials)
112
+ else
113
+ export_credentials(credentials)
114
+ exec(*ARGV)
115
+ end
116
+ end
117
+ end
118
+
119
+ aws_mfa = AwsMfa.new
120
+ aws_mfa.execute
metadata ADDED
@@ -0,0 +1,48 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aws-mfa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brian Pitts
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-09-30 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Run AWS commands with MFA
15
+ email: brian.pitts@lonelyplanet.com
16
+ executables:
17
+ - aws-mfa
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - bin/aws-mfa
22
+ homepage: http://www.github.com/lonelyplanet/aws-mfa
23
+ licenses:
24
+ - Apache-2.0
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ requirements:
42
+ - aws-cli
43
+ rubyforge_project:
44
+ rubygems_version: 1.8.23
45
+ signing_key:
46
+ specification_version: 3
47
+ summary: Run AWS commands with MFA
48
+ test_files: []