aws_account_utils 0.1.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.
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -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 'aws_account_utils/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "aws_account_utils"
8
+ spec.version = AwsAccountUtils::VERSION
9
+ spec.authors = ["keviny22"]
10
+ spec.email = ["kevin_young@intuit.com"]
11
+
12
+ spec.summary = %q{A set of helper methods for configuring aspects of AWS that do not have an API.}
13
+ spec.description = %q{A set of helper methods that are webdriven.}
14
+ spec.homepage = "https://github.com/intuit/aws_account_utils"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.9'
22
+ spec.add_development_dependency 'webmock', '~> 1.21', '>= 1.21.0'
23
+ spec.add_development_dependency 'guard-rspec', '~> 4.3', '>= 4.3.1'
24
+ spec.add_development_dependency 'simplecov', '~> 0.8', '>= 0.8.2'
25
+ spec.add_development_dependency 'fakefs', '~> 0.6', '>= 0.6.7'
26
+ spec.add_runtime_dependency 'rake', '~> 10.3.2', '~> 10.0'
27
+ spec.add_runtime_dependency 'watir-webdriver', '~> 0.8', '>= 0.8.0'
28
+ spec.add_runtime_dependency 'random-word', '~> 1.3', '>= 1.3.0'
29
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "aws_account_utils"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,200 @@
1
+ require 'aws_account_utils/base'
2
+ require 'aws_account_utils/version'
3
+ require 'aws_account_utils/account_logger'
4
+ require 'aws_account_utils/watir_browser'
5
+ require 'aws_account_utils/account_registration'
6
+ require 'aws_account_utils/customer_information'
7
+ require 'aws_account_utils/settings'
8
+ require 'aws_account_utils/iam_billing'
9
+ require 'aws_account_utils/email_preferences'
10
+ require 'aws_account_utils/enterprise_support'
11
+ require 'aws_account_utils/consolidated_billing'
12
+ require 'aws_account_utils/root_access_keys'
13
+ require 'aws_account_utils/password'
14
+ require 'aws_account_utils/alternate_contacts'
15
+ require 'aws_account_utils/logout'
16
+
17
+ module AwsAccountUtils
18
+ class AwsAccountUtils
19
+ attr_reader :options, :logger, :browser, :screenshots
20
+
21
+ def initialize(logger: nil, browser: nil, screenshots: nil)
22
+ @browser = browser
23
+ @logger = logger
24
+ @screenshots = screenshots
25
+
26
+ Settings.set_screenshot_dir screenshots if screenshots
27
+ end
28
+
29
+ def create_account(account_name:, account_email:, account_password:, account_details:)
30
+ raise ArgumentError, "account_detials: must be a hash." unless account_details.is_a?(Hash)
31
+ account_registration.signup account_name, account_email, account_password
32
+ resp = customer_information.submit account_email, account_password, account_details
33
+ logger.info 'Successfully created account.' if resp
34
+ resp
35
+ ensure
36
+ browser.close rescue nil
37
+ end
38
+
39
+ def check_enterprise_support(account_email:, account_password:)
40
+ resp = enterprise_support.existing_support? account_email, account_password
41
+ logger.info 'Enterprise support was already enabled' if resp
42
+ resp
43
+ ensure
44
+ browser.close rescue nil
45
+ end
46
+
47
+ def change_root_password(account_email:, account_password:, new_password:)
48
+ resp = password.change(account_email, account_password, new_password)
49
+ logger.info 'Changed root password.' if resp
50
+ resp
51
+ ensure
52
+ browser.close rescue nil
53
+ end
54
+
55
+ def confirm_consolidated_billing(account_email:, account_password:, confirmation_link:)
56
+ resp = consolidated_billing.confirm account_email, account_password, confirmation_link
57
+ logger.info 'Consolidated billing has been confirmed' if resp
58
+ resp
59
+ ensure
60
+ browser.close rescue nil
61
+ end
62
+
63
+ def create_root_access_keys(account_email:, account_password:)
64
+ resp = root_access_keys.create account_email, account_password
65
+ logger.info 'Created root access keys.' if resp
66
+ resp
67
+ ensure
68
+ browser.close rescue nil
69
+ end
70
+
71
+ def delete_root_access_keys(account_email:, account_password:)
72
+ resp = root_access_keys.delete account_email, account_password
73
+ logger.info 'Deleted all root access keys.' if resp
74
+ resp
75
+ ensure
76
+ browser.close rescue nil
77
+ end
78
+
79
+ def email_opt_out(account_email:, account_password:)
80
+ resp = email_preferences.opt_out account_email, account_password
81
+ logger.info 'Successfully opted out of all emails' if resp
82
+ resp
83
+ ensure
84
+ browser.close rescue nil
85
+ end
86
+
87
+ def enable_enterprise_support(account_email:, account_password:)
88
+ resp = enterprise_support.enable account_email, account_password
89
+ logger.info 'Enabled enterprise support' if resp
90
+ resp
91
+ ensure
92
+ browser.close rescue nil
93
+ end
94
+
95
+ def enable_iam_billing(account_email:, account_password:)
96
+ resp = iam_billing.enable account_email, account_password
97
+ logger.info 'Successfully enabled IAM billing' if resp
98
+ resp
99
+ ensure
100
+ browser.close rescue nil
101
+ end
102
+
103
+ def existing_consolidated_billing?(account_email:, account_password:)
104
+ resp = consolidated_billing.existing? account_email, account_password
105
+ logger.info 'Consolidated billing has already been setup' if resp
106
+ resp
107
+ ensure
108
+ browser.close rescue nil
109
+ end
110
+
111
+ def logout_from_console
112
+ resp = logout.execute
113
+ logger.info 'Logged out of console' if resp
114
+ resp
115
+ ensure
116
+ browser.close rescue nil
117
+ end
118
+
119
+ def request_consolidated_billing(master_account_email:, master_account_password:, account_email:)
120
+ resp = consolidated_billing.request master_account_email, master_account_password, account_email
121
+ logger.info 'Consolidated billing has been requested' if resp
122
+ resp
123
+ ensure
124
+ browser.close rescue nil
125
+ end
126
+
127
+ def set_challenge_questions(account_email:, account_password:, answers:)
128
+ raise ArgumentError, "answers: must be a hash." unless answers.is_a?(Hash)
129
+
130
+ resp = challenge_questions.create account_email, account_password, answers
131
+ logger.info 'Security Challenge Questions have been setup' if resp
132
+ resp
133
+ ensure
134
+ browser.close rescue nil
135
+ end
136
+
137
+ def set_alternate_contacts(account_email:, account_password:, contact_info:)
138
+ raise ArgumentError, "contact_info: must be a hash." unless contact_info.is_a?(Hash)
139
+
140
+ resp = alternate_contacts.set account_email, account_password, contact_info
141
+ logger.info 'Set alterante contacts.' if resp
142
+ resp
143
+ ensure
144
+ browser.close rescue nil
145
+ end
146
+
147
+ private
148
+ def account_registration
149
+ @account_registration ||= AccountRegistration.new logger, browser
150
+ end
151
+
152
+ def alternate_contacts
153
+ @alternate_contacts ||= AlternateContacts.new logger, browser
154
+ end
155
+
156
+ def browser
157
+ @browser ||= WatirBrowser.new(logger).create
158
+ end
159
+
160
+ def challenge_questions
161
+ @challenge_questions ||= ChallengeQuestions.new logger, browser
162
+ end
163
+
164
+ def consolidated_billing
165
+ @consolidated_billing ||= ConsolidatedBilling.new logger, browser
166
+ end
167
+
168
+ def customer_information
169
+ @customer_information ||= CustomerInformation.new logger, browser
170
+ end
171
+
172
+ def email_preferences
173
+ @email_preferences ||= EmailPreferences.new logger, browser
174
+ end
175
+
176
+ def enterprise_support
177
+ @enterprise_support ||= EnterpriseSupport.new logger, browser
178
+ end
179
+
180
+ def iam_billing
181
+ @iam_billing ||= IamBilling.new logger, browser
182
+ end
183
+
184
+ def logger
185
+ @logger ||= AccountLogger.new(options[:log_level])
186
+ end
187
+
188
+ def password
189
+ @password ||= Password.new logger, browser
190
+ end
191
+
192
+ def root_access_keys
193
+ @root_access_keys ||= RootAccessKeys.new logger, browser
194
+ end
195
+
196
+ def logout
197
+ @logout ||= Logout.new logger, browser
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,26 @@
1
+ require 'logger'
2
+ require 'forwardable'
3
+
4
+ module AwsAccountUtils
5
+ class AccountLogger
6
+ extend Forwardable
7
+ def_delegators :@logger, :fatal, :debug, :error, :info, :warn, :debug?
8
+
9
+ def initialize(log_level = 'info')
10
+ @log_level = log_level
11
+ @logger = new_logger
12
+ end
13
+
14
+ private
15
+ def new_logger
16
+ STDOUT.sync = true
17
+ Logger.new(STDOUT).tap do |l|
18
+ l.datetime_format = '%Y-%m-%dT%H:%M:%S%z'
19
+ l.formatter = proc do |severity, datetime, progname, msg|
20
+ "#{datetime} #{severity} : #{msg}\n"
21
+ end
22
+ l.level = Logger.const_get @log_level.upcase
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,52 @@
1
+ require 'aws_account_utils/base'
2
+
3
+ module AwsAccountUtils
4
+ class AccountRegistration < Base
5
+ attr_reader :logger, :browser
6
+
7
+ def initialize(logger, browser)
8
+ @logger = logger
9
+ @browser = browser
10
+ end
11
+
12
+ def signup(account_name, account_email, account_password)
13
+ logger.debug "Signing up for a new account."
14
+ login_details = { 'ap_customer_name' => account_name,
15
+ 'ap_email' => account_email,
16
+ 'ap_email_check' => account_email,
17
+ 'ap_password' => account_password,
18
+ 'ap_password_check' => account_password }
19
+
20
+ browser.goto signup_url
21
+ browser.text_field(:id => 'ap_customer_name').wait_until_present
22
+ screenshot(browser, "1")
23
+ login_details.each do |k,v|
24
+ browser.text_field(:id => k).when_present.set v
25
+ end
26
+ screenshot(browser, "2")
27
+ browser.button(:id => 'continue-input').when_present.click
28
+ raise StandardError if browser.div(:id => /message_(error|warning)/).exist?
29
+ true
30
+ rescue StandardError
31
+ screenshot(browser, "error")
32
+ error_header = browser.div(:id => /message_(error|warning)/).h6.text
33
+ error_body = browser.div(:id => /message_(error|warning)/).p.text
34
+ raise StandardError, "AWS signup error: \"#{error_header}: #{error_body}\""
35
+
36
+ rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e
37
+ screenshot(browser, "error")
38
+ raise StandardError, "#{self.class.name} - #{e}"
39
+ end
40
+
41
+ private
42
+ def signup_url
43
+ url = "https://www.amazon.com/ap/register?"
44
+ url << "&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select"
45
+ url << "&create=1&openid.assoc_handle=aws&accountStatusPolicy=P1"
46
+ url << "&openid.ns=http://specs.openid.net/auth/2.0"
47
+ url << "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select"
48
+ url << "&openid.mode=checkid_setup"
49
+ url << "&openid.return_to=https://console.aws.amazon.com/billing/signup"
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,42 @@
1
+ require 'aws_account_utils/base'
2
+
3
+ module AwsAccountUtils
4
+ class AlternateContacts < Base
5
+ attr_reader :logger, :browser
6
+
7
+ def initialize(logger, browser)
8
+ @logger = logger
9
+ @browser = browser
10
+ end
11
+
12
+ def set(account_email, account_password, contact_info = {})
13
+ logger.debug "Setting alternate account contacts."
14
+ Login.new(logger, browser).execute url,
15
+ account_email,
16
+ account_password
17
+ browser.a(:xpath => '//a[@ng-click="toggleEditingAlternateContactsInfoState()"]').when_present.click
18
+ form_inputs(contact_info)
19
+ screenshot(browser, "1")
20
+ browser.button(:xpath => '//button[@ng-click="updateAlternateContacts()"]').when_present.click
21
+ browser.div(:xpath => '//div[@ng-show="options.status == \'success\'"]').wait_until_present
22
+ true
23
+ rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e
24
+ screenshot(browser, "error")
25
+ raise StandardError, "#{self.class.name} - #{e}"
26
+ end
27
+
28
+ private
29
+ def form_inputs(requestor_info)
30
+ requestor_info.each do |type, details|
31
+ details.each do |key, value|
32
+ browser.input(:xpath => "//input[@ng-model=\"alternateContacts.#{type}Contact.#{key}\"]").to_subtype.when_present.set value
33
+ end
34
+ end
35
+ end
36
+
37
+ def url
38
+ 'https://console.aws.amazon.com/billing/home?#/account'
39
+ end
40
+
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module AwsAccountUtils
2
+ class Base
3
+
4
+ def screenshot(browser, file)
5
+ return unless Settings.screenshot_dir
6
+ calling_method = /(?<=`)(.*)(?=')/.match(caller.first).to_s.gsub(" ",'-')
7
+ calling_class = self.class.to_s.gsub("::",'_')
8
+ browser.screenshot.save screenshot_file(file, calling_class, calling_method)
9
+ end
10
+
11
+ private
12
+ def increment(path)
13
+ _, filename, count, extension = *path.match(/(\A.*?)(?:_#(\d+))?(\.[^.]*)?\Z/)
14
+ count = (count || '0').to_i + 1
15
+ "#{filename}_##{count}#{extension}"
16
+ end
17
+
18
+ def screenshot_file(file, calling_class, calling_method)
19
+ file_path = File.join Settings.screenshot_dir, "#{calling_class}_#{calling_method}_#{file}_#1.png"
20
+ File.exists?(file_path) ? increment(file_path) : file_path
21
+ end
22
+
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,49 @@
1
+ require 'aws_account_utils/base'
2
+ require 'random-word'
3
+
4
+ module AwsAccountUtils
5
+ class ChallengeQuestions < Base
6
+ attr_reader :logger, :browser
7
+
8
+ def initialize(logger, browser)
9
+ @logger = logger
10
+ @browser = browser
11
+ end
12
+
13
+ def create(account_email, account_password, challenge_words = {})
14
+ logger.debug "Entering customer details."
15
+ Login.new(logger, browser).execute url,
16
+ account_email,
17
+ account_password
18
+
19
+ browser.a(:xpath => '//a[@ng-click="toggleEditingSecurityQuestionsInfoState()"]').when_present.click
20
+
21
+ challenge_words.each do |num, word|
22
+ browser.input(:xpath => "//input[@ng-model=\"selectedSecurityQuestions.question#{num}.answer\"]").to_subtype.when_present.set word
23
+ end
24
+
25
+ screenshot(browser, "1")
26
+ browser.button(:xpath => '//button[@ng-click="updateSecurityQuestions()"]').when_present.click
27
+ browser.a(:xpath => '//a[@ng-click="toggleEditingSecurityQuestionsInfoState()"]').wait_until_present
28
+ challenge_words
29
+ rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e
30
+ screenshot(browser, "error")
31
+ raise StandardError, "#{self.class.name} - #{e}"
32
+ end
33
+
34
+ private
35
+ def challenge_words
36
+ RandomWord.exclude_list << (/_/) if RandomWord.exclude_list.none?
37
+
38
+ @challenge_words ||= (1..3).inject({}) do |hash, num|
39
+ hash[num] = RandomWord.nouns.next
40
+ hash
41
+ end
42
+ end
43
+
44
+ def url
45
+ 'https://portal.aws.amazon.com/gp/aws/manageYourAccount'
46
+ end
47
+
48
+ end
49
+ end