aws_runas 0.4.2 → 0.5.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
  SHA1:
3
- metadata.gz: 354da6c78da53eb8386cfb4bd53251271e4f19c3
4
- data.tar.gz: 39b6306ebfe1599e54abb61507d73a0a3e7b428e
3
+ metadata.gz: 9eeec3efe7aee175787d2ac5479086e7fed933ef
4
+ data.tar.gz: cf85fb2f0b0da64650789774d7b197d46b94a21d
5
5
  SHA512:
6
- metadata.gz: 26d43b13c4c6f7b051f88a053da1ee80ab15b3bc6e9d854eecf9a3db8dc4b952f3dafd35c52e386e48083a8e9137b1fd17536f1532990b5f51e450e5411286e5
7
- data.tar.gz: 416193ead9c704909597dd3ee6d94da7b02b0e1845f89a801309f0a764ee7db1a3f5b53ae5bd550826cb5faf796a0d9303980bf202a645d500ee6580fb5c749f
6
+ metadata.gz: 553fb10ff06a4aad52e00e44c5bb97a8dc2c14b23c4d36817162e129789105d8d6e8b4bb076c092e784167a6df343937adad70e3176760d3fb875184ebf8a62f
7
+ data.tar.gz: 11ec64975cc9e6396d32c2b58e60ec411d94d2c684093a5ada606ef288de810ab5672073c9d5ce361d5e3589ce7aba12977169fef16dff5f54545ca9b92d1675
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,45 @@
1
+ ## v0.5.0
2
+
3
+ ### Zsh Support
4
+
5
+ `zsh` is now supported for the fancy prompt. When using the shell, your
6
+ existing profile data from `.zshrc` will be copied over into the temporary
7
+ configuration.
8
+
9
+ ### Additional Functionality for Bash and Zsh
10
+
11
+ 2 additional functions are available for `bash` and `zsh` as well:
12
+
13
+ * `aws_session_expired`, which reads `AWS_SESSION_EXPIRATION_UNIX` (see below)
14
+ and compares this with the current Unix timestamp supplied by `date`. It
15
+ returns 0 on true and 1 on false, which can be used semantically in shell
16
+ scripts.
17
+ * `aws_session_status_color`, which works off of `aws_session_expired` to
18
+ render an ANSI numeric color code - red when `aws_session_expired` is `true`,
19
+ yellow otherwise.
20
+
21
+ The prompts for `bash` and `zsh` now work off of these functions to render the
22
+ right color. The prompt will go red when the session has expired.
23
+
24
+ ### Skip Fancy Interactive Prompt
25
+
26
+ The default interactive prompt that you get when you run `aws-runas` with no
27
+ command supplied can now by skipped by adding `--skip-prompt` to the CLI
28
+ arguments. The profile functions mentioned above are still passed in. This
29
+ allows you to leverage their functionality inside your own scripts and custom
30
+ prompts if you want in other ways.
31
+
32
+ ### Additional Variables
33
+
34
+ Several environment variables have been added for more quality-of-life when
35
+ working in the shell or aware tools:
36
+
37
+ * `AWS_REGION` and `AWS_DEFAULT_REGION`, which pass through the region
38
+ configured in the profile, if present
39
+ * `AWS_SESSION_EXPIRATION` and `AWS_SESSION_EXPIRATION_UNIX` to supply the
40
+ session expiration time, in both human and UNIX timestamps, respectively
41
+ named.
42
+
1
43
  ## v0.4.2
2
44
 
3
45
  The role that aws-runas assumed and the profile it used are now exposed as
data/README.md CHANGED
@@ -51,14 +51,39 @@ help you determine what credentials are in use locally:
51
51
  * `AWS_RUNAS_ASSUMED_ROLE_ARN` - set when a role is assumed (not set if
52
52
  `--no-role` is used)
53
53
  * `AWS_RUNAS_PROFILE` - set with the profile used when `aws-runas` was run
54
+ * `AWS_REGION` and `AWS_DEFAULT_REGION` - set with the region name defined in
55
+ the profile being used
56
+ * `AWS_SESSION_EXPIRATION` - set with the expiry timestamp in UTC
57
+ * `AWS_SESSION_EXPIRATION_UNIX` - set with the expiry timestamp in Unix time,
58
+ useful for scripting
54
59
 
55
- ### Fancy Bash Prompt
60
+ ### Fancy Bash/Zsh Prompt
56
61
 
57
- If you use `aws-runas` without any options and your default shell is Bash, a
58
- colorized prompt will appear with the profile that is in use if a role is
62
+ If you use `aws-runas` without any options and your default shell is Bash or
63
+ Zsh, a colorized prompt will appear with the profile that is in use if a role is
59
64
  assumed, or a simple `(AWS)` indicator added to the prompt if a session token is
60
65
  only obtained. See the video at the start of the doc for a demo!
61
66
 
67
+ #### Shell Integration Functions
68
+
69
+ 2 functions currently get exported when you run under one of the two supported
70
+ shells:
71
+
72
+ * `aws_session_expired`, which reads `AWS_SESSION_EXPIRATION_UNIX` (see above)
73
+ and compares this with the current Unix timestamp supplied by `date`. It
74
+ returns 0 on true and 1 on false, which can be used semantically in shell
75
+ scripts.
76
+ * `aws_session_status_color`, which works off of `aws_session_expired` to
77
+ render an ANSI numeric color code - red when `aws_session_expired` is `true`,
78
+ yellow otherwise.
79
+
80
+ #### Skipping the Fancy Prompt
81
+
82
+ If you are doing your own prompt customization based on aws-runas data and don't
83
+ want the prompt modified, you can supply `--skip-prompt` to skip the prompt
84
+ modification. The aforementioned integration functions will still be available
85
+ to you however, which you can use in your own scripts.
86
+
62
87
  Usage
63
88
  ------
64
89
 
@@ -76,6 +101,7 @@ depending on your system) will launch.
76
101
 
77
102
  [options] are:
78
103
  -n, --no-role Get a session token only, do not assume a role
104
+ -s, --skip-prompt Do not launch interactive sessions with the fancy prompt
79
105
  -p, --path=<s> Path to the AWS config file
80
106
  -r, --profile=<s> The AWS profile to load (default: default)
81
107
  -h, --help Show this message
@@ -37,6 +37,7 @@ module AwsRunAs
37
37
  EOS
38
38
 
39
39
  opt :no_role, 'Get a session token only, do not assume a role', type: TrueClass, default: nil
40
+ opt :skip_prompt, 'Do not launch interactive sessions with the fancy prompt', type: TrueClass, default: nil
40
41
  opt :path, 'Path to the AWS config file', type: String
41
42
  opt :profile, 'The AWS profile to load', type: String, default: 'default'
42
43
  stop_on_unknown
@@ -51,7 +52,7 @@ module AwsRunAs
51
52
  @main = AwsRunAs::Main.new(path: opts[:path], profile: opts[:profile], mfa_code: mfa_code, no_role: opts[:no_role])
52
53
  @main.assume_role
53
54
  command = ARGV.shift
54
- @main.handoff(command: command, argv: ARGV)
55
+ @main.handoff(command: command, argv: ARGV, skip_prompt: opts[:skip_prompt])
55
56
  end
56
57
 
57
58
  # Reads the MFA code from standard input.
@@ -52,35 +52,52 @@ module AwsRunAs
52
52
  mfa_serial = @cfg.load_config_value(key: 'mfa_serial') unless ENV.include?('AWS_SESSION_TOKEN')
53
53
  if @no_role
54
54
  raise 'No mfa_serial in selected profile, session will be useless' if mfa_serial.nil?
55
- @role_credentials = sts_client.get_session_token(
55
+ @session = sts_client.get_session_token(
56
56
  duration_seconds: 3600,
57
57
  serial_number: mfa_serial,
58
58
  token_code: @mfa_code
59
- ).credentials
59
+ )
60
60
  else
61
- @role_credentials = Aws::AssumeRoleCredentials.new(
61
+ @session = Aws::AssumeRoleCredentials.new(
62
62
  client: sts_client,
63
63
  role_arn: role_arn,
64
64
  serial_number: mfa_serial,
65
65
  token_code: @mfa_code,
66
66
  role_session_name: session_id
67
- ).credentials
67
+ )
68
68
  end
69
69
  end
70
70
 
71
+ def session_credentials
72
+ @session.credentials
73
+ end
74
+
71
75
  def credentials_env
72
76
  env = {}
73
- env['AWS_ACCESS_KEY_ID'] = @role_credentials.access_key_id
74
- env['AWS_SECRET_ACCESS_KEY'] = @role_credentials.secret_access_key
75
- env['AWS_SESSION_TOKEN'] = @role_credentials.session_token
77
+ env['AWS_ACCESS_KEY_ID'] = session_credentials.access_key_id
78
+ env['AWS_SECRET_ACCESS_KEY'] = session_credentials.secret_access_key
79
+ env['AWS_SESSION_TOKEN'] = session_credentials.session_token
76
80
  env['AWS_RUNAS_PROFILE'] = @cfg.profile
77
- env['AWS_RUNAS_ASSUMED_ROLE_ARN'] = @cfg.load_config_value(key: 'role_arn') unless @no_role
81
+ unless @cfg.load_config_value(key: 'region').nil?
82
+ env['AWS_REGION'] = @cfg.load_config_value(key: 'region')
83
+ env['AWS_DEFAULT_REGION'] = @cfg.load_config_value(key: 'region')
84
+ end
85
+ if @no_role
86
+ env['AWS_SESSION_EXPIRATION'] = session_credentials.expiration.to_s
87
+ env['AWS_SESSION_EXPIRATION_UNIX'] = DateTime.parse(session_credentials.expiration.to_s).strftime('%s')
88
+ else
89
+ env['AWS_SESSION_EXPIRATION'] = @session.expiration.to_s
90
+ env['AWS_SESSION_EXPIRATION_UNIX'] = DateTime.parse(@session.expiration.to_s).strftime('%s')
91
+ env['AWS_RUNAS_ASSUMED_ROLE_ARN'] = @cfg.load_config_value(key: 'role_arn')
92
+ end
78
93
  env
79
94
  end
80
95
 
81
- def handoff(command: nil, argv: nil)
96
+ def handoff(command: nil, argv: nil, skip_prompt:)
82
97
  env = credentials_env
83
- AwsRunAs::Utils.handoff_to_shell(env: env, profile: @no_role ? nil : @cfg.profile) unless command
98
+ unless command
99
+ AwsRunAs::Utils.handoff_to_shell(env: env, profile: @no_role ? nil : @cfg.profile, skip_prompt: skip_prompt)
100
+ end
84
101
  exec(env, command, *argv)
85
102
  end
86
103
  end
@@ -14,6 +14,8 @@
14
14
 
15
15
  require 'rbconfig'
16
16
  require 'tempfile'
17
+ require 'tmpdir'
18
+ require 'fileutils'
17
19
  require 'English'
18
20
 
19
21
  module AwsRunAs
@@ -21,20 +23,49 @@ module AwsRunAs
21
23
  module Utils
22
24
  module_function
23
25
 
26
+ # Return the path to the shell_profiles directory vendored with the gem.
27
+ def shell_profiles_dir
28
+ File.expand_path('../../../shell_profiles', __FILE__)
29
+ end
30
+
24
31
  # Run an interactive bash session with a special streamed RC file. The RC
25
32
  # merges a local .bashrc if it exists, with a prompt that includes the
26
33
  # computed message from handoff_to_shell.
27
- def bash_with_prompt(env:, path:, message:)
34
+ def handoff_bash(env:, path:, message:, skip_prompt:)
28
35
  rc_data = IO.read("#{ENV['HOME']}/.bashrc") if File.exist?("#{ENV['HOME']}/.bashrc")
29
36
  rc_file = Tempfile.new('aws_runas_bashrc')
30
37
  rc_file.write("#{rc_data}\n") unless rc_data.nil?
31
- rc_file.write("PS1=\"\\[\\e[33m\\](#{message})\\[\\e[0m\\] $PS1\"\n")
38
+ rc_file.write(IO.read("#{shell_profiles_dir}/sh.profile"))
39
+ unless skip_prompt
40
+ rc_file.write("PS1=\"\\[\\e[\\$(aws_session_status_color)m\\](#{message})\\[\\e[0m\\] $PS1\"\n")
41
+ end
32
42
  rc_file.close
33
43
  system(env, path, '--rcfile', rc_file.path)
34
44
  ensure
35
45
  rc_file.unlink
36
46
  end
37
47
 
48
+ # Run an interactive zsh session with a special streamed RC file. The RC
49
+ # merges a local .zshrc if it exists, with a prompt that includes the
50
+ # computed message from handoff_to_shell.
51
+ def handoff_zsh(env:, path:, message:, skip_prompt:)
52
+ rc_data = IO.read("#{ENV['HOME']}/.zshrc") if File.exist?("#{ENV['HOME']}/.zshrc")
53
+ rc_dir = Dir.mktmpdir('aws_runas_zsh')
54
+ rc_file = File.new("#{rc_dir}/.zshrc", 'w')
55
+ rc_file.write("#{rc_data}\n") unless rc_data.nil?
56
+ rc_file.write(IO.read("#{shell_profiles_dir}/sh.profile"))
57
+ unless skip_prompt
58
+ rc_file.write("setopt PROMPT_SUBST\n")
59
+ rc_file.write("export OLDPROMPT=\"${PROMPT}\"\n")
60
+ rc_file.write("PROMPT=$'%{\\e[\\%}$(aws_session_status_color)m(#{message})%{\\e[0m%} $OLDPROMPT'\n")
61
+ end
62
+ rc_file.close
63
+ env.store('ZDOTDIR', rc_dir)
64
+ system(env, path)
65
+ ensure
66
+ FileUtils.rmtree(rc_dir)
67
+ end
68
+
38
69
  # load the shell for a specific operating system.
39
70
  # if $SHELL exists, load that.
40
71
  def shell
@@ -60,10 +91,12 @@ module AwsRunAs
60
91
  # an interactive shell with the shell prompt customized to the current
61
92
  # running AWS profile. If the shell is not something we can handle
62
93
  # specifically, just run the shell.
63
- def handoff_to_shell(env:, profile: nil)
94
+ def handoff_to_shell(env:, profile: nil, skip_prompt:)
64
95
  path = shell
65
96
  if path.end_with?('/bash')
66
- bash_with_prompt(env: env, path: path, message: compute_message(profile: profile))
97
+ handoff_bash(env: env, path: path, message: compute_message(profile: profile), skip_prompt: skip_prompt)
98
+ elsif path.end_with?('/zsh')
99
+ handoff_zsh(env: env, path: path, message: compute_message(profile: profile), skip_prompt: skip_prompt)
67
100
  else
68
101
  system(env, path)
69
102
  end
@@ -13,5 +13,5 @@
13
13
  # limitations under the License.
14
14
 
15
15
  module AwsRunAs
16
- VERSION = '0.4.2'
16
+ VERSION = '0.5.0'
17
17
  end
@@ -0,0 +1,23 @@
1
+ # vim:filetype=sh
2
+ #
3
+ # aws_session_expired checks to see if the current session has expired, based
4
+ # off of the value stored in AWS_SESSION_EXPIRATION_UNIX. This functionality
5
+ # relies on date being in $PATH.
6
+ aws_session_expired() {
7
+ if [[ "${AWS_SESSION_EXPIRATION_UNIX}" -lt "$(date +%s)" ]]; then
8
+ return 0
9
+ fi
10
+ return 1
11
+ }
12
+
13
+ # aws_session_status_color returns an ANSI color number for the specific status
14
+ # of the session. Note that if session_expired is not correctly functioning,
15
+ # this will always be yellow. Red is shown when it's verified that the session
16
+ # has expired.
17
+ aws_session_status_color() {
18
+ if aws_session_expired; then
19
+ echo "31"
20
+ else
21
+ echo "33"
22
+ fi
23
+ }
@@ -102,14 +102,26 @@ describe AwsRunAs::Main do
102
102
  before do
103
103
  allow_any_instance_of(AwsRunAs::Main).to receive(:sts_client).and_return(
104
104
  Aws::STS::Client.new(
105
- stub_responses: true
105
+ stub_responses: {
106
+ get_session_token: {
107
+ credentials: {
108
+ access_key_id: 'accessKeyIdType',
109
+ secret_access_key: 'accessKeySecretType',
110
+ session_token: 'tokenType',
111
+ expiration: Time.utc(2017, 'jul', 10, 19, 56, 11)
112
+ }
113
+ }
114
+ }
106
115
  )
107
116
  )
117
+ allow_any_instance_of(Aws::AssumeRoleCredentials).to receive(:expiration).and_return(
118
+ Time.utc(2017, 'jul', 10, 19, 56, 11)
119
+ )
108
120
  end
109
121
  subject(:env) do
110
122
  ENV.delete('AWS_SESSION_TOKEN')
111
123
  main = AwsRunAs::Main.new(
112
- path: MOCK_AWS_CONFIGPATH,
124
+ path: cfg_path,
113
125
  profile: 'test-profile',
114
126
  mfa_code: '123456',
115
127
  no_role: no_role
@@ -118,6 +130,7 @@ describe AwsRunAs::Main do
118
130
  main.credentials_env
119
131
  end
120
132
  let(:no_role) { false }
133
+ let(:cfg_path) { MOCK_AWS_CONFIGPATH }
121
134
 
122
135
  context 'with role assumed' do
123
136
  it 'returns AWS_ACCESS_KEY_ID set in env' do
@@ -135,6 +148,18 @@ describe AwsRunAs::Main do
135
148
  it 'has AWS_RUNAS_ASSUMED_ROLE_ARN set to the assumed role ARN' do
136
149
  expect(env['AWS_RUNAS_ASSUMED_ROLE_ARN']).to eq('arn:aws:iam::123456789012:role/test-admin')
137
150
  end
151
+ it 'has AWS_SESSION_EXPIRATION set in env' do
152
+ expect(env['AWS_SESSION_EXPIRATION']).to eq('2017-07-10 19:56:11 UTC')
153
+ end
154
+ it 'has AWS_SESSION_EXPIRATION_UNIX set in env' do
155
+ expect(env['AWS_SESSION_EXPIRATION_UNIX']).to eq('1499716571')
156
+ end
157
+ it 'has AWS_REGION set in env' do
158
+ expect(env['AWS_REGION']).to eq('us-west-1')
159
+ end
160
+ it 'has AWS_DEFAULT_REGION set in env' do
161
+ expect(env['AWS_DEFAULT_REGION']).to eq('us-west-1')
162
+ end
138
163
  end
139
164
 
140
165
  context 'with no role assumed' do
@@ -143,6 +168,29 @@ describe AwsRunAs::Main do
143
168
  it 'does not have AWS_RUNAS_ASSUMED_ROLE_ARN set' do
144
169
  expect(env).to_not have_key('AWS_RUNAS_ASSUMED_ROLE_ARN')
145
170
  end
171
+ it 'has AWS_SESSION_EXPIRATION set in env' do
172
+ expect(env['AWS_SESSION_EXPIRATION']).to eq('2017-07-10 19:56:11 UTC')
173
+ end
174
+ it 'has AWS_SESSION_EXPIRATION_UNIX set in env' do
175
+ expect(env['AWS_SESSION_EXPIRATION_UNIX']).to eq('1499716571')
176
+ end
177
+ it 'has AWS_REGION set in env' do
178
+ expect(env['AWS_REGION']).to eq('us-west-1')
179
+ end
180
+ it 'has AWS_DEFAULT_REGION set in env' do
181
+ expect(env['AWS_DEFAULT_REGION']).to eq('us-west-1')
182
+ end
183
+ end
184
+
185
+ context 'with no region in config' do
186
+ let(:cfg_path) { MOCK_AWS_NO_REGION_PATH }
187
+
188
+ it 'does not have AWS_REGION set in env' do
189
+ expect(env).to_not have_key('AWS_REGION')
190
+ end
191
+ it 'does not have AWS_DEFAULT_REGION set in env' do
192
+ expect(env).to_not have_key('AWS_DEFAULT_REGION')
193
+ end
146
194
  end
147
195
  end
148
196
 
@@ -154,7 +202,7 @@ describe AwsRunAs::Main do
154
202
 
155
203
  it 'execs a command when a command is specified' do
156
204
  expect(@main).to receive(:exec).with(anything, '/usr/bin/foo', *['--bar', 'baz'])
157
- @main.handoff(command: '/usr/bin/foo', argv: ['--bar', 'baz'])
205
+ @main.handoff(command: '/usr/bin/foo', argv: ['--bar', 'baz'], skip_prompt: false)
158
206
  end
159
207
  end
160
208
  end
@@ -13,33 +13,113 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'spec_helper'
16
+ require 'tmpdir'
16
17
 
17
18
  describe AwsRunAs::Utils do
18
- describe '::bash_with_prompt' do
19
+ describe '::shell_profiles_dir' do
20
+ it 'returns an existent path' do
21
+ expect(File.directory?(AwsRunAs::Utils.shell_profiles_dir)).to be true
22
+ end
23
+ it 'returns a path correctly relative to spec file' do
24
+ expect(AwsRunAs::Utils.shell_profiles_dir).to eq(File.expand_path('../../../shell_profiles', __FILE__))
25
+ end
26
+ end
27
+
28
+ describe '::handoff_bash' do
19
29
  context 'with RC file' do
20
30
  before(:example) do
21
31
  allow(IO).to receive(:read).with("#{ENV['HOME']}/.bashrc").and_return(BASHRC_FILE_CONTENTS)
32
+ allow(IO).to receive(:read).with("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile").and_call_original
22
33
  end
23
34
  it 'runs bash with a properly combined RC file' do
24
35
  expect(AwsRunAs::Utils).to receive(:system).with(EXPECTED_ENV, '/bin/bash', '--rcfile', anything)
25
36
  expect_any_instance_of(Tempfile).to receive(:write).with("#{BASHRC_FILE_CONTENTS}\n")
37
+ expect_any_instance_of(Tempfile).to receive(:write).with(IO.read("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile"))
26
38
  expect_any_instance_of(Tempfile).to receive(:write).with(BASHRC_EXPECTED_PROMPT)
27
- AwsRunAs::Utils.bash_with_prompt(env: EXPECTED_ENV, path: '/bin/bash', message: 'AWS:rspec')
39
+ AwsRunAs::Utils.handoff_bash(env: EXPECTED_ENV, path: '/bin/bash', message: 'AWS:rspec', skip_prompt: false)
28
40
  end
29
41
  end
30
42
 
31
43
  context 'without RC file' do
32
44
  before(:example) do
33
45
  allow(File).to receive(:exist?).with("#{ENV['HOME']}/.bashrc").and_return(false)
46
+ allow(IO).to receive(:read).with("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile").and_call_original
34
47
  end
35
48
  it 'runs bash (no RC file found)' do
36
49
  expect(AwsRunAs::Utils).to receive(:system).with(EXPECTED_ENV, '/bin/bash', '--rcfile', anything)
50
+ expect_any_instance_of(Tempfile).to receive(:write).with(IO.read("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile"))
37
51
  expect_any_instance_of(Tempfile).to receive(:write).with(BASHRC_EXPECTED_PROMPT)
38
- AwsRunAs::Utils.bash_with_prompt(env: EXPECTED_ENV, path: '/bin/bash', message: 'AWS:rspec')
52
+ AwsRunAs::Utils.handoff_bash(env: EXPECTED_ENV, path: '/bin/bash', message: 'AWS:rspec', skip_prompt: false)
53
+ end
54
+ end
55
+
56
+ context 'with skip_prompt enabled' do
57
+ before(:example) do
58
+ allow(IO).to receive(:read).with("#{ENV['HOME']}/.bashrc").and_return(BASHRC_FILE_CONTENTS)
59
+ allow(IO).to receive(:read).with("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile").and_call_original
60
+ end
61
+ it 'runs bash with a properly combined RC file, but no prompt modification' do
62
+ expect(AwsRunAs::Utils).to receive(:system).with(EXPECTED_ENV, '/bin/bash', '--rcfile', anything)
63
+ expect_any_instance_of(Tempfile).to receive(:write).with("#{BASHRC_FILE_CONTENTS}\n")
64
+ expect_any_instance_of(Tempfile).to receive(:write).with(IO.read("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile"))
65
+ AwsRunAs::Utils.handoff_bash(env: EXPECTED_ENV, path: '/bin/bash', message: 'AWS:rspec', skip_prompt: true)
39
66
  end
40
67
  end
41
68
  end
42
69
 
70
+ describe '::handoff_zsh' do
71
+ context 'with RC file' do
72
+ before(:example) do
73
+ allow(IO).to receive(:read).with("#{ENV['HOME']}/.zshrc").and_return(ZSHRC_FILE_CONTENTS)
74
+ allow(IO).to receive(:read).with("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile").and_call_original
75
+ end
76
+ it 'runs zsh with a properly combined RC file, in special tmp dir' do
77
+ expect(AwsRunAs::Utils).to receive(:system).with(EXPECTED_ENV_ZSH, '/usr/bin/zsh')
78
+ expect(Dir).to receive(:mktmpdir).with('aws_runas_zsh') { test_mktmpdir }
79
+ expect_any_instance_of(File).to receive(:write).with("#{ZSHRC_FILE_CONTENTS}\n")
80
+ expect_any_instance_of(File).to receive(:write).with(IO.read("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile"))
81
+ expect_any_instance_of(File).to receive(:write).with(ZSHRC_EXPECTED_SETSUBST)
82
+ expect_any_instance_of(File).to receive(:write).with(ZSHRC_EXPECTED_OLDPROMPT)
83
+ expect_any_instance_of(File).to receive(:write).with(ZSHRC_EXPECTED_PROMPT)
84
+ env = EXPECTED_ENV.dup
85
+ AwsRunAs::Utils.handoff_zsh(env: env, path: '/usr/bin/zsh', message: 'AWS:rspec', skip_prompt: false)
86
+ end
87
+ end
88
+
89
+ context 'without RC file' do
90
+ before(:example) do
91
+ allow(File).to receive(:exist?).with("#{ENV['HOME']}/.zshrc").and_return(false)
92
+ allow(IO).to receive(:read).with("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile").and_call_original
93
+ end
94
+ it 'runs zsh (no RC file found)' do
95
+ expect(AwsRunAs::Utils).to receive(:system).with(EXPECTED_ENV_ZSH, '/usr/bin/zsh')
96
+ expect(Dir).to receive(:mktmpdir).with('aws_runas_zsh') { test_mktmpdir }
97
+ expect_any_instance_of(File).to receive(:write).with(IO.read("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile"))
98
+ expect_any_instance_of(File).to receive(:write).with(ZSHRC_EXPECTED_SETSUBST)
99
+ expect_any_instance_of(File).to receive(:write).with(ZSHRC_EXPECTED_OLDPROMPT)
100
+ expect_any_instance_of(File).to receive(:write).with(ZSHRC_EXPECTED_PROMPT)
101
+ env = EXPECTED_ENV.dup
102
+ AwsRunAs::Utils.handoff_zsh(env: env, path: '/usr/bin/zsh', message: 'AWS:rspec', skip_prompt: false)
103
+ end
104
+ end
105
+
106
+ context 'with skip_prompt enabled' do
107
+ before(:example) do
108
+ allow(IO).to receive(:read).with("#{ENV['HOME']}/.zshrc").and_return(ZSHRC_FILE_CONTENTS)
109
+ allow(IO).to receive(:read).with("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile").and_call_original
110
+ end
111
+ it 'runs zsh with a properly combined RC file, in special tmp dir' do
112
+ expect(AwsRunAs::Utils).to receive(:system).with(EXPECTED_ENV_ZSH, '/usr/bin/zsh')
113
+ expect(Dir).to receive(:mktmpdir).with('aws_runas_zsh') { test_mktmpdir }
114
+ expect_any_instance_of(File).to receive(:write).with("#{ZSHRC_FILE_CONTENTS}\n")
115
+ expect_any_instance_of(File).to receive(:write).with(IO.read("#{AwsRunAs::Utils.shell_profiles_dir}/sh.profile"))
116
+ env = EXPECTED_ENV.dup
117
+ AwsRunAs::Utils.handoff_zsh(env: env, path: '/usr/bin/zsh', message: 'AWS:rspec', skip_prompt: true)
118
+ end
119
+ end
120
+
121
+ end
122
+
43
123
  describe '::shell' do
44
124
  context 'Non-Windows OS' do
45
125
  context 'No $SHELL set' do
@@ -97,8 +177,8 @@ describe AwsRunAs::Utils do
97
177
  end
98
178
 
99
179
  it 'Loads bash with the rspec profile prompt' do
100
- expect(AwsRunAs::Utils).to receive(:bash_with_prompt).with(env: EXPECTED_ENV, path: '/bin/bash', message: 'AWS:rspec')
101
- AwsRunAs::Utils.handoff_to_shell(env: EXPECTED_ENV, profile: 'rspec')
180
+ expect(AwsRunAs::Utils).to receive(:handoff_bash).with(env: EXPECTED_ENV, path: '/bin/bash', message: 'AWS:rspec', skip_prompt: false)
181
+ AwsRunAs::Utils.handoff_to_shell(env: EXPECTED_ENV, profile: 'rspec', skip_prompt: false)
102
182
  end
103
183
  end
104
184
 
@@ -110,7 +190,7 @@ describe AwsRunAs::Utils do
110
190
 
111
191
  it 'starts a default shell without any args' do
112
192
  expect(AwsRunAs::Utils).to receive(:system).with(EXPECTED_ENV, '/bin/sh')
113
- AwsRunAs::Utils.handoff_to_shell(env: EXPECTED_ENV, profile: nil)
193
+ AwsRunAs::Utils.handoff_to_shell(env: EXPECTED_ENV, profile: nil, skip_prompt: false)
114
194
  end
115
195
  end
116
196
  end
@@ -17,3 +17,4 @@ require 'spec_helper'
17
17
  MOCK_AWS_CONFIGPATH = File.expand_path('../files/aws_config', __FILE__)
18
18
  MOCK_AWS_NO_MFA_PATH = File.expand_path('../files/aws_config_nomfa', __FILE__)
19
19
  MOCK_AWS_NO_SOURCE_PATH = File.expand_path('../files/aws_config_nosource', __FILE__)
20
+ MOCK_AWS_NO_REGION_PATH = File.expand_path('../files/aws_config_noregion', __FILE__)
@@ -0,0 +1,6 @@
1
+ [default]
2
+
3
+ [profile test-profile]
4
+ role_arn = arn:aws:iam::123456789012:role/test-admin
5
+ mfa_serial = arn:aws:iam::123456789012:mfa/test
6
+ source_profile = test-credentials
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'tmpdir'
2
3
 
3
4
  MOCK_BASHRC_PATH = File.expand_path('../files/bashrc', __FILE__)
4
5
 
@@ -6,10 +7,30 @@ BASHRC_FILE_CONTENTS = <<EOS.freeze
6
7
  foobar
7
8
  EOS
8
9
 
9
- BASHRC_EXPECTED_PROMPT = "PS1=\"\\[\\e[33m\\](AWS:rspec)\\[\\e[0m\\] $PS1\"\n".freeze
10
+ ZSHRC_FILE_CONTENTS = <<EOS.freeze
11
+ bazqux
12
+ EOS
13
+
14
+ BASHRC_EXPECTED_PROMPT = "PS1=\"\\[\\e[\\$(aws_session_status_color)m\\](AWS:rspec)\\[\\e[0m\\] $PS1\"\n".freeze
15
+ ZSHRC_EXPECTED_PROMPT = "PROMPT=$'%{\\e[\\%}$(aws_session_status_color)m(AWS:rspec)%{\\e[0m%} $OLDPROMPT'\n".freeze
16
+ ZSHRC_EXPECTED_SETSUBST = "setopt PROMPT_SUBST\n".freeze
17
+ ZSHRC_EXPECTED_OLDPROMPT = "export OLDPROMPT=\"${PROMPT}\"\n".freeze
18
+ ZSH_MOCK_TMPDIR = "#{Dir.tmpdir}/aws_runas_zsh_rspec".freeze
10
19
 
11
20
  EXPECTED_ENV = {
12
21
  'AWS_ACCESS_KEY_ID' => 'AccessKeyId',
13
22
  'AWS_SECRET_ACCESS_KEY' => 'SecretAccessKey',
14
23
  'AWS_SESSION_TOKEN' => 'Token'
15
24
  }.freeze
25
+
26
+ EXPECTED_ENV_ZSH = {
27
+ 'AWS_ACCESS_KEY_ID' => 'AccessKeyId',
28
+ 'AWS_SECRET_ACCESS_KEY' => 'SecretAccessKey',
29
+ 'AWS_SESSION_TOKEN' => 'Token',
30
+ 'ZDOTDIR' => ZSH_MOCK_TMPDIR
31
+ }.freeze
32
+
33
+ def test_mktmpdir
34
+ Dir.mkdir(ZSH_MOCK_TMPDIR)
35
+ ZSH_MOCK_TMPDIR
36
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws_runas
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Marchesi
@@ -31,7 +31,7 @@ cert_chain:
31
31
  80WBA6xKwX0zwURD8J7WNieL2iY5AhBg26cHuFLMQGTCyNEeZHZHnJhCwuBcnV1w
32
32
  2zQ=
33
33
  -----END CERTIFICATE-----
34
- date: 2017-05-03 00:00:00.000000000 Z
34
+ date: 2017-07-16 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: aws-sdk
@@ -156,6 +156,7 @@ files:
156
156
  - lib/aws_runas/main.rb
157
157
  - lib/aws_runas/utils.rb
158
158
  - lib/aws_runas/version.rb
159
+ - shell_profiles/sh.profile
159
160
  - spec/aws_runas/cli_spec.rb
160
161
  - spec/aws_runas/config_spec.rb
161
162
  - spec/aws_runas/main_spec.rb
@@ -163,8 +164,8 @@ files:
163
164
  - spec/helpers/config_spec.rb
164
165
  - spec/helpers/files/aws_config
165
166
  - spec/helpers/files/aws_config_nomfa
167
+ - spec/helpers/files/aws_config_noregion
166
168
  - spec/helpers/files/aws_config_nosource
167
- - spec/helpers/files/bashrc
168
169
  - spec/helpers/utils_spec.rb
169
170
  - spec/spec_helper.rb
170
171
  homepage: https://github.com/vancluever/aws-runas
@@ -199,7 +200,7 @@ test_files:
199
200
  - spec/helpers/config_spec.rb
200
201
  - spec/helpers/files/aws_config
201
202
  - spec/helpers/files/aws_config_nomfa
203
+ - spec/helpers/files/aws_config_noregion
202
204
  - spec/helpers/files/aws_config_nosource
203
- - spec/helpers/files/bashrc
204
205
  - spec/helpers/utils_spec.rb
205
206
  - spec/spec_helper.rb
metadata.gz.sig CHANGED
@@ -1,3 +1,3 @@
1
- ����бa��v��ߝW�v [�d[R���_��JY����1�?�7
2
- ��O빜��
3
- 5���l@�i��_��%����{���Y
1
+ ��չۙ���j=7[^s*�3��_l�*� �!������t����U���H�Ř�l�����;��L(~LfE'O�"T_j8p��b؀*��b�,W}C����$C��ߪ,�o��b��9�I̼m+� ʊ�I���
2
+ ���fE�]�ĸB���I�?��/�ݾ��ڬ�
3
+ �6�Rp;pja���E�3��žFi��F������T���_�)�⳵����Kˀ��w�/[����|8��S��xlh����~E(
@@ -1 +0,0 @@
1
- foobar