mist_aws 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ecbfb2c243c78f6e0b31be95db7ba6f10abe271f
4
+ data.tar.gz: 8f10d71ae5f7c1ae0a29aec510bbeea1d8506c65
5
+ SHA512:
6
+ metadata.gz: 7137a1ecf189cecbf4ee81b43a263ecf97db5798e4e096f3b319b9706357bca2e417f40eb6259ceac0ddc2d33696e3405a745757d7a6c5765263b01404ad20dc
7
+ data.tar.gz: 40ac0d83153c646e93cce36f9a23c223eccf373fa65f6c3f27011fdfc997de034a801589c1408abad43a260948bf5c87aa3ae01089b61cb22921b4eddcdcec78
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mist_aws.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Robert J. Berger
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # MistAws
2
+
3
+ Uses the [ruby aws-sdk v2](https://github.com/aws/aws-sdk-core-ruby) [Resource Interface](https://github.com/aws/aws-sdk-core-ruby#resource-interfaces) to create some use specific higher level functionality.
4
+
5
+ > NOTE: Currently the only object implemented is IAM for creating / deleting instance roles
6
+
7
+
8
+ ## Installation
9
+
10
+ ### Install the Gem
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'mist_aws'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install mist_aws
25
+
26
+ ### Generate Yard Docs
27
+
28
+ $ rake yard
29
+ $ open doc/index.html
30
+
31
+ ## Usage
32
+
33
+ * Get the handle to the MistAws::Iam object
34
+ * Credentials will come from the `my_profile_name` profile in ~/.aws/credentials as per [Providing AWS Credentials in the AWS SDK for Ruby] (http://docs.aws.amazon.com/AWSSdkDocsRuby/latest/DeveloperGuide/prog-basics-creds.html#creds-explicit)
35
+ ```
36
+ mist_aws = ::MistAws::Iam.new(profile_name: "my_profile_name", region: "us-east-1")
37
+ ```
38
+ * Create an IAM Role
39
+ * role_policy_document is a JSON text file that is an [AWS IAM policy](http://docs.aws.amazon.com/IAM/latest/UserGuide/PoliciesOverview.html)
40
+ * This method will create:
41
+ * [Role](http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/Role.html)
42
+ * [Role Policy](http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/RolePolicy.html)
43
+ * [Instance profile](http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/InstanceProfile.html)
44
+ * Connect them all together
45
+ * Returns a [Role](http://docs.aws.amazon.com/sdkforruby/api/Aws/IAM/Role.html) Resource instance
46
+ ```
47
+ role = mist_aws.create_iam_role(role_name, role_policy_name, role_policy_document, instance_profile_name)
48
+ ```
49
+
50
+ ## Contributing
51
+
52
+ I would be very interested in feedback on things that could be done
53
+ better. Also would be interested in how to better do the rspec
54
+ tests. I felt like there was WAY too much mocking. I did find it
55
+ useful for finding bugs and broken assumptions though.
56
+
57
+
58
+ 1. Fork it ( https://github.com/[my-github-username]/mist_aws/fork )
59
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
60
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
61
+ 4. Push to the branch (`git push origin my-new-feature`)
62
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
7
+
8
+ require "yard"
9
+
10
+ current_dir = File.dirname(__FILE__)
11
+
12
+ YARD::Rake::YardocTask.new do |t|
13
+ t.files = ["#{current_dir}/**/*.rb"]
14
+ #t.options = ['--debug']
15
+ end
data/lib/mist_aws.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "mist_aws/version"
2
+ require "mist_aws/iam"
3
+
4
+ module MistAws
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,186 @@
1
+ require 'json'
2
+ require 'inifile'
3
+ require 'pp'
4
+ require 'aws-sdk'
5
+ require 'time'
6
+ require 'tempfile'
7
+ require 'pry'
8
+ require 'logger'
9
+
10
+ module MistAws
11
+ class Iam
12
+
13
+ # These are read-only accessor and are initializeds by initialize method
14
+ attr_reader :profile_name
15
+ attr_reader :credentials
16
+ attr_reader :region
17
+ attr_reader :logger
18
+ attr_reader :handle
19
+ attr_reader :iam_client
20
+ attr_reader :iam
21
+
22
+
23
+ # Initializes all you need to access aws resources in a region
24
+ # You can create multiple instances to allow access to multiple regions in one program/recipe
25
+ #
26
+ # @param opts [Hash] the key/value pairs for the initializer
27
+ # @option opts [String] :profile_name ('default' or ENV['AWS_PROFILE']) profile name to use to get creds from ~/.aws/credentials.
28
+ # @option opts [String] :region (us-east-1 or ENV['AWS_REGION']) AWS Region to use
29
+ # @option opts [Logger] :logger (STDERR) A logger instance to use for logging
30
+ # @return [MistAws::Iam]
31
+ #
32
+ def initialize(opts={})
33
+ # Ruby 1.9 backwards compatability
34
+ opts = {profile_name: nil, region: nil, logger: ::Logger.new(STDERR)}.merge(opts)
35
+ opts.each do |key, value|
36
+ instance_variable_set "@#{key}", value
37
+ end
38
+
39
+ # Set by rspec tests that are testing methods called by initialize
40
+ return if ENV['RSPEC_IGNORE_INITIALIZE']
41
+
42
+ @region ||= ENV['AWS_REGION'] ? ENV['AWS_REGION'] : 'us-east-1'
43
+
44
+ # Note get_creds also resolves and sets @profile_name as well as
45
+ # fetching the appropriate credentials based on the value of
46
+ # profile_name and various Environment Variables
47
+ @credentials = get_creds(profile_name)
48
+
49
+ @iam_client = Aws::IAM::Client.new(credentials: @credentials, region: @region)
50
+ @iam = Aws::IAM::Resource.new(client: @iam_client)
51
+ end
52
+
53
+
54
+ # Returns the proper Aws credential object.
55
+ #
56
+ # @param profile_name [String] (nil) Name of profile
57
+ # @return [Aws::SharedCredentials | Aws::Credentials]
58
+ #
59
+ def get_creds(profile_name=nil)
60
+ unless profile_name
61
+ if ENV['AWS_PROFILE']
62
+ @profile_name = ENV['AWS_PROFILE']
63
+ else
64
+ if ENV['AWS_ACCESS_KEY_ID'] && ENV['AWS_SECRET_ACCESS_KEY']
65
+ return Aws::Credentials.new(ENV['AWS_ACCESS_KEY_ID'], ENV['AWS_SECRET_ACCESS_KEY'])
66
+ else
67
+ @profile_name = 'default'
68
+ end
69
+ end
70
+ else
71
+ @profile_name = profile_name
72
+ end
73
+
74
+ begin
75
+ Aws::SharedCredentials.new(profile_name: @profile_name)
76
+ rescue StandardError => e
77
+ @logger.error e.inspect
78
+ raise e
79
+ end
80
+ end
81
+
82
+ # Check if a role exists
83
+ def role_exists?(role_name)
84
+ begin
85
+ iam_client.get_role role_name: role_name
86
+ rescue ::Aws::IAM::Errors::NoSuchEntity
87
+ return false
88
+ end
89
+ return true
90
+ end
91
+
92
+ # Check if an instance profile exists
93
+ def instance_profile_exists?(instance_profile_name)
94
+ instance_profile = iam.instance_profile(instance_profile_name)
95
+ case instance_profile.data_loaded?
96
+ when true
97
+ return instance_profile
98
+ else
99
+ return nil
100
+ end
101
+ end
102
+
103
+ # Check if there is a role_policy
104
+ def role_policy_exists?(role_name, policy_name)
105
+ begin
106
+ iam_client.get_role_policy(role_name: role_name, policy_name: policy_name)
107
+ exists = true
108
+ rescue Aws::IAM::Errors::NoSuchEntityException
109
+ logger.warn "No role_polcy: #{policy_name.inspect} for role: #{role_name.inspect}"
110
+ exists = false
111
+ end
112
+ exists
113
+ end
114
+
115
+ #
116
+ # Delete role, policy and instance_profile if they exist
117
+ #
118
+ def delete_iam_role(role_name, policy_name, instance_profile_name=nil)
119
+ unless role_exists? role_name
120
+ logger.warn "MistAws::Iam#delete_iam_role: No role: #{role_name.inspect}; Doing nothing"
121
+ return nil
122
+ end
123
+
124
+ role = iam.role role_name
125
+
126
+ # Removes the role from the instance_profiles
127
+ # Deletes the instance_profile
128
+ instance_profiles = role.instance_profiles
129
+ instance_profiles.each do | instance_profile |
130
+ instance_profile.remove_role role_name: role_name
131
+ instance_profile.delete
132
+ end
133
+
134
+ # Delete the role_policies associated with the role
135
+ role_policies = role.policies
136
+ role_policies.each do | role_policy |
137
+ role_policy.delete
138
+ end
139
+
140
+ # Delete the Role
141
+ role.delete
142
+
143
+ true
144
+ end
145
+
146
+ #
147
+ # Create an IAM role to be assigned to an ec2 instance
148
+ # Returns the Role object
149
+ #
150
+ # @param role_name [String] Name of the role to create
151
+ # @param policy_name [String]
152
+ def create_iam_role(role_name, policy_name, policy_document, instance_profile_name=nil)
153
+ result = role_exists? role_name
154
+ if result
155
+ logger.warn "MistAws::Iam#create_iam_role: Role: #{role_name.inspect} already exists; Doing nothing"
156
+ return nil
157
+ end
158
+
159
+ assume_role_policy = {
160
+ "Version" => "2012-10-17",
161
+ "Statement" => [
162
+ {"Effect" => "Allow",
163
+ "Principal" => {
164
+ "Service" => [
165
+ "ec2.amazonaws.com"
166
+ ]
167
+ },
168
+ "Action" => ["sts:AssumeRole"]
169
+ }
170
+ ]
171
+ }.to_json
172
+
173
+ # Create the role
174
+ role = iam.create_role(role_name: role_name, assume_role_policy_document: assume_role_policy)
175
+
176
+ # Create a policy object associated to the role and stuff the policy document into it
177
+ policy = Aws::IAM::RolePolicy.new(role_name: role_name, name: policy_name, client: iam_client)
178
+ policy.put(policy_document: policy_document)
179
+
180
+ # Create an instance_profile
181
+ instance_profile = iam.create_instance_profile(instance_profile_name: instance_profile_name)
182
+ instance_profile.add_role(role_name: role_name)
183
+ role
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,3 @@
1
+ module MistAws
2
+ VERSION = "0.1.0"
3
+ end
data/mist_aws.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mist_aws/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mist_aws"
8
+ spec.version = MistAws::VERSION
9
+ spec.authors = ["Robert J. Berger"]
10
+ spec.email = ["rberger@mistsys.com"]
11
+ spec.summary = %q{Wrapper around aws-sdk for higher level use}
12
+ spec.description = %q{Wrapper around aws-sdk for higher level use. So far only supports IAM Role create/delete}
13
+ spec.homepage = "https://github.com/mistsys/mist_aws"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.1.0"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "yard"
26
+ spec.add_dependency "aws-sdk", "~>2.0.1.pre"
27
+ spec.add_dependency "json"
28
+ spec.add_dependency "inifile"
29
+ end
@@ -0,0 +1,77 @@
1
+ # These tests actually hit AWS and are not mocked
2
+
3
+ require 'spec_helper'
4
+ require 'json'
5
+
6
+ include MistAws
7
+
8
+ describe "Live tests on AWS (not mocked)" do
9
+ describe Iam do
10
+ PRE = "trsh"
11
+ let(:profile_name) { 'mistsys' }
12
+ let(:region) { 'us-east-1' }
13
+ let(:role_name) { "#{PRE}_my_role" }
14
+ let(:role_policy_name) { "#{PRE}_my_role_policy_name" }
15
+ let(:instance_profile_name) { "#{PRE}_my_instance_profile" }
16
+ let(:test_dir) { File.dirname(__FILE__) }
17
+ let(:role_policy_document_filename) { "#{test_dir}/policy_document.txt" }
18
+ let(:role_policy_document) { File.readlines(role_policy_document_filename).join("\n") }
19
+ let(:assume_role_policy) {
20
+ {
21
+ "Version" => "2012-10-17",
22
+ "Statement" => [
23
+ {"Effect" => "Allow",
24
+ "Principal" => {
25
+ "Service" => [
26
+ "ec2.amazonaws.com"
27
+ ]
28
+ },
29
+ "Action" => ["sts:AssumeRole"]
30
+ }
31
+ ]
32
+ }.to_json
33
+ }
34
+
35
+ let(:test_credentials) { ::Aws::SharedCredentials.new(profile_name: profile_name) }
36
+ let(:test_iam_client) { ::Aws::IAM::Client.new(credentials: test_credentials, region: region) }
37
+ let(:test_iam) { ::Aws::IAM::Resource.new(client: test_iam_client) }
38
+
39
+ let(:mist_aws) { ::MistAws::Iam.new(profile_name: profile_name, region: region) }
40
+
41
+ describe '#create_iam_role' do
42
+ context 'when no role already exists' do
43
+ before(:each) do
44
+ allow(mist_aws.logger).to receive(:warn).with(/No role/)
45
+ mist_aws.delete_iam_role(role_name, role_policy_name, instance_profile_name)
46
+ end
47
+
48
+ after(:each) do
49
+ mist_aws.delete_iam_role(role_name, role_policy_name, instance_profile_name)
50
+ end
51
+
52
+ it 'creates a role' do
53
+ test_role = mist_aws.create_iam_role(role_name, role_policy_name, role_policy_document, instance_profile_name)
54
+ # test_role = test_iam.role role_name
55
+ expect(test_role.name).to eq role_name
56
+ expect(test_role.assume_role_policy_document).to include 'Statement'
57
+ end
58
+ end
59
+ end
60
+
61
+ context 'when a role already exists' do
62
+ before(:each) do
63
+ allow(mist_aws.logger).to receive(:warn).with(/already exists/)
64
+ mist_aws.create_iam_role(role_name, role_policy_name, role_policy_document, instance_profile_name)
65
+ end
66
+
67
+ after(:each) do
68
+ mist_aws.delete_iam_role(role_name, role_policy_name, instance_profile_name)
69
+ end
70
+
71
+ it 'returns falsy' do
72
+ expect(mist_aws.role_exists? role_name).to be_truthy
73
+ expect(mist_aws.create_iam_role(role_name, role_policy_name, role_policy_document, instance_profile_name)).to be_falsy
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,231 @@
1
+ # These should be purly mocked and not hit AWS
2
+
3
+ require 'spec_helper'
4
+ require 'json'
5
+
6
+ include MistAws
7
+
8
+ describe "Fully Mocked Tests" do
9
+ describe Iam do
10
+ it 'has a version number' do
11
+ expect(MistAws::VERSION).not_to be nil
12
+ end
13
+
14
+
15
+ let(:my_profile_name) { 'arg_specified_profile_name' }
16
+ let(:env_profile_name) { 'env_profile_name' }
17
+ let(:access_key_value) { 'access_key_value' }
18
+ let(:default_region) { 'us-east-1' }
19
+
20
+ let(:mist_aws) { ::MistAws::Iam.new }
21
+ let(:role_name) { "my_role" }
22
+ let(:role_policy_name) { "my_role_policy_name" }
23
+ let(:role_policy_document) { "my_role_policy_document" }
24
+ let(:instance_profile_name) { "my_instance_profile" }
25
+
26
+ let (:shared_credentials) { instance_double("::Aws::SharedCredentials") }
27
+ #let(:credentials) {object_double(::Aws::SharedCredentials.new(profile_name: 'default')) }
28
+ let(:iam_client) { object_double(::Aws::IAM::Client.new(credentials: shared_credentials, region: 'us-east-1')) }
29
+ let(:iam) { object_double(::Aws::IAM::Resource.new(client: iam_client)) }
30
+ let(:context) { object_double(::Seahorse::Client::RequestContext) }
31
+
32
+ let(:role_policy) { instance_double("Aws::IAM::RolePolicy", role_name: role_name, name: role_policy_name) }
33
+ let(:instance_profile) { instance_double("Aws::IAM::InstanceProfile",name: instance_profile_name) }
34
+
35
+ let(:assume_role_policy) {
36
+ {
37
+ "Version" => "2012-10-17",
38
+ "Statement" => [
39
+ {"Effect" => "Allow",
40
+ "Principal" => {
41
+ "Service" => [
42
+ "ec2.amazonaws.com"
43
+ ]
44
+ },
45
+ "Action" => ["sts:AssumeRole"]
46
+ }
47
+ ]
48
+ }.to_json
49
+ }
50
+
51
+ let(:role) { object_double(::Aws::IAM::Role.new(name: role_name, client: iam_client)) }
52
+
53
+ before(:example, :run_global_before) do
54
+ ENV['AWS_PROFILE'] = ENV['AWS_REGION'] = ENV['AWS_ACCESS_KEY_ID'] = ENV['AWS_SECRET_ACCESS_KEY']= nil
55
+ allow_any_instance_of(::MistAws::Iam).to receive(:get_creds).and_return(shared_credentials)
56
+ allow(::Aws::IAM::Client).to receive(:new).with(credentials: shared_credentials, region: default_region).and_return(iam_client)
57
+ allow(::Aws::IAM::Resource).to receive(:new).with(client: iam_client).and_return(iam)
58
+ end
59
+
60
+ after(:example) do
61
+ ENV['RSPEC_IGNORE_INITIALIZE'] = nil
62
+ end
63
+
64
+ describe '#get_creds' do
65
+ before(:example) do
66
+ ENV['RSPEC_IGNORE_INITIALIZE'] = 'true'
67
+ ENV['AWS_PROFILE'] = ENV['AWS_REGION'] = ENV['AWS_ACCESS_KEY_ID'] = ENV['AWS_SECRET_ACCESS_KEY']= nil
68
+ end
69
+
70
+ context 'when all inputs are nil' do
71
+ it 'will fetch the default shared credential' do
72
+ expect(::Aws::SharedCredentials).to receive(:new).with(profile_name: 'default')
73
+ my_mist_aws = ::MistAws::Iam.new
74
+ my_mist_aws.get_creds
75
+ end
76
+ end
77
+
78
+ context 'profile is specified in arguments' do
79
+
80
+ it 'will fetch the profile specified by argument' do
81
+ expect(::Aws::SharedCredentials).to receive(:new).with(profile_name: my_profile_name)
82
+ mist_aws.get_creds(my_profile_name)
83
+ end
84
+
85
+
86
+ it 'will ignore ENV["AWS_PROFILE"]' do
87
+ ENV['AWS_PROFILE'] = 'invalid_profile_name'
88
+ expect(::Aws::SharedCredentials).to receive(:new).with(profile_name: my_profile_name)
89
+ mist_aws.get_creds(my_profile_name)
90
+ end
91
+ it 'will ignore ENV["AWS_ACCESS_KEY_ID"], ENV["AWS_SECRET_ACCESS_KEY"]' do
92
+ ENV['AWS_ACCESS_KEY_ID'] = ENV['AWS_SECRET_ACCESS_KEY'] = access_key_value
93
+ expect(::Aws::SharedCredentials).to receive(:new).with(profile_name: my_profile_name)
94
+ mist_aws.get_creds(my_profile_name)
95
+ end
96
+ end
97
+
98
+ context 'profile only specified in ENV["AWS_PROFILE"]' do
99
+ before(:example) do
100
+ ENV['AWS_PROFILE'] = env_profile_name
101
+ ENV['AWS_ACCESS_KEY_ID'] = ENV['AWS_SECRET_ACCESS_KEY'] = access_key_value
102
+ end
103
+
104
+ it 'will fetch the profile specified by ENV["AWS_PROFILE\`]' do
105
+ expect(::Aws::SharedCredentials).to receive(:new).with(profile_name: env_profile_name)
106
+ mist_aws.get_creds
107
+ end
108
+
109
+ context "only ENV['AWS_ACCESS_KEY_ID'] and ENV['AWS_SECRET_ACCESS_KEY'] are set" do
110
+ before(:example) do
111
+ ENV['AWS_PROFILE'] = nil
112
+ end
113
+ it 'will use Aws::Credentials and not Aws::SharedCredentials' do
114
+ expect(::Aws::SharedCredentials).not_to receive(:new)
115
+ expect(::Aws::Credentials).to receive(:new).with(access_key_value, access_key_value)
116
+
117
+ mist_aws.get_creds
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ describe '.initialize', :run_global_before do
124
+ context 'when all inputs are nil' do
125
+ before(:example) do
126
+ expect_any_instance_of(Iam).to receive(:get_creds).with(nil).and_return(shared_credentials)
127
+ end
128
+
129
+ it 'initializes an IAM Client' do
130
+ expect(Aws::IAM::Client).to receive(:new).with({credentials: shared_credentials, region: default_region})
131
+ Iam.new
132
+ end
133
+ end
134
+ end
135
+
136
+ describe '#role_exists?', :run_global_before do
137
+ it 'returns truthy when it exists' do
138
+ expect(iam_client).to receive(:get_role).with(role_name: role_name).and_return(role)
139
+
140
+ expect(mist_aws.role_exists?(role_name)).to be_truthy
141
+ end
142
+
143
+ it 'returns falsy when it does not exist' do
144
+ expect(iam_client).to receive(:get_role).with(role_name: role_name).and_raise(Aws::IAM::Errors::NoSuchEntity.new(context, 'foo'))
145
+
146
+ expect(mist_aws.role_exists?(role_name)).to be_falsy
147
+ end
148
+ end
149
+
150
+ describe '#instance_profile_exists?', :run_global_before do
151
+ it 'returns truthy when it exists' do
152
+ expect(iam).to receive(:instance_profile).with(instance_profile_name).and_return(instance_profile)
153
+ expect(instance_profile).to receive(:data_loaded?).and_return(true)
154
+
155
+ expect(mist_aws.instance_profile_exists?(instance_profile_name)).to be_truthy
156
+ end
157
+
158
+ it 'returns falsy when it does not exist' do
159
+ expect(iam).to receive(:instance_profile).with(instance_profile_name).and_return(instance_profile)
160
+ expect(instance_profile).to receive(:data_loaded?).and_return(false)
161
+
162
+ expect(mist_aws.instance_profile_exists?(instance_profile_name)).to be_falsy
163
+ end
164
+ end
165
+
166
+ describe '#role_policy_exists?', :run_global_before do
167
+ it 'returns truthy when it exists' do
168
+ expect(iam_client).to receive(:get_role_policy).with(role_name: role_name, policy_name: role_policy_name).and_return(role_policy)
169
+
170
+ expect(mist_aws.role_policy_exists?(role_name, role_policy_name)).to be_truthy
171
+ end
172
+
173
+ it 'returns falsy when it does not exist' do
174
+ expect(mist_aws.logger).to receive(:warn).with(/No role/)
175
+ expect(iam_client).to receive(:get_role_policy).with(role_name: role_name, policy_name: role_policy_name).and_raise(Aws::IAM::Errors::NoSuchEntityException.new(context, 'foo'))
176
+
177
+ expect(mist_aws.role_policy_exists?(role_name, role_policy_name)).to be_falsy
178
+ end
179
+ end
180
+
181
+ describe '#create_iam_role', :run_global_before do
182
+ it 'creates an IAM role with a role policy and an instance_profile' do
183
+ expect_any_instance_of(::MistAws::Iam).to receive(:role_exists?).with(role_name).and_return(false)
184
+ expect(iam).to receive(:create_role).with(role_name: role_name, assume_role_policy_document: assume_role_policy).and_return(role)
185
+
186
+ expect(::Aws::IAM::RolePolicy).to receive(:new).with(role_name: role_name, name: role_policy_name, client: iam_client).and_return(role_policy)
187
+ expect(role_policy).to receive(:put).with(policy_document: role_policy_document)
188
+
189
+ expect(iam).to receive(:create_instance_profile).with(instance_profile_name: instance_profile_name).and_return(instance_profile)
190
+ expect(instance_profile).to receive(:add_role).with(role_name: role_name)
191
+
192
+
193
+ mist_aws.create_iam_role(role_name, role_policy_name, role_policy_document, instance_profile_name)
194
+ end
195
+
196
+ end
197
+
198
+ describe '#delete_iam_role', :run_global_before do
199
+ it 'Does nothing if there is no role' do
200
+ expect(mist_aws.logger).to receive(:warn).with(/No role/)
201
+ expect(iam_client).to receive(:get_role).with(role_name: role_name).and_raise(Aws::IAM::Errors::NoSuchEntity.new(context, 'foo'))
202
+
203
+ expect(mist_aws.delete_iam_role(role_name, role_policy_name, instance_profile_name)).to be_falsy
204
+ end
205
+
206
+ it 'Existing role, policy and instance_profile' do
207
+ expect(iam_client).to receive(:get_role).with(role_name: role_name).and_return(role)
208
+ expect(iam).to receive(:role).with(role_name).and_return(role)
209
+
210
+ # Get all the instance_profiles associated with the role
211
+ expect(role).to receive(:instance_profiles).and_return([instance_profile])
212
+
213
+ # Removes the role from the instance_profile
214
+ expect(instance_profile).to receive(:remove_role).with(role_name: role_name)
215
+ # Delete the instance_profile
216
+ expect(instance_profile).to receive(:delete)
217
+
218
+ # Get all role_policies associated with the role
219
+ expect(role).to receive(:policies).and_return([role_policy])
220
+
221
+ # Deletes the role_policy
222
+ expect(role_policy).to receive(:delete)
223
+
224
+ # Deletes the role
225
+ expect(role).to receive(:delete)
226
+
227
+ expect(mist_aws.delete_iam_role(role_name, role_policy_name, instance_profile_name)).to be_truthy
228
+ end
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,71 @@
1
+ {
2
+ "Version": "2012-10-17",
3
+ "Statement": [
4
+ {
5
+ "Action": [
6
+ "appstream:Get*",
7
+ "autoscaling:Describe*",
8
+ "cloudformation:DescribeStacks",
9
+ "cloudformation:DescribeStackEvents",
10
+ "cloudformation:DescribeStackResource",
11
+ "cloudformation:DescribeStackResources",
12
+ "cloudformation:GetTemplate",
13
+ "cloudformation:List*",
14
+ "cloudfront:Get*",
15
+ "cloudfront:List*",
16
+ "cloudtrail:DescribeTrails",
17
+ "cloudtrail:GetTrailStatus",
18
+ "cloudwatch:Describe*",
19
+ "cloudwatch:Get*",
20
+ "cloudwatch:List*",
21
+ "directconnect:Describe*",
22
+ "dynamodb:GetItem",
23
+ "dynamodb:BatchGetItem",
24
+ "dynamodb:Query",
25
+ "dynamodb:Scan",
26
+ "dynamodb:DescribeTable",
27
+ "dynamodb:ListTables",
28
+ "ec2:Describe*",
29
+ "elasticache:Describe*",
30
+ "elasticbeanstalk:Check*",
31
+ "elasticbeanstalk:Describe*",
32
+ "elasticbeanstalk:List*",
33
+ "elasticbeanstalk:RequestEnvironmentInfo",
34
+ "elasticbeanstalk:RetrieveEnvironmentInfo",
35
+ "elasticloadbalancing:Describe*",
36
+ "elastictranscoder:Read*",
37
+ "elastictranscoder:List*",
38
+ "iam:List*",
39
+ "iam:Get*",
40
+ "kinesis:Describe*",
41
+ "kinesis:Get*",
42
+ "kinesis:List*",
43
+ "opsworks:Describe*",
44
+ "opsworks:Get*",
45
+ "route53:Get*",
46
+ "route53:List*",
47
+ "redshift:Describe*",
48
+ "redshift:ViewQueriesInConsole",
49
+ "rds:Describe*",
50
+ "rds:ListTagsForResource",
51
+ "s3:Get*",
52
+ "s3:List*",
53
+ "sdb:GetAttributes",
54
+ "sdb:List*",
55
+ "sdb:Select*",
56
+ "ses:Get*",
57
+ "ses:List*",
58
+ "sns:Get*",
59
+ "sns:List*",
60
+ "sqs:GetQueueAttributes",
61
+ "sqs:ListQueues",
62
+ "sqs:ReceiveMessage",
63
+ "storagegateway:List*",
64
+ "storagegateway:Describe*",
65
+ "trustedadvisor:Describe*"
66
+ ],
67
+ "Effect": "Allow",
68
+ "Resource": "*"
69
+ }
70
+ ]
71
+ }
@@ -0,0 +1,10 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'mist_aws'
3
+
4
+ ENV['UNDER_RSPEC_TEST']="true"
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :rspec do |mocks|
8
+ mocks.verify_partial_doubles = true
9
+ end
10
+ end
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mist_aws
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Robert J. Berger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.1.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.1.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: aws-sdk
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 2.0.1.pre
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 2.0.1.pre
97
+ - !ruby/object:Gem::Dependency
98
+ name: json
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: inifile
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Wrapper around aws-sdk for higher level use. So far only supports IAM
126
+ Role create/delete
127
+ email:
128
+ - rberger@mistsys.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".gitignore"
134
+ - ".rspec"
135
+ - ".travis.yml"
136
+ - Gemfile
137
+ - LICENSE.txt
138
+ - README.md
139
+ - Rakefile
140
+ - lib/mist_aws.rb
141
+ - lib/mist_aws/iam.rb
142
+ - lib/mist_aws/version.rb
143
+ - mist_aws.gemspec
144
+ - spec/mist_aws_live_spec.rb
145
+ - spec/mist_aws_spec.rb
146
+ - spec/policy_document.txt
147
+ - spec/spec_helper.rb
148
+ homepage: https://github.com/mistsys/mist_aws
149
+ licenses:
150
+ - MIT
151
+ metadata: {}
152
+ post_install_message:
153
+ rdoc_options: []
154
+ require_paths:
155
+ - lib
156
+ required_ruby_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ required_rubygems_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ requirements: []
167
+ rubyforge_project:
168
+ rubygems_version: 2.2.2
169
+ signing_key:
170
+ specification_version: 4
171
+ summary: Wrapper around aws-sdk for higher level use
172
+ test_files:
173
+ - spec/mist_aws_live_spec.rb
174
+ - spec/mist_aws_spec.rb
175
+ - spec/policy_document.txt
176
+ - spec/spec_helper.rb
177
+ has_rdoc: