aws-mfa 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []