aws_su 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +8 -1
- data/README.md +28 -17
- data/Rakefile +7 -5
- data/aws_su.gemspec +4 -3
- data/bin/console +3 -3
- data/lib/aws_su/version.rb +1 -1
- data/lib/aws_su.rb +78 -44
- data/lib/matches_aws_access_key_id.rb +1 -0
- data/lib/matches_aws_profile.rb +1 -0
- data/lib/matches_aws_secret_access_key.rb +1 -0
- data/lib/matches_aws_security_token.rb +1 -0
- data/lib/matches_aws_session_token.rb +1 -0
- data/lib/matches_aws_token_etl.rb +1 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ced5b07379bc4a4e9f0f3d316e575886367f0cca
|
4
|
+
data.tar.gz: 14ab789e98f42ad0790d43d1d72020c65514db48
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2eeaa96c2b04eb60d6ed82d5d7b76c4f9c0cc1d5d24aa881754f4581d5bd142ac8321f3e0a905ec4fc35d49b6c2c7820a255806fc04cebe043b6ced7dbabd58
|
7
|
+
data.tar.gz: 10253e4ab496fc1924807d6f22b32d6c271b7c634a671a1813b929e6c433066040c8b9afd5e99348109df32abd36f783b7db43dc1c7266306f72a203b280e93c
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -8,4 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
8
8
|
## [0.1.0] - 01-12-2018
|
9
9
|
### Added
|
10
10
|
- Ability to authenticate and switch role via a single authenticate() method
|
11
|
-
- Gemspec file updated to enable push to Rubygems.org
|
11
|
+
- Gemspec file updated to enable push to Rubygems.org
|
12
|
+
|
13
|
+
## [0.1.1] - 02-12-2018
|
14
|
+
### Added
|
15
|
+
- Required ruby version in gemspec
|
16
|
+
- Housekeeping now that gem is on both github and rubygems
|
17
|
+
- Changed authenticate() method to accept options hash
|
18
|
+
- Added detailed header to AwsSu module
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# AwsSu
|
2
2
|
|
3
|
-
AwsSu is a gem developed for a specific use case, where the user has an ID
|
3
|
+
AwsSu is a gem developed for a specific use case, where the user has an ID setup in an AWS master account and wants to
|
4
4
|
assume a role in another account that they have permission to assume.
|
5
5
|
|
6
6
|
## Installation
|
@@ -8,7 +8,7 @@ assume a role in another account that they have permission to assume.
|
|
8
8
|
Add this line to your application's Gemfile:
|
9
9
|
|
10
10
|
```ruby
|
11
|
-
gem 'aws_su'
|
11
|
+
gem 'aws_su'
|
12
12
|
```
|
13
13
|
|
14
14
|
And then execute:
|
@@ -25,15 +25,19 @@ Implemented as a Ruby Module, the gem can be included into any class that needs
|
|
25
25
|
a role prior to calling one of the aws client methods like so:
|
26
26
|
|
27
27
|
```ruby
|
28
|
-
require 'aws_su'
|
29
|
-
|
30
|
-
class
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
28
|
+
require 'aws_su'
|
29
|
+
|
30
|
+
class RunAwsSu
|
31
|
+
include AwsSu
|
32
|
+
end
|
33
|
+
|
34
|
+
run_aws_su = RunAwsSu.new
|
35
|
+
run_aws_su.authenticate(
|
36
|
+
profile: 'ds-nonprod',
|
37
|
+
duration: '28800',
|
38
|
+
region: 'eu-west-2'
|
39
|
+
)
|
40
|
+
run_aws_su.ec2_client.describe_vpcs
|
37
41
|
```
|
38
42
|
|
39
43
|
The gem expects to find the standard aws secrets files:
|
@@ -51,19 +55,26 @@ With the former containing the master account secrets:
|
|
51
55
|
And the latter containing the details of the role to be assumed:
|
52
56
|
|
53
57
|
```
|
54
|
-
[profile my-profile]
|
55
|
-
source_profile=master
|
56
|
-
mfa_serial=arn:aws:iam::1234567890:mfa/bradley.atkins@bjss.com
|
57
|
-
role_arn=arn:aws:iam::1234567890:role/MY-NONPROD-TESTER-ROLE
|
58
|
+
[profile my-profile]
|
59
|
+
source_profile=master
|
60
|
+
mfa_serial=arn:aws:iam::1234567890:mfa/bradley.atkins@bjss.com
|
61
|
+
role_arn=arn:aws:iam::1234567890:role/MY-NONPROD-TESTER-ROLE
|
58
62
|
```
|
59
63
|
|
60
64
|
AwsSu also configures the current shell with the necessary environment variables to allow system calls to
|
61
65
|
be made without further authentication:
|
62
66
|
|
63
67
|
```ruby
|
64
|
-
system('aws ec2 describe-vpcs --region eu-west-2')
|
68
|
+
system('aws ec2 describe-vpcs --region eu-west-2')
|
65
69
|
```
|
66
70
|
|
71
|
+
Clients currently supported are:
|
72
|
+
|
73
|
+
- ec2_client
|
74
|
+
- elb_client
|
75
|
+
- iam_client
|
76
|
+
- sqs_client
|
77
|
+
|
67
78
|
## Development
|
68
79
|
|
69
80
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -72,7 +83,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
72
83
|
|
73
84
|
## Contributing
|
74
85
|
|
75
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
86
|
+
Bug reports and pull requests are welcome on GitHub at [The Github Repository](https://github.com/museadmin/aws_su). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
76
87
|
|
77
88
|
## License
|
78
89
|
|
data/Rakefile
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
require 'rake/testtask'
|
3
5
|
|
4
6
|
Rake::TestTask.new(:test) do |t|
|
5
|
-
t.libs <<
|
6
|
-
t.libs <<
|
7
|
+
t.libs << 'test'
|
8
|
+
t.libs << 'lib'
|
7
9
|
t.test_files = FileList["test/**/*_test.rb"]
|
8
10
|
end
|
9
11
|
|
10
|
-
task :
|
12
|
+
task default: :test
|
data/aws_su.gemspec
CHANGED
@@ -12,8 +12,8 @@ Gem::Specification.new do |spec|
|
|
12
12
|
|
13
13
|
spec.summary = 'Gem to wrap helper methods around AWS authentication API'
|
14
14
|
spec.description = 'Developed for a specific use case: ' \
|
15
|
-
'User has an AWS id in a master account and wants to assume'\
|
16
|
-
'
|
15
|
+
'User has an AWS id in a master account and wants to assume '\
|
16
|
+
'a role in another account. This module exposes a single '\
|
17
17
|
'authenticate() method that handles authentication and switching role '\
|
18
18
|
'by referencing the user\'s aws secrets.'
|
19
19
|
spec.homepage = 'https://github.com/museadmin'
|
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
if spec.respond_to?(:metadata)
|
25
25
|
spec.metadata['homepage_uri'] = spec.homepage
|
26
26
|
spec.metadata['source_code_uri'] = 'https://github.com/museadmin/aws_su'
|
27
|
-
spec.metadata['changelog_uri'] =
|
27
|
+
spec.metadata['changelog_uri'] = 'https://github.com/museadmin/aws_su/blob/master/CHANGELOG.md'
|
28
28
|
else
|
29
29
|
raise 'RubyGems >= 2.0 is required to protect against public gem pushes'
|
30
30
|
end
|
@@ -39,6 +39,7 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.bindir = 'exe'
|
40
40
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
41
41
|
spec.require_paths = ['lib']
|
42
|
+
spec.required_ruby_version = '>= 2.4'
|
42
43
|
|
43
44
|
spec.add_development_dependency 'awsecrets'
|
44
45
|
spec.add_development_dependency 'bundler', '~> 1.17'
|
data/bin/console
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require "bundler/setup"
|
4
|
-
require "aws_su"
|
3
|
+
require "bundler/setup".freeze
|
4
|
+
require "aws_su".freeze
|
5
5
|
|
6
6
|
# You can add fixtures and/or initialization code here to make experimenting
|
7
7
|
# with your gem easier. You can also use a different console, if you like.
|
@@ -10,5 +10,5 @@ require "aws_su"
|
|
10
10
|
# require "pry"
|
11
11
|
# Pry.start
|
12
12
|
|
13
|
-
require "irb"
|
13
|
+
require "irb".freeze
|
14
14
|
IRB.start(__FILE__)
|
data/lib/aws_su/version.rb
CHANGED
data/lib/aws_su.rb
CHANGED
@@ -3,9 +3,39 @@
|
|
3
3
|
require 'aws_config'
|
4
4
|
require 'matches'
|
5
5
|
require 'awsecrets'
|
6
|
-
require '
|
6
|
+
require 'aws_su/version'
|
7
7
|
|
8
|
-
# Set up the AWS authentication environment
|
8
|
+
# Set up the AWS authentication environment for a user
|
9
|
+
# who has an ID in a master account and is allowed to
|
10
|
+
# switch to a role in another account.
|
11
|
+
#
|
12
|
+
# Typical usage scenario:
|
13
|
+
#
|
14
|
+
# require 'aws_su'
|
15
|
+
#
|
16
|
+
# class RunAwsSu
|
17
|
+
# include AwsSu
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# run_aws_su = RunAwsSu.new
|
21
|
+
# run_aws_su.authenticate(
|
22
|
+
# profile: 'ds-nonprod',
|
23
|
+
# duration: '28800',
|
24
|
+
# region: 'eu-west-2'
|
25
|
+
# )
|
26
|
+
# run_aws_su.ec2_client.describe_vpcs
|
27
|
+
#
|
28
|
+
# also sets up current shell so system calls don't need further authentication:
|
29
|
+
#
|
30
|
+
# system('aws ec2 describe-vpcs --region eu-west-2')
|
31
|
+
#
|
32
|
+
# It is assumed that the region is set in the first profile in .aws/config, e.g.
|
33
|
+
#
|
34
|
+
# [profile master]
|
35
|
+
# region=eu-west-2
|
36
|
+
#
|
37
|
+
# or it can be set in the call to authenticate() as shown above
|
38
|
+
#
|
9
39
|
module AwsSu
|
10
40
|
class Error < StandardError; end
|
11
41
|
|
@@ -19,11 +49,21 @@ module AwsSu
|
|
19
49
|
@master_config = Awsecrets.load # AWS config for master account
|
20
50
|
|
21
51
|
# Authenticate user for the session
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
52
|
+
# @param options Hash {
|
53
|
+
# duration: 'AWS role session timeout',
|
54
|
+
# region: AWS region,
|
55
|
+
# profile: Name of profile in .aws/config to use
|
56
|
+
# }
|
57
|
+
def authenticate(options = {})
|
58
|
+
@session = "aws-su-session-#{Time.now.to_i}"
|
59
|
+
@profile = options[:profile]
|
60
|
+
@duration = options[:duration].nil? ? DURATION : options[:duration]
|
61
|
+
@token_ttl = calculate_session_expiry(@duration)
|
62
|
+
|
63
|
+
region = AWSConfig.profiles.first[1][:region]
|
64
|
+
@region = options[:region].nil? ? region : options[:region]
|
65
|
+
raise('Unable to determine region') if @region.nil?
|
66
|
+
|
27
67
|
export_aws_sudo_file
|
28
68
|
assume_role
|
29
69
|
end
|
@@ -48,21 +88,24 @@ module AwsSu
|
|
48
88
|
Aws::S3::Client.new
|
49
89
|
end
|
50
90
|
|
51
|
-
#
|
91
|
+
# SQS Client
|
92
|
+
def sqs_client
|
93
|
+
Aws::SQS::Client.new
|
94
|
+
end
|
95
|
+
|
96
|
+
# STS
|
52
97
|
def sts_client
|
53
98
|
Aws::STS::Client.new(
|
54
|
-
|
55
|
-
|
99
|
+
credentials: load_secrets,
|
100
|
+
region: @region
|
56
101
|
)
|
57
102
|
end
|
58
103
|
|
59
104
|
private
|
105
|
+
|
60
106
|
# Assume a role
|
61
|
-
# @param duration A string integer representing the session duration
|
107
|
+
# @param duration A string integer representing the role session duration
|
62
108
|
def assume_role(duration = DURATION)
|
63
|
-
# For the benefit of anything downstream we are running
|
64
|
-
export_aws_sudo_file
|
65
|
-
|
66
109
|
if session_valid?
|
67
110
|
# Recover persisted session and use that to update AWS.config
|
68
111
|
Aws.config.update(
|
@@ -74,25 +117,28 @@ module AwsSu
|
|
74
117
|
)
|
75
118
|
else
|
76
119
|
# Session has expired so auth again
|
77
|
-
|
120
|
+
assume_role_mfa(duration)
|
78
121
|
end
|
122
|
+
# For the benefit of anything downstream we are running
|
123
|
+
export_aws_sudo_file
|
79
124
|
end
|
80
125
|
|
81
126
|
# Assume a role using an MFA Token
|
82
|
-
def
|
127
|
+
def assume_role_mfa(duration, mfa_code = nil)
|
83
128
|
mfa_code = prompt_for_mfa_code if mfa_code.nil?
|
84
129
|
role_creds = sts_client.assume_role(
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
130
|
+
role_arn: AWSConfig[@profile]['role_arn'],
|
131
|
+
role_session_name: @session,
|
132
|
+
duration_seconds: duration.to_i,
|
133
|
+
serial_number: AWSConfig[@profile]['mfa_serial'],
|
134
|
+
token_code: mfa_code.to_s
|
90
135
|
)
|
91
136
|
update_aws_config(role_creds)
|
92
|
-
|
137
|
+
persist_aws_su(role_creds)
|
93
138
|
end
|
94
139
|
|
95
140
|
# Calculate the session expiration
|
141
|
+
# # @param duration A string integer representing the role session duration
|
96
142
|
def calculate_session_expiry(duration = DURATION)
|
97
143
|
(Time.now + duration.to_i).strftime('%Y-%m-%d %H:%M:%S')
|
98
144
|
end
|
@@ -148,20 +194,6 @@ module AwsSu
|
|
148
194
|
end
|
149
195
|
end
|
150
196
|
|
151
|
-
# Recover the role_arn from the AWS config file
|
152
|
-
def parse_role_arn
|
153
|
-
File.readlines(AWS_CONFIG_FILE).each do |line|
|
154
|
-
return line.split('=')[1].chomp if line.include?('role_arn')
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
# Recover the mfa serial number from AWS config file
|
159
|
-
def parse_mfa_serial
|
160
|
-
File.readlines(AWS_CONFIG_FILE).each do |line|
|
161
|
-
return line.split('=')[1].chomp if line.include?('mfa_serial')
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
197
|
# Parse the session token from awssudo
|
166
198
|
def parse_session_token
|
167
199
|
File.readlines(AWS_SUDO_FILE).each do |line|
|
@@ -177,14 +209,16 @@ module AwsSu
|
|
177
209
|
end
|
178
210
|
|
179
211
|
# Persist the config to the awssudo file
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
212
|
+
# @param config Credentials from assume role to persist
|
213
|
+
# @param file The temporary secrets file ~/.awssudo
|
214
|
+
def persist_aws_su(config, file = AWS_SUDO_FILE)
|
215
|
+
File.open(file, 'w') do |f|
|
216
|
+
f.puts('AWS_ACCESS_KEY_ID=' + config.credentials.access_key_id)
|
217
|
+
f.puts('AWS_SECRET_ACCESS_KEY=' + config.credentials.secret_access_key)
|
218
|
+
f.puts('AWS_SESSION_TOKEN=' + config.credentials.session_token)
|
219
|
+
f.puts('AWS_SECURITY_TOKEN=' + config.credentials.session_token)
|
220
|
+
f.puts('AWS_TOKEN_TTL=' + @token_ttl)
|
221
|
+
f.puts('AWS_PROFILE=' + @profile)
|
188
222
|
end
|
189
223
|
end
|
190
224
|
|
data/lib/matches_aws_profile.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws_su
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bradley Atkins
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-12-
|
11
|
+
date: 2018-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awsecrets
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '10.0'
|
69
69
|
description: 'Developed for a specific use case: User has an AWS id in a master account
|
70
|
-
and wants to assume a role in another account. This module exposes a
|
70
|
+
and wants to assume a role in another account. This module exposes a single authenticate()
|
71
71
|
method that handles authentication and switching role by referencing the user''s
|
72
72
|
aws secrets.'
|
73
73
|
email:
|
@@ -103,7 +103,7 @@ licenses:
|
|
103
103
|
metadata:
|
104
104
|
homepage_uri: https://github.com/museadmin
|
105
105
|
source_code_uri: https://github.com/museadmin/aws_su
|
106
|
-
changelog_uri:
|
106
|
+
changelog_uri: https://github.com/museadmin/aws_su/blob/master/CHANGELOG.md
|
107
107
|
post_install_message:
|
108
108
|
rdoc_options: []
|
109
109
|
require_paths:
|
@@ -112,7 +112,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
112
112
|
requirements:
|
113
113
|
- - ">="
|
114
114
|
- !ruby/object:Gem::Version
|
115
|
-
version: '
|
115
|
+
version: '2.4'
|
116
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
117
117
|
requirements:
|
118
118
|
- - ">="
|