vagrant-aws 0.7.0 → 0.7.1

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: a1deca95df376c2977458f95179407a4c2e04458
4
- data.tar.gz: 9d4a5506219f5f3f8db34ea476d9aa986ae75ec8
3
+ metadata.gz: 7dc5ac6ea70ec0fa3aaf489a3062a5ca91724ea2
4
+ data.tar.gz: cd91ea76e3f967df83caa7f72ae41fb5741a0129
5
5
  SHA512:
6
- metadata.gz: 96d998cf0955fab6abfac02fc5b386fb7ee15dcb224e0abbb145970cf14365d6c9881016e8b8ec90088903fb773c2b623277edfe121c7780bf72e7b049309ad9
7
- data.tar.gz: 69777208d9687dcf5038a182af1e97258aaba0b630798f4f0b61bab0fb1a473c9809664c18a7e9385e85cee2d6f2e3dcd5d9f3880720699f2533dea4aec985d6
6
+ metadata.gz: 7a30093a3a0a08781d22a13b2074a4908a5839ef69aaa0bf582d8ad5a1c0cd25afe1eaa3448e4451be5769d3ad8ba402625dc93fb26dd4b7fc0f80b03feb3ea4
7
+ data.tar.gz: c144f841a06d5222dabeca1a4f58cc71b23e4633b232d65a051d222cd1c4df79f20cb3a92d94062003e02840f27c1ab5d2edbbcf762bc0f40ba279e803bd09e9
data/README.md CHANGED
@@ -87,6 +87,19 @@ no preconfigured defaults.
87
87
  If you have issues with SSH connecting, make sure that the instances
88
88
  are being launched with a security group that allows SSH access.
89
89
 
90
+ Note: if you don't configure `aws.access_key_id` or `aws_secret_access_key`
91
+ it will attempt to read credentials from environment variables first and then
92
+ from `$HOME/.aws/`. You can choose your AWS profile and files location by using
93
+ `aws.aws_profile` and `aws.aws_dir`, however environment variables will always
94
+ have precedence as defined by the [AWS documentation](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html).
95
+ To use profile `vagrantDev` from your AWS files:
96
+ ```ruby
97
+ # this first line can actually be omitted
98
+ aws.aws_dir = ENV['HOME'] + "/.aws/"
99
+ aws.aws_profile = "vagrantDev"
100
+ ```
101
+
102
+
90
103
  ## Box Format
91
104
 
92
105
  Every provider in Vagrant must introduce a custom box format. This
@@ -106,6 +119,8 @@ This provider exposes quite a few provider-specific configuration options:
106
119
  * `ami` - The AMI id to boot, such as "ami-12345678"
107
120
  * `availability_zone` - The availability zone within the region to launch
108
121
  the instance. If nil, it will use the default set by Amazon.
122
+ * `aws_profile` - AWS profile in your config files. Defaults to *default*.
123
+ * `aws_dir` - AWS config and credentials location. Defaults to *$HOME/.aws/*.
109
124
  * `instance_ready_timeout` - The number of seconds to wait for the instance
110
125
  to become "ready" in AWS. Defaults to 120 seconds.
111
126
  * `instance_check_interval` - The number of seconds to wait to check the instance's
data/Rakefile CHANGED
@@ -15,7 +15,8 @@ Dir.chdir(File.expand_path("../", __FILE__))
15
15
  Bundler::GemHelper.install_tasks
16
16
 
17
17
  # Install the `spec` task so that we can run tests.
18
- RSpec::Core::RakeTask.new
19
-
18
+ RSpec::Core::RakeTask.new(:spec) do |t|
19
+ t.rspec_opts = "--order defined"
20
+ end
20
21
  # Default task is to run the unit tests
21
- task :default => "spec"
22
+ task :default => :spec
@@ -284,7 +284,7 @@ module VagrantPlugins
284
284
  end
285
285
 
286
286
  # Save this IP to the data dir so it can be released when the instance is destroyed
287
- if h
287
+ if h
288
288
  ip_file = env[:machine].data_dir.join('elastic_ip')
289
289
  ip_file.open('w+') do |f|
290
290
  f.write(h.to_json)
@@ -292,7 +292,7 @@ module VagrantPlugins
292
292
  end
293
293
  end
294
294
 
295
- def handle_elastic_ip_error(env, message)
295
+ def handle_elastic_ip_error(env, message)
296
296
  @logger.debug(message)
297
297
  terminate(env)
298
298
  raise Errors::FogError,
@@ -1,4 +1,5 @@
1
1
  require "vagrant"
2
+ require "iniparse"
2
3
 
3
4
  module VagrantPlugins
4
5
  module AWS
@@ -185,6 +186,16 @@ module VagrantPlugins
185
186
  # @return [String]
186
187
  attr_accessor :tenancy
187
188
 
189
+ # The directory where AWS files are stored (usually $HOME/.aws)
190
+ #
191
+ # @return [String]
192
+ attr_accessor :aws_dir
193
+
194
+ # The selected AWS named profile (as defined in $HOME/.aws/* files)
195
+ #
196
+ # @return [String]
197
+ attr_accessor :aws_profile
198
+
188
199
  def initialize(region_specific=false)
189
200
  @access_key_id = UNSET_VALUE
190
201
  @ami = UNSET_VALUE
@@ -220,6 +231,8 @@ module VagrantPlugins
220
231
  @unregister_elb_from_az = UNSET_VALUE
221
232
  @kernel_id = UNSET_VALUE
222
233
  @tenancy = UNSET_VALUE
234
+ @aws_dir = UNSET_VALUE
235
+ @aws_profile = UNSET_VALUE
223
236
 
224
237
  # Internal state (prefix with __ so they aren't automatically
225
238
  # merged)
@@ -304,11 +317,21 @@ module VagrantPlugins
304
317
  end
305
318
 
306
319
  def finalize!
307
- # Try to get access keys from standard AWS environment variables; they
308
- # will default to nil if the environment variables are not present.
309
- @access_key_id = ENV['AWS_ACCESS_KEY'] if @access_key_id == UNSET_VALUE
310
- @secret_access_key = ENV['AWS_SECRET_KEY'] if @secret_access_key == UNSET_VALUE
311
- @session_token = ENV['AWS_SESSION_TOKEN'] if @session_token == UNSET_VALUE
320
+ # If access_key_id or secret_access_key were not specified in Vagrantfile
321
+ # then try to read from environment variables first, and if it fails from
322
+ # the AWS folder.
323
+ if @access_key_id == UNSET_VALUE or @secret_access_key == UNSET_VALUE
324
+ @aws_profile = 'default' if @aws_profile == UNSET_VALUE
325
+ @aws_dir = ENV['HOME'].to_s + '/.aws/' if @aws_dir == UNSET_VALUE
326
+ @region, @access_key_id, @secret_access_key, @session_token = Credentials.new.get_aws_info(@aws_profile, @aws_dir)
327
+ @region = UNSET_VALUE if @region.nil?
328
+ else
329
+ @aws_profile = nil
330
+ @aws_dir = nil
331
+ end
332
+
333
+ # session token must be set to nil, empty string isn't enough!
334
+ @session_token = nil if @session_token == UNSET_VALUE
312
335
 
313
336
  # AMI must be nil, since we can't default that
314
337
  @ami = nil if @ami == UNSET_VALUE
@@ -414,6 +437,10 @@ module VagrantPlugins
414
437
  def validate(machine)
415
438
  errors = _detected_errors
416
439
 
440
+ errors << I18n.t("vagrant_aws.config.aws_info_required",
441
+ :profile => @aws_profile, :location => @aws_dir) if \
442
+ @aws_profile and (@access_key_id.nil? or @secret_access_key.nil? or @region.nil?)
443
+
417
444
  errors << I18n.t("vagrant_aws.config.region_required") if @region.nil?
418
445
 
419
446
  if @region
@@ -449,5 +476,89 @@ module VagrantPlugins
449
476
  @__compiled_region_configs[name] || self
450
477
  end
451
478
  end
479
+
480
+
481
+ class Credentials < Vagrant.plugin("2", :config)
482
+ # This module reads AWS config and credentials.
483
+ # Behaviour aims to mimic what is described in AWS documentation:
484
+ # http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html
485
+ # http://docs.aws.amazon.com/cli/latest/topic/config-vars.html
486
+ # Which is the following (stopping at the first successful case):
487
+ # 1) read config and credentials from environment variables
488
+ # 2) read config and credentials from files at location defined by environment variables
489
+ # 3) read config and credentials from files at default location
490
+ #
491
+ # The mandatory fields for a successful "get credentials" are the id and the secret keys.
492
+ # Region is not required since Config#finalize falls back to sensible defaults.
493
+ # The behaviour is all-or-nothing (ie: no mixing between vars and files).
494
+ #
495
+ # It also allows choosing a profile (by default it's [default]) and an "info"
496
+ # directory (by default $HOME/.aws), which can be specified in the Vagrantfile.
497
+ # Supported information: region, aws_access_key_id, aws_secret_access_key, and aws_session_token.
498
+
499
+ def get_aws_info(profile, location)
500
+ # read credentials from environment variables
501
+ aws_region, aws_id, aws_secret, aws_token = read_aws_environment()
502
+ # if nothing there, then read from files
503
+ # (the _if_ doesn't check aws_region since Config#finalize sets one by default)
504
+ if aws_id.to_s == '' or aws_secret.to_s == ''
505
+ # check if there are env variables for credential location, if so use then
506
+ aws_config = ENV['AWS_CONFIG_FILE'].to_s
507
+ aws_creds = ENV['AWS_SHARED_CREDENTIALS_FILE'].to_s
508
+ if aws_config == '' or aws_creds == ''
509
+ aws_config = location + 'config'
510
+ aws_creds = location + 'credentials'
511
+ end
512
+ if File.exist?(aws_config) and File.exist?(aws_creds)
513
+ aws_region, aws_id, aws_secret, aws_token = read_aws_files(profile, aws_config, aws_creds)
514
+ end
515
+ end
516
+ aws_region = nil if aws_region == ''
517
+ aws_id = nil if aws_id == ''
518
+ aws_secret = nil if aws_secret == ''
519
+ aws_token = nil if aws_token == ''
520
+
521
+ return aws_region, aws_id, aws_secret, aws_token
522
+ end
523
+
524
+
525
+ private
526
+
527
+ def read_aws_files(profile, aws_config, aws_creds)
528
+ # determine section in config ini file
529
+ if profile == 'default'
530
+ ini_profile = profile
531
+ else
532
+ ini_profile = 'profile ' + profile
533
+ end
534
+ # get info from config ini file for selected profile
535
+ data = File.read(aws_config)
536
+ doc_cfg = IniParse.parse(data)
537
+ aws_region = doc_cfg[ini_profile]['region']
538
+
539
+ # determine section in credentials ini file
540
+ ini_profile = profile
541
+ # get info from credentials ini file for selected profile
542
+ data = File.read(aws_creds)
543
+ doc_cfg = IniParse.parse(data)
544
+ aws_id = doc_cfg[ini_profile]['aws_access_key_id']
545
+ aws_secret = doc_cfg[ini_profile]['aws_secret_access_key']
546
+ aws_token = doc_cfg[ini_profile]['aws_session_token']
547
+
548
+ return aws_region, aws_id, aws_secret, aws_token
549
+ end
550
+
551
+ def read_aws_environment()
552
+ aws_region = ENV['AWS_DEFAULT_REGION']
553
+ aws_id = ENV['AWS_ACCESS_KEY_ID']
554
+ aws_secret = ENV['AWS_SECRET_ACCESS_KEY']
555
+ aws_token = ENV['AWS_SESSION_TOKEN']
556
+
557
+ return aws_region, aws_id, aws_secret, aws_token
558
+ end
559
+
560
+ end
561
+
562
+
452
563
  end
453
564
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module AWS
3
- VERSION = '0.7.0'
3
+ VERSION = '0.7.1'
4
4
  end
5
5
  end
@@ -76,6 +76,9 @@ en:
76
76
  A secret access key is required via "secret_access_key"
77
77
  subnet_id_required_with_public_ip: |-
78
78
  If you assign a public IP address to an instance in a VPC, a subnet must be specifed via "subnet_id"
79
+ aws_info_required: |-
80
+ One or more of the needed AWS credentials are missing. No environment variables
81
+ are set nor profile '%{profile}' exists at '%{location}'
79
82
 
80
83
  errors:
81
84
  fog_error: |-
@@ -1,6 +1,18 @@
1
1
  require "vagrant-aws/config"
2
2
  require 'rspec/its'
3
3
 
4
+ # remove deprecation warnings
5
+ # (until someone decides to update the whole spec file to rspec 3.4)
6
+ RSpec.configure do |config|
7
+ # ...
8
+ config.mock_with :rspec do |c|
9
+ c.syntax = [:should, :expect]
10
+ end
11
+ config.expect_with :rspec do |c|
12
+ c.syntax = [:should, :expect]
13
+ end
14
+ end
15
+
4
16
  describe VagrantPlugins::AWS::Config do
5
17
  let(:instance) { described_class.new }
6
18
 
@@ -62,6 +74,10 @@ describe VagrantPlugins::AWS::Config do
62
74
  :source_dest_check].each do |attribute|
63
75
 
64
76
  it "should not default #{attribute} if overridden" do
77
+ # but these should always come together, so you need to set them all or nothing
78
+ instance.send("access_key_id=".to_sym, "foo")
79
+ instance.send("secret_access_key=".to_sym, "foo")
80
+ instance.send("session_token=".to_sym, "foo")
65
81
  instance.send("#{attribute}=".to_sym, "foo")
66
82
  instance.finalize!
67
83
  instance.send(attribute).should == "foo"
@@ -89,8 +105,8 @@ describe VagrantPlugins::AWS::Config do
89
105
 
90
106
  context "with EC2 credential environment variables" do
91
107
  before :each do
92
- ENV.stub(:[]).with("AWS_ACCESS_KEY").and_return("access_key")
93
- ENV.stub(:[]).with("AWS_SECRET_KEY").and_return("secret_key")
108
+ ENV.stub(:[]).with("AWS_ACCESS_KEY_ID").and_return("access_key")
109
+ ENV.stub(:[]).with("AWS_SECRET_ACCESS_KEY").and_return("secret_key")
94
110
  ENV.stub(:[]).with("AWS_SESSION_TOKEN").and_return("session_token")
95
111
  end
96
112
 
@@ -106,6 +122,124 @@ describe VagrantPlugins::AWS::Config do
106
122
  end
107
123
  end
108
124
 
125
+
126
+ describe "getting credentials when there is an AWS profile" do
127
+ ## ENV has been nuked so ENV['HOME'] will be a empty string when Credentials#get_aws_info gets called
128
+ let(:filename_cfg) { "/.aws/config" }
129
+ let(:filename_keys) { "/.aws/credentials" }
130
+ let(:data_cfg) {
131
+ "[default]
132
+ region=eu-west-1
133
+ output=json
134
+
135
+ [profile user1]
136
+ region=us-east-1
137
+ output=text
138
+
139
+ [profile user2]
140
+ region=us-east-1
141
+ output=text
142
+
143
+ [profile user3]
144
+ region=us-west-2
145
+ output=text
146
+ " }
147
+ let(:data_keys) {
148
+ "[default]
149
+ aws_access_key_id=AKIdefault
150
+ aws_secret_access_key=PASSdefault
151
+
152
+ [user1]
153
+ aws_access_key_id=AKIuser1
154
+ aws_secret_access_key=PASSuser1
155
+
156
+ [user2]
157
+ aws_access_key_id=AKIuser2
158
+ aws_secret_access_key=PASSuser2
159
+ aws_session_token=TOKuser2
160
+
161
+ [user3]
162
+ aws_access_key_id=AKIuser3
163
+ aws_secret_access_key=PASSuser3
164
+ aws_session_token= TOKuser3
165
+ " }
166
+ # filenames and file data when using AWS_SHARED_CREDENTIALS_FILE and AWS_CONFIG_FILE
167
+ let(:sh_dir) { "/aws_shared/" }
168
+ let(:sh_filename_cfg) { sh_dir + "config" }
169
+ let(:sh_filename_keys) { sh_dir + "credentials" }
170
+ let(:sh_data_cfg) { "[default]\nregion=sh-region\noutput=text" }
171
+ let(:sh_data_keys) { "[default]\naws_access_key_id=AKI_set_shared\naws_secret_access_key=set_shared_foobar" }
172
+
173
+ context "with EC2 credential environment variables set" do
174
+ subject do
175
+ ENV.stub(:[]).with("AWS_ACCESS_KEY_ID").and_return("env_access_key")
176
+ ENV.stub(:[]).with("AWS_SECRET_ACCESS_KEY").and_return("env_secret_key")
177
+ ENV.stub(:[]).with("AWS_SESSION_TOKEN").and_return("env_session_token")
178
+ ENV.stub(:[]).with("AWS_DEFAULT_REGION").and_return("env_region")
179
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
180
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
181
+ instance.tap do |o|
182
+ o.finalize!
183
+ end
184
+ end
185
+ its("access_key_id") { should == "env_access_key" }
186
+ its("secret_access_key") { should == "env_secret_key" }
187
+ its("session_token") { should == "env_session_token" }
188
+ its("region") { should == "env_region" }
189
+ end
190
+
191
+ context "without EC2 credential environment variables but with AWS_CONFIG_FILE and AWS_SHARED_CREDENTIALS_FILE set" do
192
+ subject do
193
+ allow(File).to receive(:exist?).and_return(true)
194
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
195
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
196
+ ENV.stub(:[]).with("AWS_CONFIG_FILE").and_return(sh_filename_cfg)
197
+ ENV.stub(:[]).with("AWS_SHARED_CREDENTIALS_FILE").and_return(sh_filename_keys)
198
+ allow(File).to receive(:read).with(sh_filename_cfg).and_return(sh_data_cfg)
199
+ allow(File).to receive(:read).with(sh_filename_keys).and_return(sh_data_keys)
200
+ instance.tap do |o|
201
+ o.finalize!
202
+ end
203
+ end
204
+ its("access_key_id") { should == "AKI_set_shared" }
205
+ its("secret_access_key") { should == "set_shared_foobar" }
206
+ its("session_token") { should be_nil }
207
+ its("region") { should == "sh-region" }
208
+ end
209
+
210
+ context "without any credential environment variables and fallback to default profile at default location" do
211
+ subject do
212
+ allow(File).to receive(:exist?).and_return(true)
213
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
214
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
215
+ instance.tap do |o|
216
+ o.finalize!
217
+ end
218
+ end
219
+ its("access_key_id") { should == "AKIdefault" }
220
+ its("secret_access_key") { should == "PASSdefault" }
221
+ its("session_token") { should be_nil }
222
+ end
223
+
224
+ context "without any credential environment variables and chosing a profile" do
225
+ subject do
226
+ allow(File).to receive(:exist?).and_return(true)
227
+ allow(File).to receive(:read).with(filename_cfg).and_return(data_cfg)
228
+ allow(File).to receive(:read).with(filename_keys).and_return(data_keys)
229
+ instance.aws_profile = "user3"
230
+ instance.tap do |o|
231
+ o.finalize!
232
+ end
233
+ end
234
+ its("access_key_id") { should == "AKIuser3" }
235
+ its("secret_access_key") { should == "PASSuser3" }
236
+ its("session_token") { should == "TOKuser3" }
237
+ its("region") { should == "us-west-2" }
238
+ end
239
+ end
240
+
241
+
242
+
109
243
  describe "region config" do
110
244
  let(:config_access_key_id) { "foo" }
111
245
  let(:config_ami) { "foo" }
@@ -187,6 +321,7 @@ describe VagrantPlugins::AWS::Config do
187
321
 
188
322
  # Set some top-level values
189
323
  instance.access_key_id = "parent"
324
+ instance.secret_access_key = "parent"
190
325
  instance.ami = "parent"
191
326
 
192
327
  # Finalize and get the region
@@ -195,6 +330,7 @@ describe VagrantPlugins::AWS::Config do
195
330
  end
196
331
 
197
332
  its("access_key_id") { should == "parent" }
333
+ its("secret_access_key") { should == "parent" }
198
334
  its("ami") { should == "child" }
199
335
  end
200
336
 
@@ -16,9 +16,11 @@ Gem::Specification.new do |s|
16
16
  s.rubyforge_project = "vagrant-aws"
17
17
 
18
18
  s.add_runtime_dependency "fog", "~> 1.22"
19
+ s.add_runtime_dependency "iniparse", "~> 1.4", ">= 1.4.2"
19
20
 
20
21
  s.add_development_dependency "rake"
21
- s.add_development_dependency "rspec", "~> 2.12"
22
+ # rspec 3.4 to mock File
23
+ s.add_development_dependency "rspec", "~> 3.4"
22
24
  s.add_development_dependency "rspec-its"
23
25
 
24
26
  # The following block of code determines the files that should be included
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mitchell Hashimoto
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-04 00:00:00.000000000 Z
11
+ date: 2016-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: fog
@@ -24,6 +24,26 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.22'
27
+ - !ruby/object:Gem::Dependency
28
+ name: iniparse
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.4'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 1.4.2
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.4'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 1.4.2
27
47
  - !ruby/object:Gem::Dependency
28
48
  name: rake
29
49
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +64,14 @@ dependencies:
44
64
  requirements:
45
65
  - - "~>"
46
66
  - !ruby/object:Gem::Version
47
- version: '2.12'
67
+ version: '3.4'
48
68
  type: :development
49
69
  prerelease: false
50
70
  version_requirements: !ruby/object:Gem::Requirement
51
71
  requirements:
52
72
  - - "~>"
53
73
  - !ruby/object:Gem::Version
54
- version: '2.12'
74
+ version: '3.4'
55
75
  - !ruby/object:Gem::Dependency
56
76
  name: rspec-its
57
77
  requirement: !ruby/object:Gem::Requirement
@@ -135,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
155
  version: 1.3.6
136
156
  requirements: []
137
157
  rubyforge_project: vagrant-aws
138
- rubygems_version: 2.4.3
158
+ rubygems_version: 2.5.1
139
159
  signing_key:
140
160
  specification_version: 4
141
161
  summary: Enables Vagrant to manage machines in EC2 and VPC.