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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c94982b2139e90c3f36bb7b8e7f4d2989b05a2e
4
- data.tar.gz: b6de06567ecb9a29348ecce20a12d4b93600ad19
3
+ metadata.gz: ced5b07379bc4a4e9f0f3d316e575886367f0cca
4
+ data.tar.gz: 14ab789e98f42ad0790d43d1d72020c65514db48
5
5
  SHA512:
6
- metadata.gz: 412fb1c85c563d71b74e6aca277ef5c3031ad7503aafbeb6baccc58dde436b81fe5c7755ac0d71095af878cff2d1062b3570868624cd7f8041782f32f006561b
7
- data.tar.gz: de13c38ada25aeada402abff4465d24f91346b032365ebaef4c02f5992b20bdb503332caab3b8a9800d9a58571ed977a2779e72a541550fcb4a95df812a9580a
6
+ metadata.gz: c2eeaa96c2b04eb60d6ed82d5d7b76c4f9c0cc1d5d24aa881754f4581d5bd142ac8321f3e0a905ec4fc35d49b6c2c7820a255806fc04cebe043b6ced7dbabd58
7
+ data.tar.gz: 10253e4ab496fc1924807d6f22b32d6c271b7c634a671a1813b929e6c433066040c8b9afd5e99348109df32abd36f783b7db43dc1c7266306f72a203b280e93c
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  .idea/*
11
11
  Gemfile.lock
12
12
  *.html
13
+ /test/runner.rb
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 setuo in an AWS master account and wants to
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 Runner
31
- include AwsSu
32
- end
33
-
34
- runner = Runner.new
35
- runner.authenticate('my-profile')
36
- runner.ec2_client.describe_vpcs
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/[USERNAME]/aws_sudo. 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.
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
- require "bundler/gem_tasks"
2
- require "rake/testtask"
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 << "test"
6
- t.libs << "lib"
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
7
9
  t.test_files = FileList["test/**/*_test.rb"]
8
10
  end
9
11
 
10
- task :default => :test
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
- ' a role in another account. This module exposes a single'\
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'] = "Put your gem's CHANGELOG.md URL here."
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__)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AwsSu
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
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 'aws_sudo/version'
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
- def authenticate(profile, duration = DURATION)
23
- @session = "awssudo-session-#{Time.now.to_i}"
24
- @token_ttl = calculate_session_expiry(duration)
25
- @profile = profile
26
- @duration = duration
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
- # Get an STS client so we can request a session token
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
- credentials: load_secrets,
55
- region: 'eu-west-2'
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
- assume_role_with_mfa_token(duration)
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 assume_role_with_mfa_token(duration, mfa_code = nil)
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
- role_arn: AWSConfig[@profile]['role_arn'],
86
- role_session_name: @session,
87
- duration_seconds: duration.to_i,
88
- serial_number: AWSConfig[@profile]['mfa_serial'],
89
- token_code: mfa_code.to_s
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
- persist_aws_sudo(role_creds)
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
- def persist_aws_sudo(config, file = AWS_SUDO_FILE)
181
- File.open(file, 'w') do |file|
182
- file.puts('AWS_ACCESS_KEY_ID=' + config.credentials.access_key_id)
183
- file.puts('AWS_SECRET_ACCESS_KEY=' + config.credentials.secret_access_key)
184
- file.puts('AWS_SESSION_TOKEN=' + config.credentials.session_token)
185
- file.puts('AWS_SECURITY_TOKEN=' + config.credentials.session_token)
186
- file.puts('AWS_TOKEN_TTL=' + @token_ttl)
187
- file.puts('AWS_PROFILE=' + @profile)
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
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  # Match AWS_ACCESS_KEY_ID
3
4
  class MatchesAwsAccessKeyId
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  # Match AWS_PROFILE
3
4
  class MatchesAwsProfile
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  # Match AWS_SECRET_ACCESS_KEY
3
4
  class MatchesAwsSecretAccessKey
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  # Match AWS_SECURITY_TOKEN
3
4
  class MatchesAwsSecurityToken
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  # Match AWS_SESSION_TOKEN
3
4
  class MatchesAwsSessionToken
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  # Match AWS_TOKEN_TTL
3
4
  class MatchesAwsTokenEtl
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.0
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-01 00:00:00.000000000 Z
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 singleauthenticate()
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: Put your gem's CHANGELOG.md URL here.
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: '0'
115
+ version: '2.4'
116
116
  required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  requirements:
118
118
  - - ">="