awskeyring 1.3.3 → 1.4.0

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
  SHA256:
3
- metadata.gz: 3207b3732716f614eecc291edeaa629ebac97934e590cf7b6bf97d385cd593e5
4
- data.tar.gz: 37c0275281e5f4b2e42e8319be344aba943f4fbf81fa64e687d8cbda8e8f827f
3
+ metadata.gz: ae2606582cb2a9c079bf4ebcb6223570148954cf66fe9938c9b4d969c1312da6
4
+ data.tar.gz: d6b24f01901e6c3161e1874f9bd9d018f9b62e734d7d73f5ffaed78f0125ecb1
5
5
  SHA512:
6
- metadata.gz: 158d8f44b19e2b40a4873ecfa84f22ac2751a8470409f45ec733d614e617a00b7ad7b52786c5d3ffa1d98149120603f04e6db21c5a279fecaee55e679e10718d
7
- data.tar.gz: 0c9d3561a5c6ef181527e8ab52e858e17c5dd722403aec9df246606099c4b9bc66eb54dbacc98a770534012faf8fa52f3ebbab7c97a7fbaacd0673f5aac3f2f2
6
+ metadata.gz: d7704820e908585b67575c319e03493512917a9e5ea5db9620040402c49fbcd6466448e108949bcf32ea2d2f782e2ee8bf7e3e1bdd4e4138cb6d462c2c603635
7
+ data.tar.gz: 667e7d6d0417cda0a79c1d81680469f1ba2c7a03630bd8e7269e03f137ad669155126a927eb39542b1e9e0b07ee0f408678bb603bc77900cc7db9ff60e702c6b
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## [v1.4.0](https://github.com/servian/awskeyring/tree/v1.4.0) (2020-06-19)
4
+
5
+ [Full Changelog](https://github.com/servian/awskeyring/compare/v1.3.3...v1.4.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Import Keys and Tokens from shared credentials files. [\#65](https://github.com/servian/awskeyring/pull/65) ([tristanmorgan](https://github.com/tristanmorgan))
10
+
3
11
  ## [v1.3.3](https://github.com/servian/awskeyring/tree/v1.3.3) (2020-06-04)
4
12
 
5
13
  [Full Changelog](https://github.com/servian/awskeyring/compare/v1.3.2...v1.3.3)
data/README.md CHANGED
@@ -65,6 +65,7 @@ The CLI is using [Thor](http://whatisthor.com) with help provided interactively.
65
65
  awskeyring env ACCOUNT # Outputs bourne shell environment exports for an ACCOUNT
66
66
  awskeyring exec ACCOUNT command... # Execute a COMMAND with the environment set for an ACCOUNT
67
67
  awskeyring help [COMMAND] # Describe available commands or one specific command
68
+ awskeyring import ACCOUNT # Import an ACCOUNT to the keyring from ~/.aws/credentials
68
69
  awskeyring initialise # Initialises a new KEYCHAIN
69
70
  awskeyring json ACCOUNT # Outputs AWS CLI compatible JSON for an ACCOUNT
70
71
  awskeyring list # Prints a list of accounts in the keyring
data/Rakefile CHANGED
@@ -22,12 +22,18 @@ RuboCop::RakeTask.new do |rubocop|
22
22
  rubocop.requires << 'rubocop-rubycw'
23
23
  end
24
24
 
25
- RSpec::Core::RakeTask.new(:spec) do |rspec|
26
- rspec.rspec_opts = %w[--order rand --format documentation --color]
25
+ desc 'Run RSpec code examples'
26
+ task :spec do
27
+ puts 'Running RSpec...'
28
+ require 'rspec/core'
29
+ runner = RSpec::Core::Runner
30
+ xcode = runner.run(%w[--pattern spec/**{,/*/**}/*_spec.rb --order rand --format documentation --color])
31
+ abort 'RSpec failed' if xcode.positive?
27
32
  end
28
33
 
29
34
  desc 'Check filemode bits'
30
35
  task :filemode do
36
+ puts 'Running FileMode...'
31
37
  files = Set.new(`git ls-files -z`.split("\x0"))
32
38
  dirs = Set.new(files.map { |file| File.dirname(file) })
33
39
  failure = []
@@ -42,7 +48,7 @@ end
42
48
 
43
49
  desc 'generate manpage'
44
50
  task :ronn do
45
- puts 'Writing manpage'
51
+ puts 'Running Ronn...'
46
52
  roff_text = Ronn::Document.new('man/awskeyring.5.ronn').to_roff
47
53
  File.write('man/awskeyring.5', roff_text)
48
54
  puts "done\n\n"
@@ -14,6 +14,8 @@ en:
14
14
  desc: Outputs bourne shell environment exports for an ACCOUNT
15
15
  exec:
16
16
  desc: Execute a COMMAND with the environment set for an ACCOUNT
17
+ import:
18
+ desc: Import an ACCOUNT to the keyring from ~/.aws/credentials
17
19
  initialise:
18
20
  desc: Initialises a new KEYCHAIN
19
21
  json:
@@ -72,18 +72,17 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
72
72
 
73
73
  # Return a list of all acount items
74
74
  private_class_method def self.list_items
75
- items = all_items.all.sort do |elem_a, elem_b|
76
- elem_a.attributes[:label] <=> elem_b.attributes[:label]
77
- end
78
- items.select { |elem| elem.attributes[:label].start_with?(ACCOUNT_PREFIX) }
75
+ all_items.all.select { |elem| elem.attributes[:label].start_with?(ACCOUNT_PREFIX) }
79
76
  end
80
77
 
81
78
  # Return a list of all role items
82
79
  private_class_method def self.list_roles
83
- items = all_items.all.sort do |elem_a, elem_b|
84
- elem_a.attributes[:label] <=> elem_b.attributes[:label]
85
- end
86
- items.select { |elem| elem.attributes[:label].start_with?(ROLE_PREFIX) }
80
+ all_items.all.select { |elem| elem.attributes[:label].start_with?(ROLE_PREFIX) }
81
+ end
82
+
83
+ # Return a list of all acount items
84
+ private_class_method def self.list_tokens
85
+ all_items.all.select { |elem| elem.attributes[:label].start_with?(SESSION_KEY_PREFIX) }
87
86
  end
88
87
 
89
88
  # Return all keychain items
@@ -175,12 +174,21 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
175
174
 
176
175
  # Return a list account item names
177
176
  def self.list_account_names
178
- list_items.map { |elem| elem.attributes[:label][(ACCOUNT_PREFIX.length)..-1] }
177
+ items = list_items.map { |elem| elem.attributes[:label][(ACCOUNT_PREFIX.length)..-1] }
178
+
179
+ tokens = list_tokens.map { |elem| elem.attributes[:label][(SESSION_KEY_PREFIX.length)..-1] }
180
+
181
+ (items + tokens).uniq.sort
179
182
  end
180
183
 
181
184
  # Return a list role item names
182
185
  def self.list_role_names
183
- list_roles.map { |elem| elem.attributes[:label][(ROLE_PREFIX.length)..-1] }
186
+ list_roles.map { |elem| elem.attributes[:label][(ROLE_PREFIX.length)..-1] }.sort
187
+ end
188
+
189
+ # Return a list token item names
190
+ def self.list_token_names
191
+ list_tokens.map { |elem| elem.attributes[:label][(SESSION_KEY_PREFIX.length)..-1] }.sort
184
192
  end
185
193
 
186
194
  # Return a list role item names and arns
@@ -246,7 +254,7 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
246
254
  # Delete session token items if expired
247
255
  private_class_method def self.delete_expired(key:, token:)
248
256
  expires_at = Time.at(token.attributes[:account].to_i)
249
- if expires_at < Time.now
257
+ if expires_at < Time.new
250
258
  delete_pair(key: key, token: token, message: I18n.t('message.delexpired'))
251
259
  key = nil
252
260
  token = nil
@@ -347,6 +355,16 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
347
355
  role_name
348
356
  end
349
357
 
358
+ # Validate token exists
359
+ #
360
+ # @param [String] token_name the associated account name.
361
+ def self.token_exists(token_name)
362
+ Awskeyring::Validate.account_name(token_name)
363
+ raise 'Token does not exist' unless list_token_names.include?(token_name)
364
+
365
+ token_name
366
+ end
367
+
350
368
  # Validate role arn not exists
351
369
  #
352
370
  # @param [String] role_arn the associated role arn.
@@ -141,10 +141,11 @@ module Awskeyring
141
141
  #
142
142
  # @param [String] key The aws_access_key_id
143
143
  # @param [String] secret The aws_secret_access_key
144
- def self.verify_cred(key:, secret:)
144
+ # @param [String] token The aws_session_token
145
+ def self.verify_cred(key:, secret:, token:)
145
146
  begin
146
147
  ENV['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
147
- sts = Aws::STS::Client.new(access_key_id: key, secret_access_key: secret)
148
+ sts = Aws::STS::Client.new(access_key_id: key, secret_access_key: secret, session_token: token)
148
149
  sts.get_caller_identity
149
150
  rescue Aws::Errors::ServiceError => e
150
151
  warn e.to_s
@@ -153,6 +154,26 @@ module Awskeyring
153
154
  true
154
155
  end
155
156
 
157
+ # Retrieve credentials from the AWS Credentials file
158
+ #
159
+ # @param [String] account the profile name wanted
160
+ # @return [Hash] with the new credentials
161
+ # key The aws_access_key_id
162
+ # secret The aws_secret_access_key
163
+ # token The aws_session_token
164
+ # expiry expiry time
165
+ def self.get_credentials_from_file(account:)
166
+ creds = Aws::SharedCredentials.new(profile_name: account)
167
+ {
168
+ account: account,
169
+ key: creds.credentials.access_key_id,
170
+ secret: creds.credentials.secret_access_key,
171
+ token: creds.credentials.session_token,
172
+ expiry: Time.new + TWELVE_HOUR,
173
+ role: nil
174
+ }
175
+ end
176
+
156
177
  # Retrieves an AWS Console login url
157
178
  #
158
179
  # @param [String] key The aws_access_key_id
@@ -6,7 +6,7 @@ require 'json'
6
6
  # Version const and query of latest.
7
7
  module Awskeyring
8
8
  # The Gem's version number
9
- VERSION = '1.3.3'
9
+ VERSION = '1.4.0'
10
10
  # The Gem's homepage
11
11
  HOMEPAGE = 'https://github.com/servian/awskeyring'
12
12
 
@@ -122,6 +122,42 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
122
122
  )
123
123
  end
124
124
 
125
+ desc 'import ACCOUNT', I18n.t('import.desc')
126
+ method_option 'no-remote', type: :boolean, aliases: '-r', desc: I18n.t('method_option.noremote'), default: false
127
+ # Import an Account
128
+ def import(account = nil) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
129
+ account = ask_check(
130
+ existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_not_exists)
131
+ )
132
+ new_creds = Awskeyring::Awsapi.get_credentials_from_file(account: account)
133
+ unless options['no-remote']
134
+ Awskeyring::Awsapi.verify_cred(
135
+ key: new_creds[:key],
136
+ secret: new_creds[:secret],
137
+ token: new_creds[:token]
138
+ )
139
+ end
140
+ if new_creds[:token].nil?
141
+ Awskeyring.add_account(
142
+ account: new_creds[:account],
143
+ key: new_creds[:key],
144
+ secret: new_creds[:secret],
145
+ mfa: ''
146
+ )
147
+ puts I18n.t('message.addaccount', account: account)
148
+ else
149
+ Awskeyring.add_token(
150
+ account: new_creds[:account],
151
+ key: new_creds[:key],
152
+ secret: new_creds[:secret],
153
+ token: new_creds[:token],
154
+ expiry: new_creds[:expiry].to_i.to_s,
155
+ role: nil
156
+ )
157
+ puts I18n.t('message.addtoken', account: account, time: Time.at(new_creds[:expiry].to_i))
158
+ end
159
+ end
160
+
125
161
  desc 'exec ACCOUNT command...', I18n.t('exec.desc')
126
162
  method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false
127
163
  # execute an external command with env set
@@ -163,7 +199,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
163
199
  existing: options[:mfa], message: I18n.t('message.mfa'),
164
200
  flags: 'optional', validator: Awskeyring::Validate.method(:mfa_arn)
165
201
  )
166
- Awskeyring::Awsapi.verify_cred(key: key, secret: secret) unless options['no-remote']
202
+ Awskeyring::Awsapi.verify_cred(key: key, secret: secret, token: nil) unless options['no-remote']
167
203
  Awskeyring.add_account(
168
204
  account: account,
169
205
  key: key,
@@ -235,8 +271,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
235
271
  # remove a session token
236
272
  def remove_token(account = nil)
237
273
  account = ask_check(
238
- existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_exists),
239
- limited_to: Awskeyring.list_account_names
274
+ existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:token_exists),
275
+ limited_to: Awskeyring.list_token_names
240
276
  )
241
277
  Awskeyring.delete_token(account: account, message: I18n.t('message.deltoken', account: account))
242
278
  end
@@ -415,6 +451,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
415
451
  comp_len = 2
416
452
  when '--path', '-p'
417
453
  comp_len = 4
454
+ when 'remove-token', 'rmt'
455
+ comp_len = 5
418
456
  end
419
457
 
420
458
  [curr, comp_len, sub_cmd]
@@ -430,7 +468,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
430
468
  self.class.map[sub_cmd].to_s
431
469
  end
432
470
 
433
- def print_auto_resp(curr, len, sub_cmd)
471
+ def print_auto_resp(curr, len, sub_cmd) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
434
472
  list = []
435
473
  case len
436
474
  when 0
@@ -443,6 +481,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
443
481
  list = list_arguments(command: sub_cmd)
444
482
  when 4
445
483
  list = Awskeyring.list_console_path
484
+ when 5
485
+ list = Awskeyring.list_token_names
446
486
  else
447
487
  exit 1
448
488
  end
@@ -1,7 +1,7 @@
1
1
  .\" generated with Ronn/v0.7.3
2
2
  .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
3
  .
4
- .TH "AWSKEYRING" "5" "April 2020" "" ""
4
+ .TH "AWSKEYRING" "5" "June 2020" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBAwskeyring\fR \- is a small tool to manage AWS account keys in the macOS Keychain
@@ -61,6 +61,12 @@ help [COMMAND]:
61
61
  Describe available commands or one specific command
62
62
  .
63
63
  .TP
64
+ import:
65
+ .
66
+ .IP
67
+ Import an ACCOUNT to the keyring from ~/\.aws/credentials
68
+ .
69
+ .TP
64
70
  initialise:
65
71
  .
66
72
  .IP
@@ -42,6 +42,10 @@ The commands are as follows:
42
42
 
43
43
  Describe available commands or one specific command
44
44
 
45
+ * import:
46
+
47
+ Import an ACCOUNT to the keyring from ~/.aws/credentials
48
+
45
49
  * initialise:
46
50
 
47
51
  Initialises a new KEYCHAIN
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awskeyring
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.3
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tristan Morgan
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-04 00:00:00.000000000 Z
11
+ date: 2020-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-iam
@@ -97,8 +97,8 @@ licenses:
97
97
  metadata:
98
98
  bug_tracker_uri: https://github.com/servian/awskeyring/issues
99
99
  changelog_uri: https://github.com/servian/awskeyring/blob/master/CHANGELOG.md
100
- documentation_uri: https://rubydoc.info/gems/awskeyring/1.3.3
101
- source_code_uri: https://github.com/servian/awskeyring/tree/v1.3.3
100
+ documentation_uri: https://rubydoc.info/gems/awskeyring/1.4.0
101
+ source_code_uri: https://github.com/servian/awskeyring/tree/v1.4.0
102
102
  wiki_uri: https://github.com/servian/awskeyring/wiki
103
103
  post_install_message:
104
104
  rdoc_options: []