awskeyring 1.12.0 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73c6d89c7a836a7f9b8d75bbb1bde93a27792dbfbdc4c8cc563b0f1b4127f811
4
- data.tar.gz: fe93e67911337c48cd21c8207bec071de5c5991bbbcccb96fdfc36b2728c346c
3
+ metadata.gz: 77b3d983a4ed2fefb518f35a38a93070b200b7c6d6a22cb189bf3df954636c6b
4
+ data.tar.gz: '085d5f2dd6622efd844dcbb952a92030ed9cafb4e52098f96b7fee904c3a5739'
5
5
  SHA512:
6
- metadata.gz: e91c2c5df102632b00cb823943381c4b1548c2baec16bb72c58724b5e0f790cc2eddac774e96efcc072bd8283efdc356e3ef77a39374659030f1fb4ff4c58ce4
7
- data.tar.gz: 70cb85135e88d82902dd3f30e2cd8428f6534480d49c75dfb79001525b31c687bfb11c0df3cc35afe97f41a88e9aa32fc48626539c6788cff0c1c607efbf0a33
6
+ metadata.gz: cb99fad81b567e8db647ad41b7c3d56c2a42000006c5ef1f9adc9c72db3f524a043c6a0e55d17e82977b9308e242604f5fe4473ab49065698ec440d95fe09727
7
+ data.tar.gz: f39f3e192b664eab640662e0e74c3d1db37939a4048ee6990c8e1bb411f9b053b24c2dc8614b8ea5f46bc2509a1419b1f32ef5b9799fa6b8284a0930ff4056d9
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2016-2022 Tristan Morgan
3
+ Copyright (c) 2016-2025 Tristan Morgan
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  ![Awskeyring](https://raw.githubusercontent.com/tristanmorgan/awskeyring/main/awskeyring-144.png)
4
4
 
5
+ * ![Build Passing](https://github.com/tristanmorgan/awskeyring/actions/workflows/ruby.yml/badge.svg)
5
6
  * [![Gem Version](https://img.shields.io/gem/v/awskeyring)](https://badge.fury.io/rb/awskeyring)
6
7
  * [![license MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)
7
8
  * [![All Downloads](https://img.shields.io/gem/dt/awskeyring)](https://rubygems.org/gems/awskeyring)
@@ -11,6 +12,11 @@
11
12
  Awskeyring is a small tool to manage AWS account keys in the macOS Keychain. It has
12
13
  grown to incorporate a lot of [features](https://github.com/tristanmorgan/awskeyring/wiki/Awskeyring-features).
13
14
 
15
+ ## Project Status
16
+
17
+ Awskeyring is a fairly mature project so it it doesn't see frequent updates but is still being maintained.
18
+ It is tested against the version of Ruby that is shipped with the latest version of macOS, but that ruby version is dated.
19
+
14
20
  ## Motivation
15
21
 
16
22
  The motivation of this application is to provide a local secure store of AWS
data/i18n/en.yml CHANGED
@@ -33,6 +33,7 @@ en:
33
33
  notoken: 'Do not use saved token.'
34
34
  noremote: 'Do not validate with remote api.'
35
35
  path: 'The service PATH to open.'
36
+ test: 'Generate test credentials.'
36
37
  browser: 'Specify an alternative browser.'
37
38
  secret: 'AWS account secret.'
38
39
  unset: 'Unset environment variables.'
@@ -3,6 +3,7 @@
3
3
  require 'aws-sdk-iam'
4
4
  require 'cgi'
5
5
  require 'json'
6
+ require 'securerandom'
6
7
 
7
8
  # Awskeyring Module,
8
9
  # gives you an interface to access keychains and items.
@@ -180,6 +181,23 @@ module Awskeyring
180
181
  }
181
182
  end
182
183
 
184
+ # Generate test credentials for AWS
185
+ #
186
+ # @return [Hash] with the new credentials
187
+ # key The aws_access_key_id
188
+ # secret The aws_secret_access_key
189
+ # expiry expiry time
190
+ def self.gen_test_credentials(account:)
191
+ {
192
+ account: account,
193
+ key: "AKIA#{Array.new(16) { [*'A'..'Z', *'2'..'7'].sample }.join}",
194
+ secret: SecureRandom.base64(30),
195
+ token: nil,
196
+ expiry: nil,
197
+ role: nil
198
+ }
199
+ end
200
+
183
201
  # Retrieves an AWS Console login url
184
202
  #
185
203
  # @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.12.0'
9
+ VERSION = '1.13.0'
10
10
  # The Gem's homepage
11
11
  HOMEPAGE = 'https://github.com/tristanmorgan/awskeyring'
12
12
 
@@ -109,10 +109,15 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
109
109
  desc 'env ACCOUNT', I18n.t('env_desc')
110
110
  method_option :force, type: :boolean, aliases: '-f', desc: I18n.t('method_option.force'), default: false
111
111
  method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false
112
+ method_option :test, type: :boolean, aliases: '-t', desc: I18n.t('method_option.test'), default: false
112
113
  method_option :unset, type: :boolean, aliases: '-u', desc: I18n.t('method_option.unset'), default: false
113
114
  # Print Env vars
114
115
  def env(account = nil)
115
- if options[:unset]
116
+ if options[:test]
117
+ account ||= 'fakeaccount'
118
+ cred = Awskeyring::Awsapi.gen_test_credentials(account: account)
119
+ put_env_string(cred)
120
+ elsif options[:unset]
116
121
  put_env_string(account: nil, key: nil, secret: nil, token: nil)
117
122
  else
118
123
  output_safe(options[:force])
@@ -129,21 +134,32 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
129
134
  desc 'json ACCOUNT', I18n.t('json_desc')
130
135
  method_option :force, type: :boolean, aliases: '-f', desc: I18n.t('method_option.force'), default: false
131
136
  method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false
137
+ method_option :test, type: :boolean, aliases: '-t', desc: I18n.t('method_option.test'), default: false
132
138
  # Print JSON for use with credential_process
133
- def json(account) # rubocop:disable Metrics/AbcSize
134
- output_safe(options[:force])
135
- account = ask_check(
136
- existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_exists),
137
- limited_to: Awskeyring.list_account_names
138
- )
139
- cred = age_check_and_get(account: account, no_token: options['no-token'])
140
- expiry = Time.at(cred[:expiry]) unless cred[:expiry].nil?
141
- puts Awskeyring::Awsapi.get_cred_json(
142
- key: cred[:key],
143
- secret: cred[:secret],
144
- token: cred[:token],
145
- expiry: (expiry || (Time.new + Awskeyring::Awsapi::ONE_HOUR)).iso8601
146
- )
139
+ def json(account) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
140
+ if options[:test]
141
+ cred = Awskeyring::Awsapi.gen_test_credentials(account: account)
142
+ puts Awskeyring::Awsapi.get_cred_json(
143
+ key: cred[:key],
144
+ secret: cred[:secret],
145
+ token: cred[:token],
146
+ expiry: (Time.new + Awskeyring::Awsapi::TWELVE_HOUR).iso8601
147
+ )
148
+ else
149
+ output_safe(options[:force])
150
+ account = ask_check(
151
+ existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_exists),
152
+ limited_to: Awskeyring.list_account_names
153
+ )
154
+ cred = age_check_and_get(account: account, no_token: options['no-token'])
155
+ expiry = Time.at(cred[:expiry]) unless cred[:expiry].nil?
156
+ puts Awskeyring::Awsapi.get_cred_json(
157
+ key: cred[:key],
158
+ secret: cred[:secret],
159
+ token: cred[:token],
160
+ expiry: (expiry || (Time.new + Awskeyring::Awsapi::ONE_HOUR)).iso8601
161
+ )
162
+ end
147
163
  end
148
164
 
149
165
  desc 'import ACCOUNT', I18n.t('import_desc')
@@ -186,8 +202,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
186
202
  method_option 'no-bundle', type: :boolean, aliases: '-b', desc: I18n.t('method_option.nobundle'), default: false
187
203
  method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false
188
204
  # execute an external command with env set
189
- def exec(account, *command) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
190
- if command.empty?
205
+ def exec(account, *exec) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
206
+ if exec.empty?
191
207
  warn I18n.t('message.exec')
192
208
  exit 1
193
209
  end
@@ -199,7 +215,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
199
215
  env_vars = Awskeyring::Awsapi.get_env_array(cred)
200
216
  unbundle if options['no-bundle']
201
217
  begin
202
- pid = Process.spawn(env_vars, command.join(' '))
218
+ pid = Process.spawn(env_vars, exec.join(' '))
203
219
  Process.wait pid
204
220
  exit 1 if Process.last_status.exitstatus.positive?
205
221
  rescue Errno::ENOENT => e
@@ -456,7 +472,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
456
472
 
457
473
  comp_lines = comp_line[0..(comp_point_str.to_i)].split
458
474
 
459
- comp_type, sub_cmd = comp_type(comp_lines: comp_lines, prev: prev)
475
+ comp_type, sub_cmd = comp_type(comp_lines: comp_lines, prev: prev, curr: curr)
460
476
  list = fetch_auto_resp(comp_type, sub_cmd)
461
477
  puts list.select { |elem| elem.start_with?(curr) }.sort!.join("\n")
462
478
  end
@@ -473,7 +489,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
473
489
  end
474
490
 
475
491
  # determine the type of completion needed
476
- def comp_type(comp_lines:, prev:)
492
+ def comp_type(comp_lines:, prev:, curr:)
477
493
  sub_cmd = sub_command(comp_lines)
478
494
  comp_idx = comp_lines.rindex(prev)
479
495
 
@@ -484,19 +500,19 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
484
500
  comp_type = :browser_type
485
501
  else
486
502
  comp_type = :command
487
- comp_type = param_type(comp_idx, sub_cmd) unless sub_cmd.empty?
503
+ comp_type = param_type(comp_idx, sub_cmd, curr) unless sub_cmd.empty?
488
504
  end
489
505
 
490
506
  [comp_type, sub_cmd]
491
507
  end
492
508
 
493
509
  # check params for named params or fall back to flags
494
- def param_type(comp_idx, sub_cmd)
495
- types = %i[opt req]
510
+ def param_type(comp_idx, sub_cmd, curr)
511
+ types = %i[opt req rest]
496
512
  param_list = method(sub_cmd).parameters.select { |elem| types.include? elem[0] }
497
513
  if comp_idx.zero?
498
514
  :command
499
- elsif comp_idx > param_list.length
515
+ elsif comp_idx > param_list.length || curr.start_with?('-')
500
516
  :flag
501
517
  else
502
518
  param_list[comp_idx - 1][1]
@@ -515,7 +531,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
515
531
  end
516
532
 
517
533
  # given a type return the right list for completions
518
- def fetch_auto_resp(comp_type, sub_cmd)
534
+ def fetch_auto_resp(comp_type, sub_cmd) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
519
535
  case comp_type
520
536
  when :command
521
537
  list_commands
@@ -529,6 +545,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
529
545
  Awskeyring.list_token_names
530
546
  when :browser_type
531
547
  Awskeyring.list_browsers
548
+ when :exec
549
+ list_exec
532
550
  else
533
551
  list_arguments(command: sub_cmd)
534
552
  end
@@ -540,6 +558,17 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
540
558
  commands.reject! { |elem| %w[autocomplete default decode].include?(elem) }
541
559
  end
542
560
 
561
+ # list executables
562
+ def list_exec
563
+ list = []
564
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
565
+ list.concat(Dir.children(File.expand_path(path)))
566
+ rescue Errno::ENOENT
567
+ next
568
+ end
569
+ list.flatten
570
+ end
571
+
543
572
  # list flags for a command
544
573
  def list_arguments(command:)
545
574
  options = self.class.all_commands[command].options.values
data/man/awskeyring.5 CHANGED
@@ -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" "December 2023" "" ""
4
+ .TH "AWSKEYRING" "5" "February 2025" "" ""
5
5
  .
6
6
  .SH "NAME"
7
7
  \fBAwskeyring\fR \- is a small tool to manage AWS account keys in the macOS Keychain
@@ -95,7 +95,10 @@ Outputs bourne shell environment exports for an ACCOUNT
95
95
  \-n, \-\-no\-token: Do not use saved token\.
96
96
  .
97
97
  .br
98
- \-u, \-\-unset, \-\-no\-unset: Unset environment variables\.
98
+ \-t, \-\-test: Generate test credentials\.
99
+ .
100
+ .br
101
+ \-u, \-\-unset: Unset environment variables\.
99
102
  .
100
103
  .TP
101
104
  exec ACCOUNT command\.\.\.:
@@ -153,6 +156,9 @@ Outputs AWS CLI compatible JSON for an ACCOUNT
153
156
  .br
154
157
  \-n, \-\-no\-token: Do not use saved token\.
155
158
  .
159
+ .br
160
+ \-t, \-\-test: Generate test credentials\.
161
+ .
156
162
  .TP
157
163
  list:
158
164
  .
@@ -347,7 +353,7 @@ The motivation of this application is to provide a local secure store of AWS cre
347
353
  If you believe you have found a security issue in Awskeyring, please responsibly disclose by contacting me at \fItristan\.morgan@gmail\.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\.
348
354
  .
349
355
  .SH "AUTHOR"
350
- Tristan Morgan \fItristan\.morgan@gmail\.com\fR is the maintainer of Awskeyring\.
356
+ Tristan Morgan \fItristan\.morgan@gmail\.com\fR is the maintainer and author of Awskeyring\.
351
357
  .
352
358
  .SH "CONTRIBUTORS"
353
359
  .
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.12.0
4
+ version: 1.13.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: 2023-12-04 00:00:00.000000000 Z
11
+ date: 2025-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-iam
@@ -92,9 +92,9 @@ licenses:
92
92
  metadata:
93
93
  bug_tracker_uri: https://github.com/tristanmorgan/awskeyring/issues
94
94
  changelog_uri: https://github.com/tristanmorgan/awskeyring/blob/main/CHANGELOG.md
95
- documentation_uri: https://rubydoc.info/gems/awskeyring/1.12.0
95
+ documentation_uri: https://rubydoc.info/gems/awskeyring/1.13.0
96
96
  rubygems_mfa_required: 'true'
97
- source_code_uri: https://github.com/tristanmorgan/awskeyring/tree/v1.12.0
97
+ source_code_uri: https://github.com/tristanmorgan/awskeyring/tree/v1.13.0
98
98
  wiki_uri: https://github.com/tristanmorgan/awskeyring/wiki
99
99
  post_install_message:
100
100
  rdoc_options: []