aws_session_token 0.3.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 +7 -0
- data/.document +5 -0
- data/.rspec +1 -0
- data/.rubocop.yml +34 -0
- data/.semver +6 -0
- data/.travis.yml +33 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +29 -0
- data/Gemfile.lock +703 -0
- data/LICENSE +201 -0
- data/README.markdown +81 -0
- data/Rakefile +86 -0
- data/bin/aws_session_token +9 -0
- data/config/syntax.yaml +7 -0
- data/lib/aws_session_token.rb +29 -0
- data/lib/aws_session_token/cli.rb +92 -0
- data/lib/aws_session_token/credentials_file.rb +85 -0
- data/lib/aws_session_token/options.rb +128 -0
- data/spec/aws_session_token/cli_spec.rb +197 -0
- data/spec/aws_session_token/credentials_file_spec.rb +116 -0
- data/spec/aws_session_token/options_spec.rb +184 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +54 -0
- data/spec/support/custom_matchers.rb +50 -0
- metadata +226 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# AWS Session Token Gem - Tool to wrap AWS API to create and store
|
|
5
|
+
# Session tokens so that other commands/tools (e.g. Terraform) can function as
|
|
6
|
+
# necessary.
|
|
7
|
+
#
|
|
8
|
+
#
|
|
9
|
+
# Copyright 2018 Bryan Stopp <bryan.stopp@gmail.com>
|
|
10
|
+
#
|
|
11
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
# you may not use this file except in compliance with the License.
|
|
13
|
+
# You may obtain a copy of the License at
|
|
14
|
+
#
|
|
15
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
#
|
|
17
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
# See the License for the specific language governing permissions and
|
|
21
|
+
# limitations under the License.
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
module AwsSessionToken
|
|
25
|
+
|
|
26
|
+
# Helper class for interacting with the Credentials file.
|
|
27
|
+
class CredentialsFile
|
|
28
|
+
|
|
29
|
+
Profile = Struct.new(:name, :data)
|
|
30
|
+
|
|
31
|
+
def write(filename, profile, credentials)
|
|
32
|
+
file = nil
|
|
33
|
+
begin
|
|
34
|
+
profiles = read_profiles(filename)
|
|
35
|
+
file = File.open(filename, 'w')
|
|
36
|
+
write_file(credentials, file, profile, profiles)
|
|
37
|
+
ensure
|
|
38
|
+
file&.close
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def read_profiles(credentials_file)
|
|
45
|
+
profiles = []
|
|
46
|
+
profile = nil
|
|
47
|
+
File.readlines(credentials_file).each do |line|
|
|
48
|
+
if line =~ /^\[/
|
|
49
|
+
profile = Profile.new(line, [])
|
|
50
|
+
profiles << profile
|
|
51
|
+
else
|
|
52
|
+
profile.data << line
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
profiles
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def write_file(credentials, file, profile, profiles)
|
|
59
|
+
found = false
|
|
60
|
+
profiles.each do |p|
|
|
61
|
+
if p.name =~ /^\[#{profile}\]/
|
|
62
|
+
write_session(file, profile, credentials)
|
|
63
|
+
found = true
|
|
64
|
+
else
|
|
65
|
+
write_profile(file, p)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
write_session(file, profile, credentials) unless found
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def write_profile(file, profile)
|
|
72
|
+
file.puts(profile.name)
|
|
73
|
+
profile.data.each do |l|
|
|
74
|
+
file.puts(l)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def write_session(file, profile, creds)
|
|
79
|
+
file.puts("[#{profile}]")
|
|
80
|
+
file.puts("aws_access_key_id = #{creds.access_key_id}")
|
|
81
|
+
file.puts("aws_secret_access_key = #{creds.secret_access_key}")
|
|
82
|
+
file.puts("aws_session_token = #{creds.session_token}")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# AWS Session Token Gem - Tool to wrap AWS API to create and store Session tokens
|
|
5
|
+
# so that other commands/tools (e.g. Terraform) can function as necessary.
|
|
6
|
+
#
|
|
7
|
+
# Copyright 2018 Bryan Stopp <bryan.stopp@gmail.com>
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the 'License');
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an 'AS IS' BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
|
|
21
|
+
module AwsSessionToken
|
|
22
|
+
|
|
23
|
+
# Options class to define properties for the command line.
|
|
24
|
+
class Options
|
|
25
|
+
|
|
26
|
+
SESSION_PROFILE = 'session_profile'
|
|
27
|
+
DURATION = 3600
|
|
28
|
+
|
|
29
|
+
attr_accessor :credentials_file, :duration, :profile, :profile_provided, :session_profile, :token, :user
|
|
30
|
+
|
|
31
|
+
def initialize
|
|
32
|
+
creds = Aws::SharedCredentials.new
|
|
33
|
+
self.credentials_file = creds.path
|
|
34
|
+
self.profile = creds.profile_name
|
|
35
|
+
self.session_profile = SESSION_PROFILE
|
|
36
|
+
self.duration = DURATION
|
|
37
|
+
self.profile_provided = false
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def parse(args)
|
|
41
|
+
define_options.parse!(args)
|
|
42
|
+
validate
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def define_options
|
|
48
|
+
opts = OptionParser.new
|
|
49
|
+
opts.banner = 'Usage: aws_session_token [options]'
|
|
50
|
+
opts.separator('')
|
|
51
|
+
|
|
52
|
+
# Additional options
|
|
53
|
+
file_option(opts)
|
|
54
|
+
user_option(opts)
|
|
55
|
+
profile_option(opts)
|
|
56
|
+
session_profile_option(opts)
|
|
57
|
+
duration_option(opts)
|
|
58
|
+
token_option(opts)
|
|
59
|
+
common_options(opts)
|
|
60
|
+
opts
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def file_option(opts)
|
|
64
|
+
opts.on('-f', '--file FILE', 'Specify a custom credentials file.') do |f|
|
|
65
|
+
self.credentials_file = f
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def user_option(opts)
|
|
70
|
+
opts.on('-u', '--user USER',
|
|
71
|
+
'Specify the AWS User name for passing to API.') do |u|
|
|
72
|
+
self.user = u
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def profile_option(opts)
|
|
77
|
+
opts.on('-p', '--profile PROFILE',
|
|
78
|
+
'Specify the AWS credentials profile to use. Also sets user, if user is not provided.') do |p|
|
|
79
|
+
self.profile = p
|
|
80
|
+
self.profile_provided = true
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def session_profile_option(opts)
|
|
85
|
+
opts.on('-s', '--session SESSION_PROFILE',
|
|
86
|
+
'Specify the name of the profile used to store the session credentials.') do |s|
|
|
87
|
+
self.session_profile = s
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def duration_option(opts)
|
|
92
|
+
opts.on('-d', '--duration DURATION', Integer,
|
|
93
|
+
'Specify the duration the of the token in seconds. (Default 3600)') do |d|
|
|
94
|
+
self.duration = d
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def token_option(opts)
|
|
99
|
+
opts.on('-t', '--token TOKEN', Integer,
|
|
100
|
+
'Specify the OTP Token to use for creating the session credentials.') do |t|
|
|
101
|
+
self.token = t
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def common_options(opts)
|
|
106
|
+
opts.separator('')
|
|
107
|
+
opts.separator('Common options:')
|
|
108
|
+
opts.on_tail('-h', '--help', 'Show this message.') do
|
|
109
|
+
puts opts
|
|
110
|
+
exit
|
|
111
|
+
end
|
|
112
|
+
opts.on_tail('-v', '--version', 'Show version.') do
|
|
113
|
+
puts SemVer.find.format(+ '%M.%m.%p%s')
|
|
114
|
+
exit
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def validate
|
|
119
|
+
validate_profiles
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def validate_profiles
|
|
123
|
+
raise ArgumentError, 'Profile and Session Profile must be different.' if profile == session_profile
|
|
124
|
+
self.user ||= profile if profile_provided
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# AWS Session Token Gem - Tool to wrap AWS API to create and store Session tokens
|
|
5
|
+
# so that other commands/tools (e.g. Terraform) can function as necessary.
|
|
6
|
+
#
|
|
7
|
+
# Copyright 2018 Bryan Stopp <bryan.stopp@gmail.com>
|
|
8
|
+
#
|
|
9
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
+
# you may not use this file except in compliance with the License.
|
|
11
|
+
# You may obtain a copy of the License at
|
|
12
|
+
#
|
|
13
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
+
#
|
|
15
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
16
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
17
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
+
# See the License for the specific language governing permissions and
|
|
19
|
+
# limitations under the License.
|
|
20
|
+
#
|
|
21
|
+
|
|
22
|
+
require 'spec_helper'
|
|
23
|
+
require 'aws_session_token/credentials_file'
|
|
24
|
+
|
|
25
|
+
describe AwsSessionToken::CLI do
|
|
26
|
+
|
|
27
|
+
before do
|
|
28
|
+
$stdout = StringIO.new
|
|
29
|
+
$stderr = StringIO.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
after do
|
|
33
|
+
$stdout = STDOUT
|
|
34
|
+
$stderr = STDERR
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
subject(:cli) { described_class.new }
|
|
38
|
+
|
|
39
|
+
let(:creds_data) do
|
|
40
|
+
Aws::STS::Types::Credentials.new(
|
|
41
|
+
access_key_id: 'AKIAIOSFODNN7EXAMPLE',
|
|
42
|
+
expiration: Time.parse('2011-07-11T19:55:29.611Z'),
|
|
43
|
+
secret_access_key: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY',
|
|
44
|
+
session_token: 'EXAMPLE SESSION TOKEN'
|
|
45
|
+
)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
let(:mfa_arn) { 'Fake Serial Number' }
|
|
49
|
+
|
|
50
|
+
let(:mfa_token) { 123_456 }
|
|
51
|
+
|
|
52
|
+
describe 'run' do
|
|
53
|
+
it 'should work' do
|
|
54
|
+
expect(cli).to receive(:set_aws_creds)
|
|
55
|
+
expect(cli).to receive(:mfa_device).and_return(mfa_arn)
|
|
56
|
+
expect(cli).to receive(:token_prompt).and_return(mfa_token)
|
|
57
|
+
expect(cli).to receive(:session_token).with(mfa_arn, mfa_token).and_return(creds_data)
|
|
58
|
+
expect_any_instance_of(AwsSessionToken::CredentialsFile).to receive(:write).with(
|
|
59
|
+
Aws::SharedCredentials.new.path,
|
|
60
|
+
AwsSessionToken::Options::SESSION_PROFILE,
|
|
61
|
+
creds_data
|
|
62
|
+
)
|
|
63
|
+
cli.run
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe 'token provided' do
|
|
67
|
+
before do
|
|
68
|
+
ARGV << '-t'
|
|
69
|
+
ARGV << mfa_token.to_s
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should skip token prompt' do
|
|
73
|
+
expect(cli).to receive(:set_aws_creds)
|
|
74
|
+
expect(cli).to receive(:mfa_device).and_return(mfa_arn)
|
|
75
|
+
expect(cli).to receive(:session_token).with(mfa_arn, mfa_token).and_return(creds_data)
|
|
76
|
+
expect_any_instance_of(AwsSessionToken::CredentialsFile).to receive(:write).with(
|
|
77
|
+
Aws::SharedCredentials.new.path,
|
|
78
|
+
AwsSessionToken::Options::SESSION_PROFILE,
|
|
79
|
+
creds_data
|
|
80
|
+
)
|
|
81
|
+
cli.run
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe 'validate_creds_file' do
|
|
87
|
+
it 'should succeed if file exists' do
|
|
88
|
+
creds = Aws::SharedCredentials.new
|
|
89
|
+
expect(File).to receive(:exist?).with(creds.path).and_return(true)
|
|
90
|
+
expect { cli.validate_creds_file }.to_not raise_error
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'should fail if file is missing' do
|
|
94
|
+
creds = Aws::SharedCredentials.new
|
|
95
|
+
expect(File).to receive(:exist?).with(creds.path).at_least(:once).and_return(false)
|
|
96
|
+
expect { cli.validate_creds_file }.to raise_error(ArgumentError, /Specified credentials file is missing/)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'should fail if file is not writable by current user' do
|
|
100
|
+
creds = Aws::SharedCredentials.new
|
|
101
|
+
expect(File).to receive(:exist?).with(creds.path).at_least(:once).and_return(true)
|
|
102
|
+
expect(File).to receive(:writable?).with(creds.path).at_least(:once).and_return(false)
|
|
103
|
+
expect { cli.validate_creds_file }.to raise_error(ArgumentError, /Specified credentials file cannot /)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe 'set_aws_creds' do
|
|
108
|
+
it 'is should work' do
|
|
109
|
+
expect(Aws.config).to receive(:update).with(
|
|
110
|
+
credentials: instance_of(Aws::SharedCredentials)
|
|
111
|
+
)
|
|
112
|
+
cli.set_aws_creds
|
|
113
|
+
end
|
|
114
|
+
it 'is should fail if profile does not exist' do
|
|
115
|
+
cli.options.profile = 'nonexistent'
|
|
116
|
+
expect { cli.set_aws_creds }.to exit_with_code(1)
|
|
117
|
+
expect($stderr.string).to match(/Specified AWS Profile doesn't exist: nonexistent/)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe 'mfa_device' do
|
|
122
|
+
let(:mfa_device) do
|
|
123
|
+
mfa = Aws::IAM::Types::MFADevice.new
|
|
124
|
+
mfa.user_name = 'username'
|
|
125
|
+
mfa.serial_number = 'serial-number'
|
|
126
|
+
mfa.enable_date = 'enable-date'
|
|
127
|
+
mfa
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'should work without user' do
|
|
131
|
+
params = { max_items: 1 }
|
|
132
|
+
client = double('iam_client')
|
|
133
|
+
response = Aws::IAM::Types::ListMFADevicesResponse.new(mfa_devices: [mfa_device])
|
|
134
|
+
expect(Aws::IAM::Client).to receive(:new).and_return(client)
|
|
135
|
+
expect(client).to receive(:list_mfa_devices).with(params).and_return(response)
|
|
136
|
+
expect(cli.mfa_device).to eq('serial-number')
|
|
137
|
+
end
|
|
138
|
+
it 'should work with user' do
|
|
139
|
+
cli.options.user = 'foo'
|
|
140
|
+
params = { user_name: 'foo', max_items: 1 }
|
|
141
|
+
client = double('iam_client')
|
|
142
|
+
response = Aws::IAM::Types::ListMFADevicesResponse.new(mfa_devices: [mfa_device])
|
|
143
|
+
expect(Aws::IAM::Client).to receive(:new).and_return(client)
|
|
144
|
+
expect(client).to receive(:list_mfa_devices).with(params).and_return(response)
|
|
145
|
+
expect(cli.mfa_device).to eq('serial-number')
|
|
146
|
+
end
|
|
147
|
+
it 'should exit if no MFA devices' do
|
|
148
|
+
|
|
149
|
+
client = double('iam_client')
|
|
150
|
+
response = Aws::IAM::Types::ListMFADevicesResponse.new(mfa_devices: [])
|
|
151
|
+
expect(Aws::IAM::Client).to receive(:new).and_return(client)
|
|
152
|
+
expect(client).to receive(:list_mfa_devices).and_return(response)
|
|
153
|
+
begin
|
|
154
|
+
expect { cli.mfa_device }.to exit_with_code(0)
|
|
155
|
+
rescue SystemExit # rubocop:disable Lint/HandleExceptions
|
|
156
|
+
end
|
|
157
|
+
expected = 'Script execution unnecessary.'
|
|
158
|
+
expect($stderr.string).to match(/#{expected}/)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
context 'token_prompt' do
|
|
163
|
+
before do
|
|
164
|
+
$stdin = StringIO.new
|
|
165
|
+
$stdin.puts('123456')
|
|
166
|
+
$stdin.rewind
|
|
167
|
+
end
|
|
168
|
+
it 'should work' do
|
|
169
|
+
expect { cli.token_prompt }.to_not raise_error
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe 'session_token' do
|
|
174
|
+
let(:response) do
|
|
175
|
+
creds = Aws::STS::Types::Credentials.new
|
|
176
|
+
creds.access_key_id = 'access_key_id'
|
|
177
|
+
creds.secret_access_key = 'secret_access_key'
|
|
178
|
+
creds.expiration = 'expiration'
|
|
179
|
+
creds.session_token = 'session_token'
|
|
180
|
+
|
|
181
|
+
resp = Aws::STS::Types::GetSessionTokenResponse.new
|
|
182
|
+
resp.credentials = creds
|
|
183
|
+
resp
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'should work' do
|
|
187
|
+
device = 'device'
|
|
188
|
+
token = 'token'
|
|
189
|
+
client = double('sts-client')
|
|
190
|
+
expect(Aws::STS::Client).to receive(:new).and_return(client)
|
|
191
|
+
expect(client).to receive(:get_session_token).with(
|
|
192
|
+
duration_seconds: 3600, serial_number: device, token_code: token
|
|
193
|
+
).and_return(response)
|
|
194
|
+
expect(cli.session_token(device, token)).to eq(response.credentials)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# AWS Session Token Gem - Tool to wrap AWS API to create and store
|
|
5
|
+
# Session tokens so that other commands/tools (e.g. Terraform) can function as
|
|
6
|
+
# necessary.
|
|
7
|
+
#
|
|
8
|
+
#
|
|
9
|
+
# Copyright 2018 Bryan Stopp <bryan.stopp@gmail.com>
|
|
10
|
+
#
|
|
11
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
# you may not use this file except in compliance with the License.
|
|
13
|
+
# You may obtain a copy of the License at
|
|
14
|
+
#
|
|
15
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
#
|
|
17
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
# See the License for the specific language governing permissions and
|
|
21
|
+
# limitations under the License.
|
|
22
|
+
#
|
|
23
|
+
|
|
24
|
+
require 'spec_helper'
|
|
25
|
+
|
|
26
|
+
describe AwsSessionToken::CredentialsFile, :isolated_environment do
|
|
27
|
+
before do
|
|
28
|
+
$stdout = StringIO.new
|
|
29
|
+
$stderr = StringIO.new
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
after do
|
|
33
|
+
$stdout = STDOUT
|
|
34
|
+
$stderr = STDERR
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
subject(:cf) { described_class.new }
|
|
38
|
+
|
|
39
|
+
let(:creds) do
|
|
40
|
+
creds = Aws::STS::Types::Credentials.new
|
|
41
|
+
creds.access_key_id = 'access_key_id'
|
|
42
|
+
creds.secret_access_key = 'secret_access_key'
|
|
43
|
+
creds.expiration = 'expiration'
|
|
44
|
+
creds.session_token = 'session_token'
|
|
45
|
+
creds
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe 'write' do
|
|
49
|
+
let(:file_contents) do
|
|
50
|
+
<<~CREDS
|
|
51
|
+
[stopp]
|
|
52
|
+
aws_access_key_id = EXAMPLESTOPPACCESSID
|
|
53
|
+
aws_secret_access_key = EXAMPLESTOPPSECRETKEY
|
|
54
|
+
[admin]
|
|
55
|
+
aws_access_key_id = EXAMPLEADMINACCESSID
|
|
56
|
+
aws_secret_access_key = EXAMPLEADMINSECRETKEY
|
|
57
|
+
CREDS
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
shared_examples 'update file' do |opts|
|
|
61
|
+
it do
|
|
62
|
+
file = StringIO.new
|
|
63
|
+
default_creds = Aws::SharedCredentials.new
|
|
64
|
+
expect(File).to receive(:readlines).with(default_creds.path).and_return(file_contents.split("\n"))
|
|
65
|
+
expect(File).to receive(:open).with(default_creds.path, 'w').and_return(file)
|
|
66
|
+
cf.write(default_creds.path, opts[:profile], creds)
|
|
67
|
+
expect(file.string).to eq(opts[:expected])
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe 'profile does not exist' do
|
|
72
|
+
contents = <<~CREDS
|
|
73
|
+
[stopp]
|
|
74
|
+
aws_access_key_id = EXAMPLESTOPPACCESSID
|
|
75
|
+
aws_secret_access_key = EXAMPLESTOPPSECRETKEY
|
|
76
|
+
[admin]
|
|
77
|
+
aws_access_key_id = EXAMPLEADMINACCESSID
|
|
78
|
+
aws_secret_access_key = EXAMPLEADMINSECRETKEY
|
|
79
|
+
[session_profile]
|
|
80
|
+
aws_access_key_id = access_key_id
|
|
81
|
+
aws_secret_access_key = secret_access_key
|
|
82
|
+
aws_session_token = session_token
|
|
83
|
+
CREDS
|
|
84
|
+
|
|
85
|
+
it_should_behave_like('update file', expected: contents, profile: 'session_profile')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe 'profile exists' do
|
|
89
|
+
describe 'first profile' do
|
|
90
|
+
contents = <<~CREDS
|
|
91
|
+
[stopp]
|
|
92
|
+
aws_access_key_id = access_key_id
|
|
93
|
+
aws_secret_access_key = secret_access_key
|
|
94
|
+
aws_session_token = session_token
|
|
95
|
+
[admin]
|
|
96
|
+
aws_access_key_id = EXAMPLEADMINACCESSID
|
|
97
|
+
aws_secret_access_key = EXAMPLEADMINSECRETKEY
|
|
98
|
+
CREDS
|
|
99
|
+
|
|
100
|
+
it_should_behave_like('update file', expected: contents, profile: 'stopp')
|
|
101
|
+
end
|
|
102
|
+
describe 'last profile' do
|
|
103
|
+
contents = <<~CREDS
|
|
104
|
+
[stopp]
|
|
105
|
+
aws_access_key_id = EXAMPLESTOPPACCESSID
|
|
106
|
+
aws_secret_access_key = EXAMPLESTOPPSECRETKEY
|
|
107
|
+
[admin]
|
|
108
|
+
aws_access_key_id = access_key_id
|
|
109
|
+
aws_secret_access_key = secret_access_key
|
|
110
|
+
aws_session_token = session_token
|
|
111
|
+
CREDS
|
|
112
|
+
it_should_behave_like('update file', expected: contents, profile: 'admin')
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|