awskeyring 1.2.0 → 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: 9c691b2c94541dc7bf3562ae06b25231dbc8b04f42a04cb327209424f46c9849
4
- data.tar.gz: a4c0362c4656c64de13708d44a38a1258da651abc1fb79635d99992b0259fd4a
3
+ metadata.gz: ae2606582cb2a9c079bf4ebcb6223570148954cf66fe9938c9b4d969c1312da6
4
+ data.tar.gz: d6b24f01901e6c3161e1874f9bd9d018f9b62e734d7d73f5ffaed78f0125ecb1
5
5
  SHA512:
6
- metadata.gz: d7982836f83b748af2e4a64ce91b74f33f7f26a6423919fe0ce114011b8ffae9af61039e93a9307e7caeb97eb60ba22131dc57725d6bedd69529fc80e57c6db2
7
- data.tar.gz: 79700754547b8ce87008a8624686dac7d362947f48e2e9a8a9904e71522454c53c63ed5edfc0fea5f16f5b2be9409641375836fb78fc0dd1c6f91c7b7b6464ca
6
+ metadata.gz: d7704820e908585b67575c319e03493512917a9e5ea5db9620040402c49fbcd6466448e108949bcf32ea2d2f782e2ee8bf7e3e1bdd4e4138cb6d462c2c603635
7
+ data.tar.gz: 667e7d6d0417cda0a79c1d81680469f1ba2c7a03630bd8e7269e03f137ad669155126a927eb39542b1e9e0b07ee0f408678bb603bc77900cc7db9ff60e702c6b
@@ -1,5 +1,51 @@
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
+
11
+ ## [v1.3.3](https://github.com/servian/awskeyring/tree/v1.3.3) (2020-06-04)
12
+
13
+ [Full Changelog](https://github.com/servian/awskeyring/compare/v1.3.2...v1.3.3)
14
+
15
+ **Implemented enhancements:**
16
+
17
+ - Change email references from Vibrato to Servian [\#64](https://github.com/servian/awskeyring/pull/64) ([tristanmorgan](https://github.com/tristanmorgan))
18
+
19
+ ## [v1.3.2](https://github.com/servian/awskeyring/tree/v1.3.2) (2020-04-27)
20
+
21
+ [Full Changelog](https://github.com/servian/awskeyring/compare/v1.3.1...v1.3.2)
22
+
23
+ **Fixed bugs:**
24
+
25
+ - Fix I18n message load when used as a library. [\#63](https://github.com/servian/awskeyring/pull/63) ([tristanmorgan](https://github.com/tristanmorgan))
26
+
27
+ ## [v1.3.1](https://github.com/servian/awskeyring/tree/v1.3.1) (2020-03-19)
28
+
29
+ [Full Changelog](https://github.com/servian/awskeyring/compare/v1.3.0...v1.3.1)
30
+
31
+ **Implemented enhancements:**
32
+
33
+ - Markdown linting changes and removed Rubocop-MD. [\#61](https://github.com/servian/awskeyring/pull/61) ([tristanmorgan](https://github.com/tristanmorgan))
34
+ - Removed some redundant code. [\#60](https://github.com/servian/awskeyring/pull/60) ([tristanmorgan](https://github.com/tristanmorgan))
35
+
36
+ **Merged pull requests:**
37
+
38
+ - Update Ronn code and PR template. [\#59](https://github.com/servian/awskeyring/pull/59) ([tristanmorgan](https://github.com/tristanmorgan))
39
+
40
+ ## [v1.3.0](https://github.com/servian/awskeyring/tree/v1.3.0) (2020-02-19)
41
+
42
+ [Full Changelog](https://github.com/servian/awskeyring/compare/v1.2.0...v1.3.0)
43
+
44
+ **Implemented enhancements:**
45
+
46
+ - Add a man-page and tweak README. [\#58](https://github.com/servian/awskeyring/pull/58) ([tristanmorgan](https://github.com/tristanmorgan))
47
+ - Enhanced version [\#57](https://github.com/servian/awskeyring/pull/57) ([AzySir](https://github.com/AzySir))
48
+
3
49
  ## [v1.2.0](https://github.com/servian/awskeyring/tree/v1.2.0) (2020-01-20)
4
50
 
5
51
  [Full Changelog](https://github.com/servian/awskeyring/compare/v1.1.2...v1.2.0)
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
55
55
  ## Enforcement
56
56
 
57
57
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at [tristan@vibrato.com.au]. All
58
+ reported by contacting the project team at [tristan.morgan@servian.com](mailto:tristan.morgan@servian.com). All
59
59
  complaints will be reviewed and investigated and will result in a response that
60
60
  is deemed necessary and appropriate to the circumstances. The project team is
61
61
  obligated to maintain confidentiality with regard to the reporter of an incident.
@@ -68,6 +68,6 @@ members of the project's leadership.
68
68
  ## Attribution
69
69
 
70
70
  This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
71
+ available [here](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html)
72
72
 
73
73
  [homepage]: https://www.contributor-covenant.org
@@ -35,7 +35,7 @@ A friendly `README.md` written for many audiences.
35
35
 
36
36
  The [wiki].
37
37
 
38
- ### API documentation
38
+ ### API documentation
39
39
 
40
40
  API documentation is written as [YARD] docblocks in the Ruby code.
41
41
 
data/Gemfile CHANGED
@@ -8,9 +8,9 @@ gemspec
8
8
  group :development do
9
9
  gem 'github_changelog_generator'
10
10
  gem 'rake'
11
+ gem 'ronn'
11
12
  gem 'rspec'
12
13
  gem 'rubocop'
13
- gem 'rubocop-md'
14
14
  gem 'rubocop-performance'
15
15
  gem 'rubocop-rake'
16
16
  gem 'rubocop-rspec'
data/README.md CHANGED
@@ -9,7 +9,8 @@
9
9
  * [![Version Downloads](https://ruby-gem-downloads-badge.herokuapp.com/awskeyring?label=downloads-current-version)](https://rubygems.org/gems/awskeyring)
10
10
  * [![Documentation](https://img.shields.io/badge/yard-docs-brightgreen.svg)](https://www.rubydoc.info/gems/awskeyring)
11
11
 
12
- Awskeyring is a small tool to manage AWS account keys in the macOS Keychain.
12
+ Awskeyring is a small tool to manage AWS account keys in the macOS Keychain. It has
13
+ grown to incorporate a lot of [features](https://github.com/servian/awskeyring/wiki/Awskeyring-features).
13
14
 
14
15
  ## Motivation
15
16
 
@@ -34,17 +35,19 @@ Please see the [Wiki](https://github.com/servian/awskeyring/wiki) for full usage
34
35
 
35
36
  First you need to initialise your keychain to hold your AWS credentials.
36
37
 
37
- awskeyring initialise
38
+ $ awskeyring initialise
38
39
 
39
40
  Then add your keys to it.
40
41
 
41
- awskeyring add personal-aws
42
+ $ awskeyring add personal-aws
42
43
 
43
44
  Now your keys are stored safely in the macOS keychain. To print environment variables run...
44
45
 
45
- awskeyring env personal-aws
46
+ $ awskeyring env personal-aws
46
47
 
47
- Alternatively you can create a profile using the credential_process config variable. See the [AWS CLI Config docs](https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#cli-aws-help-config-vars) for more details on this config option.
48
+ Alternatively you can create a profile using the credential_process config variable. See the
49
+ [AWS CLI Config docs](https://docs.aws.amazon.com/cli/latest/topic/config-vars.html#cli-aws-help-config-vars) for
50
+ more details on this config option.
48
51
 
49
52
  [profile personal]
50
53
  region = us-west-1
@@ -62,6 +65,7 @@ The CLI is using [Thor](http://whatisthor.com) with help provided interactively.
62
65
  awskeyring env ACCOUNT # Outputs bourne shell environment exports for an ACCOUNT
63
66
  awskeyring exec ACCOUNT command... # Execute a COMMAND with the environment set for an ACCOUNT
64
67
  awskeyring help [COMMAND] # Describe available commands or one specific command
68
+ awskeyring import ACCOUNT # Import an ACCOUNT to the keyring from ~/.aws/credentials
65
69
  awskeyring initialise # Initialises a new KEYCHAIN
66
70
  awskeyring json ACCOUNT # Outputs AWS CLI compatible JSON for an ACCOUNT
67
71
  awskeyring list # Prints a list of accounts in the keyring
@@ -87,17 +91,28 @@ To set your environment easily the following bash function helps:
87
91
 
88
92
  ## Development
89
93
 
90
- After checking out the repo, run `bundle update` to install dependencies. Then, run `rake` to run the tests. Run `bundle exec awskeyring` to use the gem in this directory, ignoring other installed copies of this gem. Awskeyring is tested against the last two versions of Ruby shipped with macOS.
94
+ After checking out the repo, run `bundle update` to install dependencies. Then, run `bundle exec rake` to run the
95
+ tests. Run `bundle exec awskeyring` to use the gem in this directory, ignoring other installed copies of this gem.
96
+ Awskeyring is tested against the last two versions of Ruby shipped with macOS.
91
97
 
92
98
  To install this gem onto your local machine, run `bundle exec rake install`.
93
99
 
94
100
  ## Security
95
101
 
96
- If you believe you have found a security issue in Awskeyring, please responsibly disclose by contacting me at [tristan@vibrato.com.au](mailto:tristan@vibrato.com.au). Awskeyring is a Ruby script and as such Ruby is whitelisted to access your "awskeyring" keychain. Use a strong password and keep the unlock time short.
102
+ If you believe you have found a security issue in Awskeyring, please responsibly disclose by contacting me at
103
+ [tristan.morgan@servian.com](mailto:tristan.morgan@servian.com). Awskeyring is a Ruby script and as such Ruby is whitelisted
104
+ to access your "awskeyring" keychain. Use a strong password and keep the unlock time short.
97
105
 
98
106
  ## Contributing
99
107
 
100
- Bug reports and pull requests are welcome on GitHub at https://github.com/servian/awskeyring. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](https://contributor-covenant.org) code of conduct.
108
+ Bug reports and pull requests are welcome on GitHub at [https://github.com/servian/awskeyring](https://github.com/servian/awskeyring).
109
+ This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to
110
+ the [Contributor Covenant](https://contributor-covenant.org) code of conduct.
111
+
112
+ ### Contributors
113
+
114
+ * Tristan [tristanmorgan](https://github.com/tristanmorgan)
115
+ * Adam Sir [AzySir](https://github.com/AzySir)
101
116
 
102
117
  ## License
103
118
 
data/Rakefile CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rspec/core/rake_task'
5
5
  require 'rubocop/rake_task'
6
+ require 'ronn'
6
7
  require 'github_changelog_generator/task'
7
8
  require 'yard'
8
9
 
@@ -14,30 +15,48 @@ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
14
15
  end
15
16
 
16
17
  RuboCop::RakeTask.new do |rubocop|
17
- rubocop.options = ['-D']
18
+ rubocop.options = %w[-D --enable-pending-cops]
19
+ rubocop.requires << 'rubocop-performance'
20
+ rubocop.requires << 'rubocop-rake'
21
+ rubocop.requires << 'rubocop-rspec'
22
+ rubocop.requires << 'rubocop-rubycw'
18
23
  end
19
24
 
20
- RSpec::Core::RakeTask.new(:spec)
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?
32
+ end
21
33
 
22
34
  desc 'Check filemode bits'
23
35
  task :filemode do
24
- files = `git ls-files -z`.split("\x0")
25
- failure = false
26
- files.each do |file|
36
+ puts 'Running FileMode...'
37
+ files = Set.new(`git ls-files -z`.split("\x0"))
38
+ dirs = Set.new(files.map { |file| File.dirname(file) })
39
+ failure = []
40
+ files.merge(dirs).each do |file|
27
41
  mode = File.stat(file).mode
28
42
  print '.'
29
- if (mode & 0x7) != (mode >> 3 & 0x7)
30
- puts file
31
- failure = true
32
- end
43
+ failure << file if (mode & 0x7) != (mode >> 3 & 0x7)
33
44
  end
34
- abort 'Error: Incorrect file mode found' if failure
45
+ abort "\nError: Incorrect file mode found\n#{failure.join("\n")}" unless failure.empty?
35
46
  print "\n"
36
47
  end
37
48
 
49
+ desc 'generate manpage'
50
+ task :ronn do
51
+ puts 'Running Ronn...'
52
+ roff_text = Ronn::Document.new('man/awskeyring.5.ronn').to_roff
53
+ File.write('man/awskeyring.5', roff_text)
54
+ puts "done\n\n"
55
+ end
56
+
38
57
  YARD::Rake::YardocTask.new do |t|
39
58
  t.options = ['--fail-on-warning', '--no-progress']
40
59
  t.stats_options = ['--list-undoc']
41
60
  end
42
61
 
43
- task default: %i[filemode rubocop spec yard]
62
+ task default: %i[filemode rubocop spec ronn yard]
@@ -8,18 +8,26 @@ Gem::Specification.new do |spec|
8
8
  spec.name = 'awskeyring'
9
9
  spec.version = Awskeyring::VERSION
10
10
  spec.authors = ['Tristan Morgan']
11
- spec.email = ['tristan@vibrato.com.au']
11
+ spec.email = 'tristan.morgan@servian.com'
12
12
 
13
13
  spec.summary = 'Manages AWS credentials in the macOS keychain'
14
14
  spec.description = 'Manages AWS credentials in the macOS keychain'
15
15
  spec.homepage = Awskeyring::HOMEPAGE
16
- spec.license = 'MIT'
16
+ spec.licenses = ['MIT']
17
17
 
18
18
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^spec/|^\..*|^.*\.png}) }
19
19
  spec.bindir = 'exe'
20
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
21
  spec.require_paths = ['lib']
22
22
 
23
+ spec.metadata = {
24
+ 'bug_tracker_uri' => "#{Awskeyring::HOMEPAGE}/issues",
25
+ 'changelog_uri' => "#{Awskeyring::HOMEPAGE}/blob/master/CHANGELOG.md",
26
+ 'documentation_uri' => "https://rubydoc.info/gems/#{spec.name}/#{Awskeyring::VERSION}",
27
+ 'source_code_uri' => "#{Awskeyring::HOMEPAGE}/tree/v#{Awskeyring::VERSION}",
28
+ 'wiki_uri' => "#{Awskeyring::HOMEPAGE}/wiki"
29
+ }
30
+
23
31
  spec.add_dependency('aws-sdk-iam')
24
32
  spec.add_dependency('i18n')
25
33
  spec.add_dependency('ruby-keychain')
@@ -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:
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'i18n'
3
4
  require 'json'
4
5
  require 'keychain'
5
6
  require 'awskeyring/validate'
@@ -7,6 +8,9 @@ require 'awskeyring/validate'
7
8
  # Awskeyring Module,
8
9
  # gives you an interface to access keychains and items.
9
10
  module Awskeyring # rubocop:disable Metrics/ModuleLength
11
+ I18n.load_path = Dir.glob(File.join(File.realpath(__dir__), '..', 'i18n', '*.{yml,yaml}'))
12
+ I18n.backend.load_translations
13
+
10
14
  # Default rpeferences fole path
11
15
  PREFS_FILE = (File.expand_path '~/.awskeyring').freeze
12
16
  # Prefix for Roles
@@ -68,18 +72,17 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
68
72
 
69
73
  # Return a list of all acount items
70
74
  private_class_method def self.list_items
71
- items = all_items.all.sort do |elem_a, elem_b|
72
- elem_a.attributes[:label] <=> elem_b.attributes[:label]
73
- end
74
- items.select { |elem| elem.attributes[:label].start_with?(ACCOUNT_PREFIX) }
75
+ all_items.all.select { |elem| elem.attributes[:label].start_with?(ACCOUNT_PREFIX) }
75
76
  end
76
77
 
77
78
  # Return a list of all role items
78
79
  private_class_method def self.list_roles
79
- items = all_items.all.sort do |elem_a, elem_b|
80
- elem_a.attributes[:label] <=> elem_b.attributes[:label]
81
- end
82
- 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) }
83
86
  end
84
87
 
85
88
  # Return all keychain items
@@ -171,12 +174,21 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
171
174
 
172
175
  # Return a list account item names
173
176
  def self.list_account_names
174
- 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
175
182
  end
176
183
 
177
184
  # Return a list role item names
178
185
  def self.list_role_names
179
- 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
180
192
  end
181
193
 
182
194
  # Return a list role item names and arns
@@ -242,7 +254,7 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
242
254
  # Delete session token items if expired
243
255
  private_class_method def self.delete_expired(key:, token:)
244
256
  expires_at = Time.at(token.attributes[:account].to_i)
245
- if expires_at < Time.now
257
+ if expires_at < Time.new
246
258
  delete_pair(key: key, token: token, message: I18n.t('message.delexpired'))
247
259
  key = nil
248
260
  token = nil
@@ -343,6 +355,16 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
343
355
  role_name
344
356
  end
345
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
+
346
368
  # Validate role arn not exists
347
369
  #
348
370
  # @param [String] role_arn the associated role arn.
@@ -24,6 +24,7 @@ module Awskeyring
24
24
 
25
25
  # AWS Env vars
26
26
  AWS_ENV_VARS = %w[
27
+ AWS_ACCOUNT_NAME
27
28
  AWS_ACCESS_KEY_ID
28
29
  AWS_ACCESS_KEY
29
30
  AWS_SECRET_ACCESS_KEY
@@ -116,29 +117,23 @@ module Awskeyring
116
117
  # Generates Environment Variables for the AWS CLI
117
118
  #
118
119
  # @param [Hash] params including
119
- # [String] account The aws_access_key_id
120
+ # [String] account The aws account name
121
+ # [String] key The aws_access_key_id
120
122
  # [String] secret The aws_secret_access_key
121
123
  # [String] token The aws_session_token
122
124
  # @return [Hash] env_var hash
123
125
  def self.get_env_array(params = {})
124
126
  env_var = {}
125
127
  env_var['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
126
- env_var['AWS_ACCOUNT_NAME'] = params[:account] if params[:account]
127
128
 
128
- if params[:key]
129
- env_var['AWS_ACCESS_KEY_ID'] = params[:key]
130
- env_var['AWS_ACCESS_KEY'] = params[:key]
131
- end
132
-
133
- if params[:secret]
134
- env_var['AWS_SECRET_ACCESS_KEY'] = params[:secret]
135
- env_var['AWS_SECRET_KEY'] = params[:secret]
129
+ params.each_key do |param_name|
130
+ AWS_ENV_VARS.each do |var_name|
131
+ if var_name.include?(param_name.to_s.upcase) && !params[param_name].nil?
132
+ env_var[var_name] = params[param_name]
133
+ end
134
+ end
136
135
  end
137
136
 
138
- if params[:token]
139
- env_var['AWS_SECURITY_TOKEN'] = params[:token]
140
- env_var['AWS_SESSION_TOKEN'] = params[:token]
141
- end
142
137
  env_var
143
138
  end
144
139
 
@@ -146,10 +141,11 @@ module Awskeyring
146
141
  #
147
142
  # @param [String] key The aws_access_key_id
148
143
  # @param [String] secret The aws_secret_access_key
149
- def self.verify_cred(key:, secret:)
144
+ # @param [String] token The aws_session_token
145
+ def self.verify_cred(key:, secret:, token:)
150
146
  begin
151
147
  ENV['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
152
- 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)
153
149
  sts.get_caller_identity
154
150
  rescue Aws::Errors::ServiceError => e
155
151
  warn e.to_s
@@ -158,6 +154,26 @@ module Awskeyring
158
154
  true
159
155
  end
160
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
+
161
177
  # Retrieves an AWS Console login url
162
178
  #
163
179
  # @param [String] key The aws_access_key_id
@@ -166,30 +182,22 @@ module Awskeyring
166
182
  # @param [String] user The local username
167
183
  # @param [String] path within the Console to access
168
184
  # @return [String] login_url to access
169
- def self.get_login_url(key:, secret:, token:, path:, user:) # rubocop:disable Metrics/MethodLength
185
+ def self.get_login_url(key:, secret:, token:, path:, user:)
170
186
  console_url = "https://console.aws.amazon.com/#{path}/home"
171
187
 
172
- if token
173
- session_json = {
174
- sessionId: key,
175
- sessionKey: secret,
176
- sessionToken: token
177
- }.to_json
178
- else
179
- ENV['AWS_DEFAULT_REGION'] = 'us-east-1' unless region
180
- sts = Aws::STS::Client.new(access_key_id: key,
181
- secret_access_key: secret)
182
-
183
- session = sts.get_federation_token(name: user,
184
- policy: ADMIN_POLICY,
185
- duration_seconds: TWELVE_HOUR)
186
- session_json = {
187
- sessionId: session.credentials[:access_key_id],
188
- sessionKey: session.credentials[:secret_access_key],
189
- sessionToken: session.credentials[:session_token]
190
- }.to_json
188
+ unless token
189
+ cred = get_token({ key: key, secret: secret, user: user, duration: TWELVE_HOUR })
190
+ key = cred[:key]
191
+ secret = cred[:secret]
192
+ token = cred[:token]
191
193
  end
192
194
 
195
+ session_json = {
196
+ sessionId: key,
197
+ sessionKey: secret,
198
+ sessionToken: token
199
+ }.to_json
200
+
193
201
  destination_param = '&Destination=' + CGI.escape(console_url)
194
202
 
195
203
  AWS_SIGNIN_URL + '?Action=login' + token_param(session_json: session_json) + destination_param
@@ -235,10 +243,10 @@ module Awskeyring
235
243
  exit 1
236
244
  end
237
245
 
238
- new_key = iam.create_access_key
246
+ new_key = iam.create_access_key[:access_key]
239
247
  iam = Aws::IAM::Client.new(
240
- access_key_id: new_key[:access_key][:access_key_id],
241
- secret_access_key: new_key[:access_key][:secret_access_key]
248
+ access_key_id: new_key[:access_key_id],
249
+ secret_access_key: new_key[:secret_access_key]
242
250
  )
243
251
  retry_backoff do
244
252
  iam.delete_access_key(
@@ -247,8 +255,8 @@ module Awskeyring
247
255
  end
248
256
  {
249
257
  account: account,
250
- key: new_key[:access_key][:access_key_id],
251
- secret: new_key[:access_key][:secret_access_key]
258
+ key: new_key[:access_key_id],
259
+ secret: new_key[:secret_access_key]
252
260
  }
253
261
  end
254
262
 
@@ -9,7 +9,7 @@ module Awskeyring
9
9
  #
10
10
  # @param [String] account_name the associated account name.
11
11
  def self.account_name(account_name)
12
- raise 'Invalid Account Name' unless account_name =~ /\S+/
12
+ raise 'Invalid Account Name' unless /\S+/.match?(account_name)
13
13
 
14
14
  account_name
15
15
  end
@@ -18,7 +18,7 @@ module Awskeyring
18
18
  #
19
19
  # @param [String] aws_access_key The aws_access_key_id
20
20
  def self.access_key(aws_access_key)
21
- raise 'Invalid Access Key' unless aws_access_key =~ /\AAKIA[A-Z0-9]{12,16}\z/
21
+ raise 'Invalid Access Key' unless /\AAKIA[A-Z0-9]{12,16}\z/.match?(aws_access_key)
22
22
 
23
23
  aws_access_key
24
24
  end
@@ -36,7 +36,7 @@ module Awskeyring
36
36
  #
37
37
  # @param [String] mfa_arn The users MFA arn
38
38
  def self.mfa_arn(mfa_arn)
39
- raise 'Invalid MFA ARN' unless mfa_arn =~ %r(\Aarn:aws:iam::[0-9]{12}:mfa\/\S*\z)
39
+ raise 'Invalid MFA ARN' unless %r(\Aarn:aws:iam::[0-9]{12}:mfa/\S*\z).match?(mfa_arn)
40
40
 
41
41
  mfa_arn
42
42
  end
@@ -45,7 +45,7 @@ module Awskeyring
45
45
  #
46
46
  # @param [String] role_name
47
47
  def self.role_name(role_name)
48
- raise 'Invalid Role Name' unless role_name =~ /\S+/
48
+ raise 'Invalid Role Name' unless /\S+/.match?(role_name)
49
49
 
50
50
  role_name
51
51
  end
@@ -54,7 +54,7 @@ module Awskeyring
54
54
  #
55
55
  # @param [String] role_arn The role arn
56
56
  def self.role_arn(role_arn)
57
- raise 'Invalid Role ARN' unless role_arn =~ %r(\Aarn:aws:iam::[0-9]{12}:role\/\S*\z)
57
+ raise 'Invalid Role ARN' unless %r(\Aarn:aws:iam::[0-9]{12}:role/\S*\z).match?(role_arn)
58
58
 
59
59
  role_arn
60
60
  end
@@ -63,7 +63,7 @@ module Awskeyring
63
63
  #
64
64
  # @param [String] mfa_code The mfa code
65
65
  def self.mfa_code(mfa_code)
66
- raise 'Invalid MFA CODE' unless mfa_code =~ /\A\d{6}\z/
66
+ raise 'Invalid MFA CODE' unless /\A\d{6}\z/.match?(mfa_code)
67
67
 
68
68
  mfa_code
69
69
  end
@@ -1,8 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+
5
+ # Awskeyring Module,
6
+ # Version const and query of latest.
3
7
  module Awskeyring
4
8
  # The Gem's version number
5
- VERSION = '1.2.0'
9
+ VERSION = '1.4.0'
6
10
  # The Gem's homepage
7
11
  HOMEPAGE = 'https://github.com/servian/awskeyring'
12
+
13
+ # RubyGems Version url
14
+ GEM_VERSION_URL = 'https://rubygems.org/api/v1/versions/awskeyring/latest.json'
15
+
16
+ # Retrieve the latest version from RubyGems
17
+ #
18
+ def self.latest_version
19
+ uri = URI(GEM_VERSION_URL)
20
+ request = Net::HTTP.new(uri.host, uri.port)
21
+ request.use_ssl = true
22
+ JSON.parse(request.get(uri).body)['version']
23
+ end
8
24
  end
@@ -34,9 +34,13 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
34
34
  end
35
35
 
36
36
  desc '--version, -v', I18n.t('__version.desc')
37
+ method_option 'no-remote', type: :boolean, aliases: '-r', desc: I18n.t('method_option.noremote'), default: false
37
38
  # print the version number
38
39
  def __version
39
40
  puts "Awskeyring v#{Awskeyring::VERSION}"
41
+ if !options['no-remote'] && Awskeyring::VERSION != Awskeyring.latest_version
42
+ puts "the latest version v#{Awskeyring.latest_version}"
43
+ end
40
44
  puts "Homepage #{Awskeyring::HOMEPAGE}"
41
45
  end
42
46
 
@@ -118,6 +122,42 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
118
122
  )
119
123
  end
120
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
+
121
161
  desc 'exec ACCOUNT command...', I18n.t('exec.desc')
122
162
  method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false
123
163
  # execute an external command with env set
@@ -159,7 +199,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
159
199
  existing: options[:mfa], message: I18n.t('message.mfa'),
160
200
  flags: 'optional', validator: Awskeyring::Validate.method(:mfa_arn)
161
201
  )
162
- 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']
163
203
  Awskeyring.add_account(
164
204
  account: account,
165
205
  key: key,
@@ -231,8 +271,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
231
271
  # remove a session token
232
272
  def remove_token(account = nil)
233
273
  account = ask_check(
234
- existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_exists),
235
- 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
236
276
  )
237
277
  Awskeyring.delete_token(account: account, message: I18n.t('message.deltoken', account: account))
238
278
  end
@@ -285,7 +325,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
285
325
  method_option :code, type: :string, aliases: '-c', desc: I18n.t('method_option.code')
286
326
  method_option :duration, type: :string, aliases: '-d', desc: I18n.t('method_option.duration')
287
327
  # generate a sessiopn token
288
- def token(account = nil, role = nil, code = nil) # rubocop:disable all
328
+ def token(account = nil, role = nil, code = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
289
329
  account = ask_check(
290
330
  existing: account,
291
331
  message: I18n.t('message.account'),
@@ -305,19 +345,13 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
305
345
  existing: code, message: I18n.t('message.code'), validator: Awskeyring::Validate.method(:mfa_code)
306
346
  )
307
347
  end
308
- duration = options[:duration]
309
- duration ||= Awskeyring::Awsapi::ONE_HOUR.to_s if role
310
- duration ||= Awskeyring::Awsapi::TWELVE_HOUR.to_s if code
311
- duration ||= Awskeyring::Awsapi::ONE_HOUR.to_s
312
-
313
348
  item_hash = age_check_and_get(account: account, no_token: true)
314
- role_arn = Awskeyring.get_role_arn(role_name: role) if role
315
349
 
316
350
  begin
317
351
  new_creds = Awskeyring::Awsapi.get_token(
318
352
  code: code,
319
- role_arn: role_arn,
320
- duration: duration,
353
+ role_arn: (Awskeyring.get_role_arn(role_name: role) if role),
354
+ duration: default_duration(options[:duration], role, code),
321
355
  mfa: item_hash[:mfa],
322
356
  key: item_hash[:key],
323
357
  secret: item_hash[:secret],
@@ -417,6 +451,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
417
451
  comp_len = 2
418
452
  when '--path', '-p'
419
453
  comp_len = 4
454
+ when 'remove-token', 'rmt'
455
+ comp_len = 5
420
456
  end
421
457
 
422
458
  [curr, comp_len, sub_cmd]
@@ -432,7 +468,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
432
468
  self.class.map[sub_cmd].to_s
433
469
  end
434
470
 
435
- def print_auto_resp(curr, len, sub_cmd)
471
+ def print_auto_resp(curr, len, sub_cmd) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
436
472
  list = []
437
473
  case len
438
474
  when 0
@@ -445,6 +481,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
445
481
  list = list_arguments(command: sub_cmd)
446
482
  when 4
447
483
  list = Awskeyring.list_console_path
484
+ when 5
485
+ list = Awskeyring.list_token_names
448
486
  else
449
487
  exit 1
450
488
  end
@@ -467,6 +505,12 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
467
505
  Awskeyring::Awsapi::AWS_ENV_VARS.each { |key| puts "unset #{key}" unless env_var.key?(key) }
468
506
  end
469
507
 
508
+ def default_duration(duration, role, code)
509
+ duration ||= Awskeyring::Awsapi::ONE_HOUR.to_s if role
510
+ duration ||= Awskeyring::Awsapi::TWELVE_HOUR.to_s if code
511
+ duration || Awskeyring::Awsapi::ONE_HOUR.to_s
512
+ end
513
+
470
514
  def ask_check(existing:, message:, flags: nil, validator: nil, limited_to: nil) # rubocop:disable Metrics/MethodLength
471
515
  retries ||= 3
472
516
  begin
@@ -0,0 +1,194 @@
1
+ .\" generated with Ronn/v0.7.3
2
+ .\" http://github.com/rtomayko/ronn/tree/0.7.3
3
+ .
4
+ .TH "AWSKEYRING" "5" "June 2020" "" ""
5
+ .
6
+ .SH "NAME"
7
+ \fBAwskeyring\fR \- is a small tool to manage AWS account keys in the macOS Keychain
8
+ .
9
+ .SH "SYNOPSIS"
10
+ awskeyring COMMAND [ACCOUNT|ROLE] [OPTIONS]
11
+ .
12
+ .P
13
+ awskeyring help COMMAND
14
+ .
15
+ .SH "DESCRIPTION"
16
+ The Awskeyring utility stores and manages AWS access keys and provides the facility to generate access tokens with combinations of assumed roles and multi\-factor\-authentication codes\. It includes autocompletion features and multiple validation checks for input parsing\. It also includes the ability for the AWS CLI to call it directly to provide authentication\.
17
+ .
18
+ .P
19
+ The commands are as follows:
20
+ .
21
+ .TP
22
+ \-\-version, \-v:
23
+ .
24
+ .IP
25
+ Prints the version
26
+ .
27
+ .TP
28
+ add ACCOUNT:
29
+ .
30
+ .IP
31
+ Adds an ACCOUNT to the keyring
32
+ .
33
+ .TP
34
+ add\-role ROLE:
35
+ .
36
+ .IP
37
+ Adds a ROLE to the keyring
38
+ .
39
+ .TP
40
+ console ACCOUNT:
41
+ .
42
+ .IP
43
+ Open the AWS Console for the ACCOUNT
44
+ .
45
+ .TP
46
+ env ACCOUNT:
47
+ .
48
+ .IP
49
+ Outputs bourne shell environment exports for an ACCOUNT
50
+ .
51
+ .TP
52
+ exec ACCOUNT command\.\.\.:
53
+ .
54
+ .IP
55
+ Execute a COMMAND with the environment set for an ACCOUNT
56
+ .
57
+ .TP
58
+ help [COMMAND]:
59
+ .
60
+ .IP
61
+ Describe available commands or one specific command
62
+ .
63
+ .TP
64
+ import:
65
+ .
66
+ .IP
67
+ Import an ACCOUNT to the keyring from ~/\.aws/credentials
68
+ .
69
+ .TP
70
+ initialise:
71
+ .
72
+ .IP
73
+ Initialises a new KEYCHAIN
74
+ .
75
+ .TP
76
+ json ACCOUNT:
77
+ .
78
+ .IP
79
+ Outputs AWS CLI compatible JSON for an ACCOUNT
80
+ .
81
+ .TP
82
+ list:
83
+ .
84
+ .IP
85
+ Prints a list of accounts in the keyring
86
+ .
87
+ .TP
88
+ list\-role:
89
+ .
90
+ .IP
91
+ Prints a list of roles in the keyring
92
+ .
93
+ .TP
94
+ remove ACCOUNT:
95
+ .
96
+ .IP
97
+ Removes an ACCOUNT from the keyring
98
+ .
99
+ .TP
100
+ remove\-role ROLE:
101
+ .
102
+ .IP
103
+ Removes a ROLE from the keyring
104
+ .
105
+ .TP
106
+ remove\-token ACCOUNT:
107
+ .
108
+ .IP
109
+ Removes a token for ACCOUNT from the keyring
110
+ .
111
+ .TP
112
+ rotate ACCOUNT:
113
+ .
114
+ .IP
115
+ Rotate access keys for an ACCOUNT
116
+ .
117
+ .TP
118
+ token ACCOUNT [ROLE] [MFA]:
119
+ .
120
+ .IP
121
+ Create an STS Token from a ROLE or an MFA code
122
+ .
123
+ .TP
124
+ update ACCOUNT:
125
+ .
126
+ .IP
127
+ Updates an ACCOUNT in the keyring
128
+ .
129
+ .SH "ENVIRONMENT"
130
+ The AWS_DEFAULT_REGION environment variable will be used for AWS API calls where specified or fall back to us\-east\-1 when not\.
131
+ .
132
+ .SH "EXIT STATUS"
133
+ The Awskeyring utility exits 0 on success, and >0 if an error occurs\.
134
+ .
135
+ .SH "EXAMPLES"
136
+ First you need to initialise your keychain to hold your AWS credentials\.
137
+ .
138
+ .IP "" 4
139
+ .
140
+ .nf
141
+
142
+ awskeyring initialise
143
+ .
144
+ .fi
145
+ .
146
+ .IP "" 0
147
+ .
148
+ .P
149
+ Then add your keys to it\.
150
+ .
151
+ .IP "" 4
152
+ .
153
+ .nf
154
+
155
+ awskeyring add personal\-aws
156
+ .
157
+ .fi
158
+ .
159
+ .IP "" 0
160
+ .
161
+ .P
162
+ Now your keys are stored safely in the macOS keychain\. To print environment variables run\.\.\.
163
+ .
164
+ .IP "" 4
165
+ .
166
+ .nf
167
+
168
+ awskeyring env personal\-aws
169
+ .
170
+ .fi
171
+ .
172
+ .IP "" 0
173
+ .
174
+ .SH "HISTORY"
175
+ The motivation of this application is to provide a local secure store of AWS credentials using specifically in the macOS Keychain, to have them easily accessed from the Terminal, and to provide useful functions like assuming roles and opening the AWS Console from the cli\. For Enterprise environments there are better suited tools to use like HashiCorp Vault \fIhttps://vaultproject\.io/\fR\.
176
+ .
177
+ .SH "SECURITY"
178
+ If you believe you have found a security issue in Awskeyring, please responsibly disclose by contacting me at \fItristan\.morgan@servian\.com\fR\. Awskeyring is a Ruby script and as such Ruby is whitelisted to access your "awskeyring" keychain\. Use a strong password and keep the unlock time short\.
179
+ .
180
+ .SH "AUTHOR"
181
+ Tristan Morgan \fItristan\.morgan@servian\.com\fR is the maintainer of Awskeyring\.
182
+ .
183
+ .SH "CONTRIBUTORS"
184
+ .
185
+ .IP "\(bu" 4
186
+ Tristan tristanmorgan \fIhttps://github\.com/tristanmorgan\fR
187
+ .
188
+ .IP "\(bu" 4
189
+ Adam Sir AzySir \fIhttps://github\.com/AzySir\fR
190
+ .
191
+ .IP "" 0
192
+ .
193
+ .SH "LICENSE"
194
+ The gem is available as open source under the terms of the MIT License \fIhttps://opensource\.org/licenses/MIT\fR\.
@@ -0,0 +1,138 @@
1
+ # Awskeyring -- is a small tool to manage AWS account keys in the macOS Keychain
2
+
3
+ ## SYNOPSIS
4
+
5
+ awskeyring COMMAND [ACCOUNT|ROLE] [OPTIONS]
6
+
7
+ awskeyring help COMMAND
8
+
9
+ ## DESCRIPTION
10
+
11
+ The Awskeyring utility stores and manages AWS access keys and provides the facility to generate access tokens with
12
+ combinations of assumed roles and multi-factor-authentication codes. It includes autocompletion features and multiple
13
+ validation checks for input parsing. It also includes the ability for the AWS CLI to call it directly to provide authentication.
14
+
15
+ The commands are as follows:
16
+
17
+ * --version, -v:
18
+
19
+ Prints the version
20
+
21
+ * add ACCOUNT:
22
+
23
+ Adds an ACCOUNT to the keyring
24
+
25
+ * add-role ROLE:
26
+
27
+ Adds a ROLE to the keyring
28
+
29
+ * console ACCOUNT:
30
+
31
+ Open the AWS Console for the ACCOUNT
32
+
33
+ * env ACCOUNT:
34
+
35
+ Outputs bourne shell environment exports for an ACCOUNT
36
+
37
+ * exec ACCOUNT command...:
38
+
39
+ Execute a COMMAND with the environment set for an ACCOUNT
40
+
41
+ * help [COMMAND]:
42
+
43
+ Describe available commands or one specific command
44
+
45
+ * import:
46
+
47
+ Import an ACCOUNT to the keyring from ~/.aws/credentials
48
+
49
+ * initialise:
50
+
51
+ Initialises a new KEYCHAIN
52
+
53
+ * json ACCOUNT:
54
+
55
+ Outputs AWS CLI compatible JSON for an ACCOUNT
56
+
57
+ * list:
58
+
59
+ Prints a list of accounts in the keyring
60
+
61
+ * list-role:
62
+
63
+ Prints a list of roles in the keyring
64
+
65
+ * remove ACCOUNT:
66
+
67
+ Removes an ACCOUNT from the keyring
68
+
69
+ * remove-role ROLE:
70
+
71
+ Removes a ROLE from the keyring
72
+
73
+ * remove-token ACCOUNT:
74
+
75
+ Removes a token for ACCOUNT from the keyring
76
+
77
+ * rotate ACCOUNT:
78
+
79
+ Rotate access keys for an ACCOUNT
80
+
81
+ * token ACCOUNT [ROLE] [MFA]:
82
+
83
+ Create an STS Token from a ROLE or an MFA code
84
+
85
+ * update ACCOUNT:
86
+
87
+ Updates an ACCOUNT in the keyring
88
+
89
+ ## ENVIRONMENT
90
+
91
+ The AWS_DEFAULT_REGION environment variable will be used for AWS API calls where specified or fall back to us-east-1
92
+ when not.
93
+
94
+ ## EXIT STATUS
95
+
96
+ The Awskeyring utility exits 0 on success, and >0 if an error occurs.
97
+
98
+ ## EXAMPLES
99
+
100
+ First you need to initialise your keychain to hold your AWS credentials.
101
+
102
+ awskeyring initialise
103
+
104
+ Then add your keys to it.
105
+
106
+ awskeyring add personal-aws
107
+
108
+ Now your keys are stored safely in the macOS keychain. To print environment variables run...
109
+
110
+ awskeyring env personal-aws
111
+
112
+ ## HISTORY
113
+
114
+ The motivation of this application is to provide a local secure store of AWS
115
+ credentials using specifically in the macOS Keychain, to have them easily accessed
116
+ from the Terminal, and to provide useful functions like assuming roles and opening
117
+ the AWS Console from the cli.
118
+ For Enterprise environments there are better suited tools to use
119
+ like [HashiCorp Vault](https://vaultproject.io/).
120
+
121
+ ## SECURITY
122
+
123
+ If you believe you have found a security issue in Awskeyring, please responsibly disclose by contacting me at
124
+ [tristan.morgan@servian.com](mailto:tristan.morgan@servian.com). Awskeyring is a Ruby script and as such Ruby is whitelisted to
125
+ access your "awskeyring" keychain. Use a strong password and keep the unlock time short.
126
+
127
+ ## AUTHOR
128
+
129
+ Tristan Morgan <tristan.morgan@servian.com> is the maintainer of Awskeyring.
130
+
131
+ ## CONTRIBUTORS
132
+
133
+ * Tristan [tristanmorgan](https://github.com/tristanmorgan)
134
+ * Adam Sir [AzySir](https://github.com/AzySir)
135
+
136
+ ## LICENSE
137
+
138
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
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.2.0
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-01-20 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
@@ -67,8 +67,7 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  description: Manages AWS credentials in the macOS keychain
70
- email:
71
- - tristan@vibrato.com.au
70
+ email: tristan.morgan@servian.com
72
71
  executables:
73
72
  - awskeyring
74
73
  extensions: []
@@ -90,10 +89,17 @@ files:
90
89
  - lib/awskeyring/validate.rb
91
90
  - lib/awskeyring/version.rb
92
91
  - lib/awskeyring_command.rb
92
+ - man/awskeyring.5
93
+ - man/awskeyring.5.ronn
93
94
  homepage: https://github.com/servian/awskeyring
94
95
  licenses:
95
96
  - MIT
96
- metadata: {}
97
+ metadata:
98
+ bug_tracker_uri: https://github.com/servian/awskeyring/issues
99
+ changelog_uri: https://github.com/servian/awskeyring/blob/master/CHANGELOG.md
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
+ wiki_uri: https://github.com/servian/awskeyring/wiki
97
103
  post_install_message:
98
104
  rdoc_options: []
99
105
  require_paths: