├── .coveralls.yml ├── .gitignore ├── .ruby-gemset ├── .ruby-version ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── aws_account_utils.gemspec ├── bin ├── console └── setup ├── lib ├── aws_account_utils.rb └── aws_account_utils │ ├── account.rb │ ├── account_logger.rb │ ├── account_registration.rb │ ├── alternate_contacts.rb │ ├── base.rb │ ├── challenge_questions.rb │ ├── company_name.rb │ ├── consolidated_billing.rb │ ├── customer_information.rb │ ├── customize_url.rb │ ├── email_preferences.rb │ ├── enterprise_support.rb │ ├── iam_billing.rb │ ├── login.rb │ ├── logout.rb │ ├── password.rb │ ├── root_access_keys.rb │ ├── settings.rb │ ├── version.rb │ └── watir_browser.rb └── spec ├── aws_account_utils ├── account_registration_spec.rb ├── account_spec.rb ├── alternate_contacts_spec.rb ├── challenge_questions_spec.rb ├── company_name_spec.rb ├── consolidated_billing_spec.rb ├── customer_information_spec.rb ├── customize_url_spec.rb ├── email_preferences_spec.rb ├── enterprise_support_spec.rb ├── iam_billing_spec.rb ├── login_spec.rb ├── logout_spec.rb ├── password_spec.rb ├── root_access_keys_spec.rb └── watir_browser_spec.rb └── spec_helper.rb /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-ci -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /Gemfile.lock 4 | /_yardoc/ 5 | /coverage/ 6 | /doc/ 7 | /pkg/ 8 | /spec/reports/ 9 | /tmp/ 10 | *.gem 11 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | aws_account_utils 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.2.3 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## v0.1.5 - Fixed close_account for Angular animation change, added waitr ng_class support, bumped waiter gem version 2 | - Fixed challenge_questions generating random word when not supplied 3 | 4 | ## v0.1.3 5 | 6 | * Added close account method 7 | 8 | ## v0.1.0 9 | 10 | * First release -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 4 | 5 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion. 6 | 7 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 8 | 9 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 10 | 11 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 12 | 13 | This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) 14 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in aws_account_utils.gemspec 4 | gemspec 5 | 6 | group :test do 7 | gem 'rspec' 8 | gem 'simplecov', require: false 9 | gem 'coveralls', require: false 10 | end 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Intuit Inc 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | 3 | **This project has been deprecated.** 4 | 5 | We recommend you look at [AWS Organizations](http://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_create.html) as a means to automate AWS account creation. 6 | 7 | --- 8 | 9 | [![Build Status](https://travis-ci.org/intuit/aws_account_utils.svg?branch=feature_delete_account)](https://travis-ci.org/intuit/aws_account_utils) 10 | [![Coverage Status](https://coveralls.io/repos/intuit/aws_account_utils/badge.svg?branch=feature_delete_account&service=github)](https://coveralls.io/github/intuit/aws_account_utils) 11 | [![Gem Version](https://badge.fury.io/rb/aws_account_utils.svg)](https://badge.fury.io/rb/aws_account_utils) 12 | [![Code Climate](https://codeclimate.com/github/intuit/aws_account_utils.png)](https://codeclimate.com/github/intuit/aws_account_utils) 13 | 14 | # AwsAccountUtils 15 | 16 | A collection of helpers for creating and modifying AWS account details that can not be done using any existing AWS API 17 | 18 | Special Note: the `create_account` operation requires that your IP be white-listed by AWS in order to bypass the CAPTCHA 19 | 20 | ## Installation 21 | 22 | NOTE: Ruby 2.2 is required! 23 | 24 | Add this line to your application's Gemfile: 25 | 26 | ```ruby 27 | gem 'aws_account_utils' 28 | ``` 29 | 30 | And then execute: 31 | 32 | $ bundle 33 | 34 | Or install it yourself as: 35 | 36 | $ gem install aws_account_utils 37 | 38 | ## Usage 39 | 40 | Overview 41 | ================= 42 | 43 | If you are required to go through a proxy, the following should be set prior to execution. 44 | ``` 45 | export AWS_ACCOUNT_UTILS_HTTP_PROXY=myproxyhots.com 46 | export AWS_ACCOUNT_UTILS_HTTP_PROXY_PORT=80 47 | ``` 48 | 49 | ```ruby 50 | aws_utils = AwsAccountUtils::AwsAccountUtils.new( 51 | browser: (Watir::Browser) - default: Watir Browser object - You can pass in your own Browser object or use the built-in which uses firefox. 52 | logger: (Logger) - default: Logger object. - You can pass in your own logger or use the built in. 53 | log_level: (Symbol) - default: :info - Sets the logger level. Only :info and :debug are useful 54 | screenshots: (String) - default: nil - Enables screenshots by passing the directory to put the screenshots which are taken throughout the different operations. 55 | ) 56 | ``` 57 | 58 | Operations 59 | ================= 60 | * [create_account](#create_account) 61 | * [change_root_password](#change_root_password) 62 | * [check_enterprise_support](#check_enterprise_support) 63 | * [close_account](#close_account) 64 | * [confirm_consolidated_billing](#confirm_consolidated_billing) 65 | * [create_root_access_keys](#create_root_access_keys) 66 | * [delete_root_access_keys](#delete_root_access_keys) 67 | * [email_opt_out](#email_opt_out) 68 | * [enable_enterprise_support](#enable_enterprise_support) 69 | * [enable_iam_billing](#enable_iam_billing) 70 | * [logout_from_console](#logout_from_console) 71 | * [request_consolidated_billing](#request_consolidated_billing) 72 | * [set_alternate_contacts](#set_alternate_contacts) 73 | * [set_challenge_questions](#set_challenge_questions) 74 | * [set_company_name](#set_company_name) 75 | 76 | create_account 77 | ------------ 78 | 79 | > Creates a new AWS Account and with the minimal amount of information and 80 | > returns the account number of the new account. 81 | > Requires that your IP be white-listed by AWS in order to bypass the CAPTCHA 82 | 83 | `#create_account(account_name:, account_email, account_password:, account_details:)` 84 | 85 | **Examples:** 86 | ```Ruby 87 | details = { 'fullName' => 'Herman Munster', 88 | 'company' => 'The Munsters', 89 | 'addressLine1' => '1313 Mockingbird Lane', 90 | 'city' => 'Mockingbird Heights', 91 | 'state' => 'CA', 92 | 'postalCode' => '92000', 93 | 'phoneNumber' => '(800) 555-1212', 94 | 'guess' => 'Test Account' } 95 | 96 | resp = aws_utils.create_account(account_name: 'My Test Account 01', 97 | account_email: 'adfefef@gmail.com', 98 | account_password: 'foobar1212121', 99 | account_details: details) 100 | resp #=> String 101 | ``` 102 | 103 | **Parameters:** 104 | ``` 105 | account_name: (required, String) - The account name to associate with this new account 106 | account_email: (required, String) - The email to associate with this new account 107 | account_password: (required, String) - The password to use with this new account 108 | account_details: (required, Hash) - Hash of account details 109 | ``` 110 | 111 | **Returns:** 112 | 113 | `1234-1223-1242 #Accont Number => String` 114 | 115 | change_root_password 116 | ------------ 117 | 118 | > Changes the account password 119 | 120 | `change_root_password(account_email:, account_password:, new_password:)` 121 | 122 | **Examples:** 123 | ```Ruby 124 | resp = aws_utils.change_root_password(account_email: 'adfefef@gmail.com', 125 | account_password: 'foobar1212121', 126 | new_password: 'mynewpassword') 127 | resp #=> true/false 128 | ``` 129 | 130 | **Parameters:** 131 | ``` 132 | account_email: (required, String) - The email to associate with this new account 133 | account_password: (required, String) - The old password to use with this new account 134 | new_password: (required, String) - The new password to use with this new account 135 | ``` 136 | 137 | **Returns:** 138 | 139 | `#return => Boolean` 140 | 141 | --- 142 | 143 | check_enterprise_support 144 | ------------ 145 | 146 | > Checks if enterprise support is enabled 147 | 148 | `check_enterprise_support(account_email:, account_password:)` 149 | 150 | **Examples:** 151 | ```Ruby 152 | resp = aws_utils.check_enterprise_support(account_email: 'adfefef@gmail.com', 153 | account_password: 'foobar1212121'') 154 | resp #=> true/false 155 | ``` 156 | 157 | **Parameters:** 158 | ``` 159 | account_email: (required, String) - The email to associate with this new account 160 | account_password: (required, String) - The password to use with this new account 161 | ``` 162 | 163 | **Returns:** 164 | 165 | `#return => Boolean` 166 | 167 | --- 168 | 169 | close_account 170 | ------------ 171 | 172 | > Closes AWS Account 173 | 174 | `close_account(account_email:, account_password:)` 175 | 176 | **Examples:** 177 | ```Ruby 178 | resp = aws_utils.close_account(account_email: 'adfefef@gmail.com', 179 | account_password: 'foobar1212121'') 180 | resp #=> true/false 181 | ``` 182 | 183 | **Parameters:** 184 | ``` 185 | account_email: (required, String) - The email to associate with this new account 186 | account_password: (required, String) - The password to use with this new account 187 | ``` 188 | 189 | **Returns:** 190 | 191 | `#return => Boolean` 192 | 193 | --- 194 | 195 | confirm_consolidated_billing 196 | ------------ 197 | 198 | > Confirms consolidated billing by taking the link that was emailed to you when you enabled consolidated billing. 199 | 200 | `confirm_consolidated_billing(account_email:, account_password:, confirmation_link:)` 201 | 202 | **Examples:** 203 | ```Ruby 204 | resp = aws_utils.confirm_consolidated_billing(account_email: 'adfefef@gmail.com', 205 | account_password: 'foobar1212121', 206 | confirmation_link: 'amazonaws.com/confirmationlink') 207 | resp #=> nil 208 | ``` 209 | 210 | **Parameters:** 211 | ``` 212 | account_email: (required, String) - The email to associate with this new account 213 | account_password: (required, String) - The password to use with this new account 214 | confirmation_link: (required, String) - The unique url that will confirm billing 215 | 216 | ``` 217 | 218 | **Returns:** 219 | 220 | `#return => nil` 221 | 222 | --- 223 | 224 | create_root_access_keys 225 | ------------ 226 | 227 | > Creates access and secret key for root account 228 | 229 | `create_root_access_keys(account_email:, account_password:)` 230 | 231 | **Examples:** 232 | ```Ruby 233 | resp = aws_utils.create_root_access_keys(account_email: 'adfefef@gmail.com', 234 | account_password: 'foobar1212121) 235 | resp #=> Hash 236 | ``` 237 | 238 | **Parameters:** 239 | ``` 240 | account_email: (required, String) - The email to associate with this new account 241 | account_password: (required, String) - The password to use with this new account 242 | ``` 243 | 244 | **Returns:** 245 | 246 | `#return => Hash {:access_key=>"my_access_key", :secret_key=>"my_secret_key"}` 247 | 248 | --- 249 | 250 | delete_root_access_keys 251 | ------------ 252 | 253 | > Deletes ALL root access/secret keys from the root of the account 254 | 255 | `delete_root_access_keys(account_email:, account_password:)` 256 | 257 | **Examples:** 258 | ```Ruby 259 | resp = aws_utils.delete_root_access_keys(account_email: 'adfefef@gmail.com', 260 | account_password: 'foobar1212121) 261 | resp #=> True/False 262 | ``` 263 | 264 | **Parameters:** 265 | ``` 266 | account_email: (required, String) - The email to associate with this new account 267 | account_password: (required, String) - The password to use with this new account 268 | ``` 269 | 270 | **Returns:** 271 | 272 | `#return => true/false` 273 | 274 | --- 275 | 276 | email_opt_out 277 | ------------ 278 | 279 | > Opts account out of all email marketing 280 | 281 | `email_opt_out(account_email:, account_password:)` 282 | 283 | **Examples:** 284 | ```Ruby 285 | resp = aws_utils.email_opt_out(account_email: 'adfefef@gmail.com', 286 | account_password: 'foobar1212121) 287 | resp #=> True/False 288 | ``` 289 | 290 | **Parameters:** 291 | ``` 292 | account_email: (required, String) - The email to associate with this new account 293 | account_password: (required, String) - The password to use with this new account 294 | ``` 295 | 296 | **Returns:** 297 | 298 | `#return => Boolean` 299 | 300 | --- 301 | 302 | enable_enterprise_support 303 | ------------ 304 | 305 | > Enables enterprise support, this should be done after consolidated billing has been setup 306 | 307 | `enable_enterprise_support(account_email:, account_password:)` 308 | 309 | **Examples:** 310 | ```Ruby 311 | resp = aws_utils.enable_enterprise_support(account_email: 'adfefef@gmail.com', 312 | account_password: 'foobar1212121) 313 | resp #=> True/False 314 | ``` 315 | 316 | **Parameters:** 317 | ``` 318 | account_email: (required, String) - The email to associate with this new account 319 | account_password: (required, String) - The password to use with this new account 320 | ``` 321 | 322 | **Returns:** 323 | 324 | `#return => Boolean` 325 | 326 | --- 327 | 328 | enable_iam_billing 329 | ------------ 330 | 331 | > Sets the account to enable IAM billing 332 | 333 | `enable_iam_billing(account_email:, account_password:)` 334 | **Examples:** 335 | ```Ruby 336 | resp = aws_utils.enable_iam_billing(account_email: 'adfefef@gmail.com', 337 | account_password: 'foobar1212121) 338 | resp #=> True/False 339 | ``` 340 | 341 | **Parameters:** 342 | ``` 343 | account_email: (required, String) - The email to associate with this new account 344 | account_password: (required, String) - The password to use with this new account 345 | ``` 346 | 347 | **Returns:** 348 | 349 | `#return => Boolean` 350 | 351 | --- 352 | 353 | existing_consolidated_billing 354 | ------------ 355 | 356 | > Checks to see if consolidated billing has been setup 357 | 358 | `existing_consolidated_billing?(account_email:, account_password:)` 359 | 360 | **Examples:** 361 | ```Ruby 362 | resp = aws_utils.existing_consolidated_billing?(account_email: 'adfefef@gmail.com', 363 | account_password: 'foobar1212121) 364 | resp #=> True/False 365 | ``` 366 | 367 | **Parameters:** 368 | ``` 369 | account_email: (required, String) - The email to associate with this new account 370 | account_password: (required, String) - The password to use with this new account 371 | ``` 372 | 373 | **Returns:** 374 | 375 | `#return => Boolean` 376 | 377 | --- 378 | 379 | logout_from_console 380 | ------------ 381 | 382 | > Logs out of the console 383 | 384 | `logout_from_console` 385 | 386 | **Examples:** 387 | ```Ruby 388 | resp = aws_utils.logout_from_console 389 | resp #=> True/False 390 | ``` 391 | 392 | **Parameters:** 393 | ``` 394 | ``` 395 | 396 | **Returns:** 397 | 398 | `#return => Boolean` 399 | 400 | --- 401 | 402 | request_consolidated_billing 403 | ------------ 404 | 405 | > Requests consolidated billing to be setup with your master account. An email is sent to the 406 | > account being added with a link. That link should be passed into `confirm_consolidated_billing` 407 | 408 | `request_consolidated_billing(master_account_email:, master_account_password:, account_email:)` 409 | 410 | **Examples:** 411 | ```Ruby 412 | resp = aws_utils.request_consolidated_billing(master_account_email: 'my_master_acccount@gmail.com', 413 | master_account_password: 'master_acct_password, 414 | account_email: 'my_new_account_email@gmail.com') 415 | resp #=> True/False 416 | ``` 417 | 418 | **Parameters:** 419 | ``` 420 | master_account_email: (required, String) - The email for your master billing aws account 421 | master_account_password: (required, String) - The password for your master billing aws account 422 | account_email: (required, String) - The email for the account you want to add to consolidated billing under the master account 423 | ``` 424 | 425 | **Returns:** 426 | 427 | `#return => Boolean` 428 | 429 | --- 430 | 431 | set_alternate_contacts 432 | ------------ 433 | 434 | > Sets alternate contacts for the account 435 | 436 | `set_alternate_contacts(account_email:, account_password:, contact_info:)` 437 | 438 | **Examples:** 439 | ```Ruby 440 | 441 | contacts = {'operations' => {'name' => 'Operations Name', 442 | 'title' => 'Operations Title', 443 | 'email' => 'operations@test.com', 444 | 'phoneNumber' => '888-888-1212'}, 445 | 'security' => {'name' => 'Security Name', 446 | 'title' => 'Security Title', 447 | 'email' => 'Security@test.com', 448 | 'phoneNumber' => '888-888-1212'}} 449 | 450 | resp = aws_utils.set_alternate_contacts(account_email: 'adfefef@gmail.com', 451 | account_password: 'foobar1212121, 452 | contact_info: contacts) 453 | resp #=> True/False 454 | ``` 455 | 456 | **Parameters:** 457 | ``` 458 | account_email: (required, String) - The email to associate with this new account 459 | account_password: (required, String) - The password to use with this new account 460 | contact_info: (required, Hash) - A Hash of Hash of contacts, operations, security, etc. 461 | 462 | ``` 463 | 464 | **Returns:** 465 | 466 | `#return => Boolean` 467 | 468 | --- 469 | 470 | set_challenge_questions 471 | ------------ 472 | 473 | > Sets the accounts challenge security questions 474 | 475 | `set_challenge_questions(account_email:, account_password:, answers:)` 476 | 477 | **Examples:** 478 | ```Ruby 479 | my_answers = {1 => 'answer1', 480 | 2 => 'answer2', 481 | 3 => 'answer3'} 482 | 483 | resp = aws_utils.set_challenge_questions(account_email: 'adfefef@gmail.com', 484 | account_password: 'foobar1212121, 485 | answers: my_answers) 486 | 487 | resp #=> {1 => 'answer1', 2 => 'answer2', 3 => 'answer3'} 488 | ``` 489 | 490 | **Parameters:** 491 | ``` 492 | account_email: (required, String) - The email to associate with this new account 493 | account_password: (required, String) - The password to use with this new account 494 | answers: (optional, Hash) - A hash of answers to fill in for the security questions. If you dont pass your own, Random word will generate for you. 495 | 496 | ``` 497 | 498 | **Returns:** 499 | 500 | `#return => Hash` 501 | 502 | --- 503 | 504 | set_company_name 505 | ------------ 506 | 507 | > Sets company name for the account (any time after account is created) 508 | 509 | `set_company_name(account_email:, account_password:, company_name:)` 510 | 511 | **Examples:** 512 | ```Ruby 513 | 514 | resp = aws_utils.set_alternate_contacts(account_email: 'adfefef@gmail.com', 515 | account_password: 'foobar1212121, 516 | name: 'The Munsters, Inc.') 517 | resp #=> True/False 518 | ``` 519 | 520 | **Parameters:** 521 | ``` 522 | account_email: (required, String) - The email address to use with this account 523 | account_password: (required, String) - The password to use with this account 524 | contact_info: (required, String) - The company name to add to this account 525 | 526 | ``` 527 | 528 | **Returns:** 529 | 530 | `#return => Boolean` 531 | 532 | --- 533 | 534 | ## Development 535 | 536 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment. 537 | 538 | To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). 539 | 540 | ## Contributing 541 | 542 | 1. Fork it ( https://github.com/[my-github-username]/aws_account_utils/fork ) 543 | 2. Create your feature branch (`git checkout -b my-new-feature`) 544 | 3. Commit your changes (`git commit -am 'Add some feature'`) 545 | 4. Push to the branch (`git push origin my-new-feature`) 546 | 5. Create a new Pull Request 547 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rspec/core/rake_task' 2 | task :default => :spec 3 | RSpec::Core::RakeTask.new 4 | 5 | -------------------------------------------------------------------------------- /aws_account_utils.gemspec: -------------------------------------------------------------------------------- 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.required_ruby_version = '~> 2.2' 22 | 23 | spec.add_development_dependency 'bundler', '>= 1.6.5' 24 | spec.add_development_dependency 'webmock', '~> 1.21', '>= 1.21.0' 25 | spec.add_development_dependency 'guard-rspec', '~> 4.3', '>= 4.3.1' 26 | spec.add_development_dependency 'simplecov', '~> 0.8', '>= 0.8.2' 27 | spec.add_development_dependency 'fakefs', '~> 0.6', '>= 0.6.7' 28 | spec.add_runtime_dependency 'rake', '~> 10.3.2', '~> 10.0' 29 | spec.add_runtime_dependency 'watir-webdriver', '~> 0.9', '>= 0.9.1' 30 | spec.add_runtime_dependency 'random-word', '~> 1.3', '>= 1.3.0' 31 | end 32 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 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 15 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 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 8 | -------------------------------------------------------------------------------- /lib/aws_account_utils.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/account' 2 | require 'aws_account_utils/base' 3 | require 'aws_account_utils/version' 4 | require 'aws_account_utils/account_logger' 5 | require 'aws_account_utils/watir_browser' 6 | require 'aws_account_utils/account_registration' 7 | require 'aws_account_utils/customer_information' 8 | require 'aws_account_utils/challenge_questions' 9 | require 'aws_account_utils/settings' 10 | require 'aws_account_utils/iam_billing' 11 | require 'aws_account_utils/email_preferences' 12 | require 'aws_account_utils/enterprise_support' 13 | require 'aws_account_utils/consolidated_billing' 14 | require 'aws_account_utils/root_access_keys' 15 | require 'aws_account_utils/password' 16 | require 'aws_account_utils/alternate_contacts' 17 | require 'aws_account_utils/company_name' 18 | require 'aws_account_utils/logout' 19 | 20 | module AwsAccountUtils 21 | class AwsAccountUtils 22 | attr_reader :log_level, :logger, :browser, :screenshots 23 | 24 | def initialize(log_level: :info, logger: nil, browser: nil, screenshots: nil) 25 | @log_level = log_level 26 | @logger = logger 27 | @browser = browser 28 | @screenshots = screenshots 29 | 30 | Settings.set_screenshot_dir screenshots if screenshots 31 | end 32 | 33 | def create_account(account_name:, account_email:, account_password:, account_details:) 34 | raise ArgumentError, "account_detials: must be a hash." unless account_details.is_a?(Hash) 35 | account_registration.signup account_name, account_email, account_password 36 | resp = customer_information.submit account_email, account_password, account_details 37 | logger.info 'Successfully created account.' if resp 38 | resp 39 | ensure 40 | browser.close rescue nil 41 | end 42 | 43 | def check_enterprise_support(account_email:, account_password:) 44 | resp = enterprise_support.existing_support? account_email, account_password 45 | logger.info 'Enterprise support was already enabled' if resp 46 | resp 47 | ensure 48 | browser.close rescue nil 49 | end 50 | 51 | def change_root_password(account_email:, account_password:, new_password:) 52 | resp = password.change(account_email, account_password, new_password) 53 | logger.info 'Changed root password.' if resp 54 | resp 55 | ensure 56 | browser.close rescue nil 57 | end 58 | 59 | def close_account(account_email:, account_password:) 60 | resp = account.close(account_email, account_password) 61 | logger.info 'Closed Account.' if resp 62 | resp 63 | ensure 64 | browser.close rescue nil 65 | end 66 | 67 | def confirm_consolidated_billing(account_email:, account_password:, confirmation_link:) 68 | resp = consolidated_billing.confirm account_email, account_password, confirmation_link 69 | logger.info 'Consolidated billing has been confirmed' if resp 70 | resp 71 | ensure 72 | browser.close rescue nil 73 | end 74 | 75 | def create_root_access_keys(account_email:, account_password:) 76 | resp = root_access_keys.create account_email, account_password 77 | logger.info 'Created root access keys.' if resp 78 | resp 79 | ensure 80 | browser.close rescue nil 81 | end 82 | 83 | def delete_root_access_keys(account_email:, account_password:) 84 | resp = root_access_keys.delete account_email, account_password 85 | logger.info 'Deleted all root access keys.' if resp 86 | resp 87 | ensure 88 | browser.close rescue nil 89 | end 90 | 91 | def email_opt_out(account_email:, account_password:) 92 | resp = email_preferences.opt_out account_email, account_password 93 | logger.info 'Successfully opted out of all emails' if resp 94 | resp 95 | ensure 96 | browser.close rescue nil 97 | end 98 | 99 | def enable_enterprise_support(account_email:, account_password:) 100 | resp = enterprise_support.enable account_email, account_password 101 | logger.info 'Enabled enterprise support' if resp 102 | resp 103 | ensure 104 | browser.close rescue nil 105 | end 106 | 107 | def enable_iam_billing(account_email:, account_password:) 108 | resp = iam_billing.enable account_email, account_password 109 | logger.info 'Successfully enabled IAM billing' if resp 110 | resp 111 | ensure 112 | browser.close rescue nil 113 | end 114 | 115 | def existing_consolidated_billing?(account_email:, account_password:) 116 | resp = consolidated_billing.existing? account_email, account_password 117 | logger.info 'Consolidated billing has already been setup' if resp 118 | resp 119 | ensure 120 | browser.close rescue nil 121 | end 122 | 123 | def logout_from_console 124 | resp = logout.execute 125 | logger.info 'Logged out of console' if resp 126 | resp 127 | ensure 128 | browser.close rescue nil 129 | end 130 | 131 | def request_consolidated_billing(master_account_email:, master_account_password:, account_email:) 132 | resp = consolidated_billing.request master_account_email, master_account_password, account_email 133 | logger.info 'Consolidated billing has been requested' if resp 134 | resp 135 | ensure 136 | browser.close rescue nil 137 | end 138 | 139 | def set_challenge_questions(account_email:, account_password:, answers:{}) 140 | raise ArgumentError, "answers: must be a hash." unless answers.is_a?(Hash) 141 | 142 | resp = challenge_questions.create account_email, account_password, answers 143 | logger.info 'Security Challenge Questions have been setup' if resp 144 | resp 145 | ensure 146 | browser.close rescue nil 147 | end 148 | 149 | def set_alternate_contacts(account_email:, account_password:, contact_info:) 150 | raise ArgumentError, "contact_info: must be a hash." unless contact_info.is_a?(Hash) 151 | 152 | resp = alternate_contacts.set account_email, account_password, contact_info 153 | logger.info 'Set alternate contacts.' if resp 154 | resp 155 | ensure 156 | browser.close rescue nil 157 | end 158 | 159 | def set_company_name(account_email:, account_password:, name:) 160 | resp = company_name.set account_email, account_password, name 161 | logger.info 'Set company name.' if resp 162 | resp 163 | ensure 164 | browser.close rescue nil 165 | end 166 | 167 | 168 | private 169 | def account_registration 170 | @account_registration ||= AccountRegistration.new logger, browser 171 | end 172 | 173 | def alternate_contacts 174 | @alternate_contacts ||= AlternateContacts.new logger, browser 175 | end 176 | 177 | def company_name 178 | @company_name ||= CompanyName.new logger, browser 179 | end 180 | 181 | def browser 182 | @browser ||= WatirBrowser.new(logger).create 183 | end 184 | 185 | def challenge_questions 186 | @challenge_questions ||= ChallengeQuestions.new logger, browser 187 | end 188 | 189 | def account 190 | @account ||= Account.new logger, browser 191 | end 192 | 193 | def consolidated_billing 194 | @consolidated_billing ||= ConsolidatedBilling.new logger, browser 195 | end 196 | 197 | def customer_information 198 | @customer_information ||= CustomerInformation.new logger, browser 199 | end 200 | 201 | def email_preferences 202 | @email_preferences ||= EmailPreferences.new logger, browser 203 | end 204 | 205 | def enterprise_support 206 | @enterprise_support ||= EnterpriseSupport.new logger, browser 207 | end 208 | 209 | def iam_billing 210 | @iam_billing ||= IamBilling.new logger, browser 211 | end 212 | 213 | def logger 214 | @logger ||= AccountLogger.new(log_level) 215 | end 216 | 217 | def password 218 | @password ||= Password.new logger, browser 219 | end 220 | 221 | def root_access_keys 222 | @root_access_keys ||= RootAccessKeys.new logger, browser 223 | end 224 | 225 | def logout 226 | @logout ||= Logout.new logger, browser 227 | end 228 | end 229 | end -------------------------------------------------------------------------------- /lib/aws_account_utils/account.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class Account < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def close(account_email, account_password) 14 | logger.debug "Closing AWS account." 15 | 16 | Login.new(logger, browser).execute url, 17 | account_email, 18 | account_password 19 | 20 | browser.checkbox(:ng_model =>'isClosingAccount').when_present.set 21 | screenshot(browser, "3") 22 | 23 | browser.button(:text => /Close Account/).when_present.click 24 | screenshot(browser, "2") 25 | 26 | browser.wait_until{ browser.text.include? 'Are you sure you want to close your account?'} 27 | screenshot(browser, "3") 28 | 29 | browser.div(:class => "modal fade in").button(:ng_click =>'closeAccount()').when_present.click 30 | screenshot(browser, "4") 31 | 32 | browser.p(:text => /Are you sure you want to close your account?/).wait_while_present 33 | 34 | 35 | 36 | browser.wait_until{ browser.text.include? 'Account has been closed'} 37 | 38 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 39 | screenshot(browser, "error") 40 | raise StandardError, "#{self.class.name} - #{e}" 41 | end 42 | 43 | private 44 | def url 45 | 'https://console.aws.amazon.com/billing/home?#/account' 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/aws_account_utils/account_logger.rb: -------------------------------------------------------------------------------- 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) 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.to_s.upcase 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/aws_account_utils/account_registration.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class AccountRegistration < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def signup(account_name, account_email, account_password) 14 | logger.debug "Signing up for a new account." 15 | login_details = { 'ap_customer_name' => account_name, 16 | 'ap_email' => account_email, 17 | 'ap_email_check' => account_email, 18 | 'ap_password' => account_password, 19 | 'ap_password_check' => account_password } 20 | 21 | browser.goto signup_url 22 | browser.text_field(:id => 'ap_customer_name').wait_until_present 23 | screenshot(browser, "1") 24 | login_details.each do |k,v| 25 | browser.text_field(:id => k).when_present.set v 26 | end 27 | screenshot(browser, "2") 28 | browser.button(:id => 'continue-input').when_present.click 29 | raise StandardError if browser.div(:id => /message_(error|warning)/).exist? 30 | true 31 | rescue StandardError 32 | screenshot(browser, "error") 33 | error_header = browser.div(:id => /message_(error|warning)/).h6.text 34 | error_body = browser.div(:id => /message_(error|warning)/).p.text 35 | raise StandardError, "AWS signup error: \"#{error_header}: #{error_body}\"" 36 | 37 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 38 | screenshot(browser, "error") 39 | raise StandardError, "#{self.class.name} - #{e}" 40 | end 41 | 42 | private 43 | def signup_url 44 | url = "https://www.amazon.com/ap/register?" 45 | url << "&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select" 46 | url << "&create=1&openid.assoc_handle=aws&accountStatusPolicy=P1" 47 | url << "&openid.ns=http://specs.openid.net/auth/2.0" 48 | url << "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select" 49 | url << "&openid.mode=checkid_setup" 50 | url << "&openid.return_to=https://console.aws.amazon.com/billing/signup" 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/aws_account_utils/alternate_contacts.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class AlternateContacts < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def set(account_email, account_password, contact_info = {}) 14 | logger.debug "Setting alternate account contacts." 15 | Login.new(logger, browser).execute url, 16 | account_email, 17 | account_password 18 | browser.a(:xpath => '//a[@ng-click="toggleEditingAlternateContactsInfoState()"]').when_present.click 19 | form_inputs(contact_info) 20 | screenshot(browser, "1") 21 | browser.button(:xpath => '//button[@ng-click="updateAlternateContacts()"]').when_present.click 22 | browser.div(:xpath => '//div[@ng-show="options.status == \'success\'"]').wait_until_present 23 | true 24 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 25 | screenshot(browser, "error") 26 | raise StandardError, "#{self.class.name} - #{e}" 27 | end 28 | 29 | private 30 | def form_inputs(requestor_info) 31 | requestor_info.each do |type, details| 32 | details.each do |key, value| 33 | browser.input(:xpath => "//input[@ng-model=\"alternateContacts.#{type}Contact.#{key}\"]").to_subtype.when_present.set value 34 | end 35 | end 36 | end 37 | 38 | def url 39 | 'https://console.aws.amazon.com/billing/home?#/account' 40 | end 41 | 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/aws_account_utils/base.rb: -------------------------------------------------------------------------------- 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 | 27 | -------------------------------------------------------------------------------- /lib/aws_account_utils/challenge_questions.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | require 'random-word' 4 | 5 | module AwsAccountUtils 6 | class ChallengeQuestions < Base 7 | attr_reader :logger, :browser 8 | 9 | def initialize(logger, browser) 10 | @logger = logger 11 | @browser = browser 12 | end 13 | 14 | def create(account_email, account_password, challenge_words) 15 | logger.debug "Setting security challenge answers." 16 | Login.new(logger, browser).execute url, 17 | account_email, 18 | account_password 19 | 20 | browser.a(:xpath => '//a[@ng-click="toggleEditingSecurityQuestionsInfoState()"]').when_present.click 21 | 22 | challenge_words = rand_challenge_words if challenge_words.empty? 23 | challenge_words.each do |num, word| 24 | browser.input(:xpath => "//input[@ng-model=\"selectedSecurityQuestions.question#{num}.answer\"]").to_subtype.when_present.set word 25 | end 26 | 27 | screenshot(browser, "1") 28 | browser.button(:xpath => '//button[@ng-click="updateSecurityQuestions()"]').when_present.click 29 | browser.a(:xpath => '//a[@ng-click="toggleEditingSecurityQuestionsInfoState()"]').wait_until_present 30 | challenge_words 31 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 32 | screenshot(browser, "error") 33 | raise StandardError, "#{self.class.name} - #{e}" 34 | end 35 | 36 | private 37 | def rand_challenge_words 38 | RandomWord.exclude_list << (/_/) if RandomWord.exclude_list.none? 39 | 40 | @challenge_words ||= (1..3).inject({}) do |hash, num| 41 | hash[num] = RandomWord.nouns.next 42 | hash 43 | end 44 | end 45 | 46 | def url 47 | 'https://portal.aws.amazon.com/gp/aws/manageYourAccount' 48 | end 49 | 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/aws_account_utils/company_name.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class CompanyName < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def set(account_email, account_password, company_name) 14 | logger.debug "Updating Company Name details." 15 | Login.new(logger, browser).execute url, 16 | account_email, 17 | account_password 18 | browser.a(:xpath => '//a[@ng-click="toggleEditingContactInfoState()"]').when_present.click 19 | browser.input(:xpath => '//input[@ng-model="address.company"]').to_subtype.set(company_name) 20 | # screenshot(browser, "1") 21 | browser.button(:xpath => '//button[@ng-click="updateContactInformation()"]').when_present.click 22 | browser.div(:xpath => '//div[@ng-show="options.status == \'success\'"]').wait_until_present 23 | true 24 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 25 | screenshot(browser, "error") 26 | raise StandardError, "#{self.class.name} - #{e}" 27 | end 28 | 29 | private 30 | def url 31 | 'https://console.aws.amazon.com/billing/home?#/account' 32 | end 33 | 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /lib/aws_account_utils/consolidated_billing.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class ConsolidatedBilling < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def request(master_account_email, master_account_password, account_email) 14 | logger.debug "Submitting consolidated billing request from master account #{master_account_email} to #{account_email}" 15 | Login.new(logger, browser).execute billing_request_url, 16 | master_account_email, 17 | master_account_password 18 | 19 | browser.text_field(:name => "emailaddresses").when_present.set account_email 20 | screenshot(browser, "1") 21 | browser.button(:class => "btn btn-primary margin-left-10").when_present.click 22 | browser.h2(:text => /Manage Requests and Accounts/).wait_until_present 23 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 24 | screenshot(browser, "error") 25 | raise StandardError, "#{self.class.name} - #{e}" 26 | end 27 | 28 | def confirm(account_email, account_password, confirmation_link) 29 | logger.debug "Confirming consolidated billing" 30 | 31 | Login.new(logger, browser).execute confirmation_link, 32 | account_email, 33 | account_password 34 | 35 | browser.button(:class => "btn btn-primary").when_present.click 36 | screenshot(browser, "1") 37 | browser.span(:text => /Accepting Request/).wait_while_present(timeout = 120) 38 | screenshot(browser, "2") 39 | true 40 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout, StandardError => e 41 | screenshot(browser, "error") 42 | page_error? 43 | raise StandardError, "#{self.class.name} - #{e}" 44 | end 45 | 46 | def existing?(account_email, account_password) 47 | logger.debug "Checking to see if Consolidated Billing is already setup" 48 | 49 | Login.new(logger, browser).execute billing_established_url, 50 | account_email, 51 | account_password 52 | browser.h2(:text => /Consolidated Billing/).wait_until_present 53 | screenshot(browser, "1") 54 | billing_setup? 55 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 56 | screenshot(browser, "error") 57 | raise StandardError, "#{self.class.name} - #{e}" 58 | end 59 | 60 | private 61 | def billing_setup? 62 | browser.text.include? 'Your account currently appears on the Consolidated Bill for the account below' 63 | end 64 | 65 | def page_error? 66 | if browser.text.include? 'error' 67 | logger.warn 'AWS webpage contains an error.' 68 | screenshot(browser, "aws_page_error") 69 | true 70 | end 71 | end 72 | 73 | def billing_request_url 74 | 'https://console.aws.amazon.com/billing/home?#/consolidatedbilling/sendrequest' 75 | end 76 | 77 | def billing_established_url 78 | 'https://console.aws.amazon.com/billing/home?#/consolidatedbilling' 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /lib/aws_account_utils/customer_information.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class CustomerInformation < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def submit(account_email, account_password, customer_details) 14 | logger.debug "Entering customer details." 15 | Login.new(logger, browser).execute url, 16 | account_email, 17 | account_password 18 | 19 | browser.wait_until{ browser.text.include? 'AWS Customer Agreement'} 20 | browser.select_list(:ng_model =>'address.countryCode').when_present.select 'United States' 21 | customer_details.each do |k,v| 22 | browser.text_field(:name => k).when_present.set v 23 | end 24 | browser.checkbox(:name, /ccepted/).when_present.set 25 | screenshot(browser, "1") 26 | browser.button(:text=> /Continue/).when_present.click 27 | 28 | browser.h2(:text => /Payment Information/).wait_until_present 29 | screenshot(browser, "2") 30 | raise StandardError if browser.text.include? 'error' 31 | browser.input(:id => "accountId", :value => "").wait_while_present(30) 32 | browser.input(:id => "accountId").value 33 | rescue StandardError 34 | screenshot(browser, 'error') 35 | raise StandardError, 'Aws returned error on the page when submitting customer information.' 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 url 43 | 'https://portal.aws.amazon.com/billing/signup#/account' 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /lib/aws_account_utils/customize_url.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class CustomizeUrl < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def execute(account_email, account_password, url_alias) 14 | logger.debug "Creating URL alias: #{url_alias}" 15 | Login.new(logger, browser).execute url, 16 | account_email, 17 | account_password 18 | 19 | browser.h2(:text => /Welcome to Identity and Access Management/).wait_until_present 20 | browser.button(:text => /Customize/).when_present.click 21 | browser.input(:id => 'alias_input').when_present.to_subtype.set url_alias 22 | screenshot(browser, "1") 23 | browser.button(:text => /Yes, Create/).when_present.click 24 | screenshot(browser, "2") 25 | browser.strong(:text => "https://#{url_alias}.signin.aws.amazon.com/console").wait_until_present 26 | "https://#{url_alias}.signin.aws.amazon.com/console" 27 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 28 | screenshot(browser, "error") 29 | raise StandardError, "#{self.class.name} - #{e}" 30 | end 31 | 32 | private 33 | def url 34 | 'https://console.aws.amazon.com/iam/home?#home' 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/aws_account_utils/email_preferences.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class EmailPreferences < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def opt_out(account_email, account_password) 14 | logger.debug "Setting email preferences." 15 | 16 | Login.new(logger, browser).execute url, 17 | account_email, 18 | account_password 19 | browser.input(:id => 'email_preferences_optout_all_true').when_present.click 20 | screenshot(browser, "1") 21 | browser.input(:value => 'Save Changes').when_present.click 22 | browser.h3(:text => /You have successfully updated your email preferences/).wait_until_present 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 url 30 | 'https://aws.amazon.com/email-preferences/' 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/aws_account_utils/enterprise_support.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class EnterpriseSupport < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def enable(account_email, account_password) 14 | logger.debug 'Enabling enterprise support.' 15 | Login.new(logger, browser).execute support_registration_url, 16 | account_email, 17 | account_password 18 | browser.input(:value => "AWSSupportEnterprise").when_present(timeout = 60).click 19 | browser.span(:text => /Continue/).when_present(timeout = 60).click 20 | screenshot(browser, "1") 21 | browser.p(:text => confirmation_text).wait_until_present(timeout = 60) 22 | screenshot(browser, "2") 23 | true 24 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 25 | page_error? 26 | screenshot(browser, "error") 27 | raise StandardError, "#{self.class.name} - #{e}" 28 | end 29 | 30 | def existing_support?(account_email,account_password) 31 | logger.debug 'Checking to see if enterprise support is enabled.' 32 | Login.new(logger, browser).execute support_status_url, 33 | account_email, 34 | account_password 35 | 36 | screenshot(browser, "1") 37 | browser.text.include? 'Enterprise Support Plan' 38 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 39 | page_error? 40 | screenshot(browser, "error") 41 | raise StandardError, "#{self.class.name} - #{e}" 42 | end 43 | 44 | private 45 | def page_error? 46 | if browser.text.include? 'error' 47 | logger.warn 'AWS webpage contains an error.' 48 | screenshot(browser, "aws_page_error") 49 | true 50 | end 51 | end 52 | 53 | def confirmation_text 54 | "Thank you for creating an Amazon Web Services (AWS) Account. We are in the process of activating your account. For most customers, activation only takes a couple minutes, but it can sometimes take a few hours if additional account verification is required. We will notify you by email when your account is activated." 55 | end 56 | 57 | def support_registration_url 58 | 'https://portal.aws.amazon.com/gp/aws/developer/registration/index.html' 59 | end 60 | 61 | def support_status_url 62 | 'https://console.aws.amazon.com/support/home' 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /lib/aws_account_utils/iam_billing.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class IamBilling < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def enable(account_email, account_password) 14 | logger.debug "Enabling IAM User Access to Billing Information" 15 | Login.new(logger, browser).execute url, 16 | account_email, 17 | account_password 18 | browser.a(:xpath => '//a[@ng-click="toggleEditingIAMPreferencesInfoState()"]').when_present(timeout = 120).click 19 | browser.label(:xpath => '//label[@ng-show="isEditingIAMPreferencesInfo"]').when_present.click 20 | screenshot(browser, "1") 21 | browser.button(:xpath => '//button[@ng-click="updateIAMPreferences()"]').when_present.click 22 | browser.strong(:text => /IAM user access to billing information is activated./).wait_until_present 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 url 30 | 'https://portal.aws.amazon.com/gp/aws/manageYourAccount' 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /lib/aws_account_utils/login.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | 3 | module AwsAccountUtils 4 | class Login < Base 5 | attr_reader :logger, :browser 6 | 7 | def initialize(logger, browser) 8 | @logger = logger 9 | @browser = browser 10 | end 11 | 12 | def execute(url, aws_email, password) 13 | browser.goto url 14 | return true unless login_page? 15 | logger.debug "Logging into AWS." 16 | screenshot(browser, "1") 17 | browser.text_field(:id => 'ap_email').when_present.set aws_email 18 | browser.text_field(:id => 'ap_password').when_present.set password 19 | screenshot(browser, "2") 20 | browser.button(:id => 'signInSubmit-input').when_present.click 21 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 22 | screenshot(browser, "error") 23 | raise StandardError, "#{self.class.name} - #{e}" 24 | end 25 | 26 | private 27 | def login_page? 28 | browser.url.include? 'ap/signin?' 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /lib/aws_account_utils/logout.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | 3 | module AwsAccountUtils 4 | class Logout < Base 5 | attr_reader :logger, :browser 6 | 7 | def initialize(logger, browser) 8 | @logger = logger 9 | @browser = browser 10 | end 11 | 12 | def execute 13 | logger.debug "Logging out of AWS." 14 | browser.goto url 15 | screenshot(browser, "1") 16 | browser.wait_until{ browser.url.include? 'https://aws.amazon.com/'} 17 | browser.text.include?('Sign In to the Console') || browser.text.include?('Create a Free Account') 18 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 19 | screenshot(browser, "error") 20 | raise StandardError, "#{self.class.name} - #{e}" 21 | end 22 | 23 | private 24 | def url 25 | 'https://console.aws.amazon.com/support/logout!doLogout' 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/aws_account_utils/password.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class Password < Base 6 | attr_reader :logger, :browser 7 | 8 | def initialize(logger, browser) 9 | @logger = logger 10 | @browser = browser 11 | end 12 | 13 | def change(account_email, account_password, new_password) 14 | logger.debug 'Changing root password.' 15 | Login.new(logger, browser).execute url, 16 | account_email, 17 | account_password 18 | browser.h1(:text => /Change Name, E-mail Address, or Password/).wait_until_present 19 | screenshot(browser, "1") 20 | browser.button(:id => 'cnep_1A_change_password_button-input').when_present.click 21 | screenshot(browser, "2") 22 | browser.text_field(:id =>"ap_password").when_present.set account_password 23 | browser.text_field(:id =>"ap_password_new").when_present.set new_password 24 | browser.text_field(:id =>"ap_password_new_check").when_present.set new_password 25 | screenshot(browser, "3") 26 | browser.button(:id => "cnep_1D_submit_button-input").when_present.click 27 | raise StandardError if browser.div(:id => /message_(error|warning)/).exist? 28 | browser.h6(:text => /Success/).exist? 29 | rescue StandardError => e 30 | screenshot(browser, "error") 31 | error_header = browser.div(:id => /message_(error|warning)/).h6.text 32 | error_body = browser.div(:id => /message_(error|warning)/).p.text 33 | raise StandardError, "AWS Password Change Error: \"#{error_header}: #{error_body}\"" 34 | 35 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 36 | screenshot(browser, "error") 37 | raise StandardError, "#{self.class.name} - #{e}" 38 | end 39 | 40 | private 41 | def url 42 | url = "https://www.amazon.com/ap/cnep?_encoding=UTF8" 43 | url<< "&openid.assoc_handle=aws" 44 | url<< "&openid.return_to=https%3A%2F%2Fconsole.aws.amazon.com%2Fbilling%2Fhome%23%2Faccount" 45 | url<< "&openid.mode=id_res&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0" 46 | url<< "&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" 47 | url<< "&openid.pape.max_auth_age=600" 48 | url<< "&openid.pape.preferred_auth_policies=http%3A%2F%2Fschemas.openid.net%2Fpape%2Fpolicies%2F2007%2F06%2Fmulti-factor-physical" 49 | url<< "&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0" 50 | url<< "&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" 51 | end 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/aws_account_utils/root_access_keys.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'aws_account_utils/login' 3 | 4 | module AwsAccountUtils 5 | class RootAccessKeys < 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) 14 | logger.debug "Creating root access/secret key" 15 | Login.new(logger, browser).execute url, 16 | account_email, 17 | account_password 18 | clear_warning if browser.div(:id => 'modal-content', :text => warning_text) 19 | browser.i(:xpath => "id('credaccordion')/div[3]/div[1]/div/div[1]/i").when_present.click 20 | browser.button(:text => /Create New Access Key/).when_present.click 21 | browser.a(:text => /Show Access Key/).when_present.click 22 | screenshot(browser, "1") 23 | parse_keys browser.text 24 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 25 | screenshot(browser, "error") 26 | raise StandardError, "#{self.class.name} - #{e}" 27 | end 28 | 29 | def delete(account_email, account_password) 30 | logger.debug "Deleting root access/secret key" 31 | Login.new(logger, browser).execute url, 32 | account_email, 33 | account_password 34 | clear_warning if browser.div(:id => 'modal-content', :text => warning_text) 35 | browser.i(:xpath => "id('credaccordion')/div[3]/div[1]/div/div[1]/i").when_present.click 36 | keys_to_delete? ? delete_all_keys : true 37 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 38 | screenshot(browser, "error") 39 | raise StandardError, "#{self.class.name} - #{e}" 40 | end 41 | 42 | private 43 | def delete_all_keys 44 | tries ||= 4 45 | browser.link(:text => 'Delete').when_present.click 46 | logger.debug "Deleting access_key: #{browser.div(:id => 'modal-content').strong.text}" 47 | browser.div(:text => /Are you sure you want to delete the access key/).wait_until_present 48 | browser.link(:text => /Yes/).when_present.click 49 | screenshot(browser, "2") 50 | browser.link(:text => /Yes/).wait_while_present 51 | screenshot(browser, "3") 52 | raise StandardError if keys_to_delete? 53 | rescue StandardError 54 | retry unless (tries -= 1).zero? 55 | false 56 | else 57 | true 58 | end 59 | 60 | def url 61 | 'https://console.aws.amazon.com/iam/home?#security_credential' 62 | end 63 | 64 | def warning_text 65 | 'You are accessing the security credentials page for your AWS account. The account credentials provide unlimited access to your AWS resources.' 66 | end 67 | 68 | def keys_to_delete? 69 | browser.a(:class => 'Delete').exist? 70 | end 71 | 72 | def clear_warning 73 | browser.label(:text => /Don't show me this message again/).wait_until_present 74 | screenshot(browser, "4") 75 | browser.element(:id => 'continue').when_present.click 76 | rescue Watir::Wait::TimeoutError, Net::ReadTimeout => e 77 | screenshot(browser, "error") 78 | raise StandardError, "#{self.class.name} - #{e}" 79 | end 80 | 81 | def parse_keys(text) 82 | { access_key: text.split("\n")[-4], 83 | secret_key: text.split("\n")[-2] } 84 | end 85 | end 86 | end -------------------------------------------------------------------------------- /lib/aws_account_utils/settings.rb: -------------------------------------------------------------------------------- 1 | module Settings 2 | 3 | def self.set_screenshot_dir(directory) 4 | @screenshot_dir = directory 5 | end 6 | 7 | def self.screenshot_dir 8 | @screenshot_dir 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/aws_account_utils/version.rb: -------------------------------------------------------------------------------- 1 | module AwsAccountUtils 2 | VERSION = "0.1.5" 3 | end 4 | -------------------------------------------------------------------------------- /lib/aws_account_utils/watir_browser.rb: -------------------------------------------------------------------------------- 1 | require 'aws_account_utils/base' 2 | require 'watir-webdriver' 3 | Watir::HTMLElement.attributes << :ng_model 4 | Watir::HTMLElement.attributes << :ng_click 5 | Watir::HTMLElement.attributes << :ng_class 6 | 7 | module AwsAccountUtils 8 | class WatirBrowser 9 | attr_reader :logger 10 | 11 | def initialize(logger) 12 | @logger = logger 13 | end 14 | 15 | def create 16 | logger.debug "Launching new browser." 17 | Watir::Browser.new(:firefox, :profile => set_firefox_profile) 18 | end 19 | 20 | private 21 | def set_firefox_profile 22 | profile = Selenium::WebDriver::Firefox::Profile.new 23 | 24 | if proxy 25 | proxy_settings.each do |k,v| 26 | profile["network.proxy.#{k}"] = v 27 | end 28 | end 29 | 30 | profile['browser.privatebrowsing.dont_prompt_on_enter'] = true 31 | profile['browser.privatebrowsing.autostart'] = true 32 | profile.native_events = false 33 | profile 34 | end 35 | 36 | def proxy_settings 37 | { 38 | 'http' => proxy, 39 | 'http_port' => proxy_port, 40 | 'ssl' => proxy, 41 | 'ssl_port' => proxy_port, 42 | 'no_proxies_on' => '127.0.0.1', 43 | 'type' => 1 44 | } 45 | end 46 | 47 | def proxy 48 | @proxy ||= ENV['AWS_ACCOUNT_UTILS_HTTP_PROXY'] 49 | end 50 | 51 | def proxy_port 52 | @proxy_port ||= ENV['AWS_ACCOUNT_UTILS_HTTP_PROXY_PORT'] 53 | end 54 | end 55 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/account_registration_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::AccountRegistration do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::AccountRegistration.new logger, browser } 6 | let(:browser) { double 'browser' } 7 | let(:button) { double 'button' } 8 | let(:text_field) { double 'text_field' } 9 | let(:error_header) { "There was a problem with your request" } 10 | let(:error_body) { "an account already exists with the e-mail" } 11 | 12 | let(:url) { url } 13 | let(:options) { {:log_level => 'debug', 14 | :screenshots => File.expand_path("/var/temp/screenshots", 15 | File.dirname(__FILE__)), 16 | :account_name => 'Dune', 17 | :account_email => 'paul_atredies@gmail.com', 18 | :account_password => 'melange', 19 | :customer_details => { 'fullName' => 'The Planet Arrakis', 20 | 'company' => 'House Atreides', 21 | 'addressLine1' => '1 Dune Way', 22 | 'city' => 'Imperium', 23 | 'state' => 'CA', 24 | 'postalCode' => '92000', 25 | 'phoneNumber' => '(800) 555-1212', 26 | 'guess' => 'Spice' }} } 27 | 28 | url = "https://www.amazon.com/ap/register?" 29 | url << "&openid.claimed_id=http://specs.openid.net/auth/2.0/identifier_select" 30 | url << "&create=1&openid.assoc_handle=aws&accountStatusPolicy=P1" 31 | url << "&openid.ns=http://specs.openid.net/auth/2.0" 32 | url << "&openid.identity=http://specs.openid.net/auth/2.0/identifier_select" 33 | url << "&openid.mode=checkid_setup" 34 | url << "&openid.return_to=https://console.aws.amazon.com/billing/signup" 35 | 36 | it "should setup Enterprise Support" do 37 | expect(logger).to receive(:debug).with('Signing up for a new account.') 38 | expect(browser).to receive(:goto).with(url) 39 | expect(browser).to receive(:text_field).with({:id=>"ap_customer_name"}) 40 | .and_return(text_field) 41 | expect(text_field).to receive(:wait_until_present) 42 | expect(browser).to receive(:text_field).with({:id=>"ap_customer_name"}) 43 | .and_return(text_field) 44 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}) 45 | .and_return(text_field) 46 | expect(browser).to receive(:text_field).with({:id=>"ap_email_check"}) 47 | .and_return(text_field) 48 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}) 49 | .and_return(text_field) 50 | expect(browser).to receive(:text_field).with({:id=>"ap_password_check"}) 51 | .and_return(text_field) 52 | expect(text_field).to receive(:when_present).exactly(5).times 53 | .and_return(text_field) 54 | expect(text_field).to receive(:set).exactly(5).times 55 | expect(browser).to receive(:button).with({:id=>"continue-input"}) 56 | .and_return(button) 57 | expect(subject).to receive(:screenshot).with(browser, "1") 58 | expect(subject).to receive(:screenshot).with(browser, "2") 59 | expect(button).to receive(:when_present).and_return(button) 60 | expect(button).to receive(:click) 61 | expect(browser).to receive(:div).with(:id => /message_(error|warning)/) 62 | .and_return(browser) 63 | expect(browser).to receive(:exist?).and_return(false) 64 | expect(subject.signup("my_account", "my_email", "my_password")).to be_truthy 65 | end 66 | 67 | it "should raise an error if the page has an error" do 68 | expect(logger).to receive(:debug).with('Signing up for a new account.') 69 | expect(browser).to receive(:goto).with(url) 70 | expect(browser).to receive(:text_field).with({:id=>"ap_customer_name"}) 71 | .and_return(text_field) 72 | expect(text_field).to receive(:wait_until_present) 73 | expect(browser).to receive(:text_field).with({:id=>"ap_customer_name"}) 74 | .and_return(text_field) 75 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}) 76 | .and_return(text_field) 77 | expect(browser).to receive(:text_field).with({:id=>"ap_email_check"}) 78 | .and_return(text_field) 79 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}) 80 | .and_return(text_field) 81 | expect(browser).to receive(:text_field).with({:id=>"ap_password_check"}) 82 | .and_return(text_field) 83 | expect(text_field).to receive(:when_present).exactly(5).times 84 | .and_return(text_field) 85 | expect(text_field).to receive(:set).exactly(5).times 86 | expect(browser).to receive(:button).with({:id=>"continue-input"}) 87 | .and_return(button) 88 | expect(subject).to receive(:screenshot).with(browser, "1") 89 | expect(subject).to receive(:screenshot).with(browser, "2") 90 | expect(button).to receive(:when_present).and_return(button) 91 | expect(button).to receive(:click) 92 | expect(browser).to receive(:div).with(:id => /message_(error|warning)/) 93 | .and_return(browser) 94 | expect(browser).to receive(:exist?).and_return(true) 95 | expect(subject).to receive(:screenshot).with(browser, "error") 96 | expect(browser).to receive(:div).with(:id => /message_(error|warning)/) 97 | .and_return(browser) 98 | expect(browser).to receive(:h6).and_return(browser) 99 | expect(browser).to receive(:text).and_return(error_header) 100 | expect(browser).to receive(:div).with(:id => /message_(error|warning)/) 101 | .and_return(browser) 102 | expect(browser).to receive(:p).and_return(browser) 103 | expect(browser).to receive(:text).and_return(error_body) 104 | expect{subject.signup("my_account", "my_email", "my_password")} 105 | .to raise_error(StandardError, 106 | "AWS signup error: \"#{error_header}: #{error_body}\"") 107 | 108 | end 109 | end 110 | -------------------------------------------------------------------------------- /spec/aws_account_utils/account_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::Account do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::Account.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:text_field) { double 'browser text field' } 9 | let(:checkbox) { double 'browser checkbox' } 10 | let(:text) { double 'browser text' } 11 | let(:p) { double 'browser p element' } 12 | let(:button) { double 'browser button' } 13 | let(:div) { double 'browser div' } 14 | let(:url) { 'https://console.aws.amazon.com/billing/home?#/account' } 15 | 16 | it "should create a url alias" do 17 | expect(logger).to receive(:debug).with('Closing AWS account.') 18 | 19 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}).and_return text_field 20 | expect(text_field).to receive(:when_present).and_return text_field 21 | expect(text_field).to receive(:set) 22 | 23 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}).and_return text_field 24 | expect(text_field).to receive(:when_present).and_return text_field 25 | expect(text_field).to receive(:set) 26 | 27 | expect(browser).to receive(:button).with({:id=>"signInSubmit-input"}).and_return button 28 | expect(button).to receive(:when_present).and_return button 29 | expect(button).to receive(:click) 30 | 31 | expect(browser).to receive(:goto).with(url) 32 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 33 | expect(logger).to receive(:debug).with('Logging into AWS.') 34 | 35 | expect(browser).to receive(:checkbox).with({:ng_model => "isClosingAccount"}).and_return checkbox 36 | expect(checkbox).to receive(:when_present).and_return checkbox 37 | expect(checkbox).to receive(:set) 38 | 39 | expect(browser).to receive(:button).with({:text => /Close Account/}).and_return button 40 | expect(button).to receive(:when_present).and_return button 41 | expect(button).to receive(:click) 42 | 43 | expect(browser).to receive(:wait_until).and_return browser 44 | 45 | expect(browser).to receive(:div).with({:class=>"modal fade in"}).and_return div 46 | expect(div).to receive(:button).with({:ng_click=>"closeAccount()"}).and_return div 47 | expect(div).to receive(:when_present).and_return div 48 | expect(div).to receive(:click) 49 | 50 | expect(browser).to receive(:p).with({:text => /Are you sure you want to close your account?/}).and_return p 51 | expect(p).to receive(:wait_while_present).and_return p 52 | 53 | expect(browser).to receive(:wait_until).and_return browser 54 | 55 | expect(subject.close('my_user', 'my_password')).to be_truthy 56 | end 57 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/alternate_contacts_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::AlternateContacts do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::AlternateContacts.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:a) { double 'browser element a' } 9 | let(:div) { double 'browser element div' } 10 | let(:input) { double 'browser input' } 11 | let(:button) { double 'browser button' } 12 | let(:text_field) { double 'browser text field' } 13 | let(:url) { 'https://console.aws.amazon.com/billing/home?#/account' } 14 | let(:contacts) { { 'operations' => { 'name' => 'Operations Name', 15 | 'title' => 'Operations Title', 16 | 'email' => 'operations@test.com', 17 | 'phoneNumber' => '888-888-1212'}, 18 | 'security' => { 'name' => 'Security Name', 19 | 'title' => 'Security Title', 20 | 'email' => 'Security@test.com', 21 | 'phoneNumber' => '888-888-1212'}} } 22 | 23 | 24 | it "should setup Alternate Contacts" do 25 | expect(logger).to receive(:debug).with('Setting alternate account contacts.') 26 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}).and_return text_field 27 | expect(text_field).to receive(:when_present).and_return text_field 28 | expect(text_field).to receive(:set) 29 | 30 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}).and_return text_field 31 | expect(text_field).to receive(:when_present).and_return text_field 32 | expect(text_field).to receive(:set) 33 | 34 | expect(browser).to receive(:button).with({:id=>"signInSubmit-input"}).and_return button 35 | expect(button).to receive(:when_present).and_return button 36 | expect(button).to receive(:click) 37 | 38 | expect(browser).to receive(:goto).with(url) 39 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 40 | expect(logger).to receive(:debug).with('Logging into AWS.') 41 | 42 | expect(browser).to receive(:a) 43 | .with({:xpath=>"//a[@ng-click=\"toggleEditingAlternateContactsInfoState()\"]"}) 44 | .and_return a 45 | expect(a).to receive(:when_present).and_return a 46 | expect(a).to receive(:click) 47 | 48 | 49 | expect(browser).to receive(:input) 50 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.operationsContact.name\"]"}) 51 | .and_return input 52 | expect(input).to receive(:set).with('Operations Name').and_return input 53 | expect(browser).to receive(:input) 54 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.operationsContact.title\"]"}) 55 | .and_return input 56 | expect(input).to receive(:set).with('Operations Title').and_return input 57 | expect(browser).to receive(:input) 58 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.operationsContact.email\"]"}) 59 | .and_return input 60 | expect(input).to receive(:set).with('operations@test.com').and_return input 61 | expect(browser).to receive(:input) 62 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.operationsContact.phoneNumber\"]"}) 63 | .and_return input 64 | expect(input).to receive(:set).with('888-888-1212').and_return input 65 | 66 | expect(browser).to receive(:input) 67 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.securityContact.name\"]"}) 68 | .and_return input 69 | expect(input).to receive(:set).with('Security Name').and_return input 70 | expect(browser).to receive(:input) 71 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.securityContact.title\"]"}) 72 | .and_return input 73 | expect(input).to receive(:set).with('Security Title').and_return input 74 | expect(browser).to receive(:input) 75 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.securityContact.email\"]"}) 76 | .and_return input 77 | expect(input).to receive(:set).with('Security@test.com').and_return input 78 | expect(browser).to receive(:input) 79 | .with({:xpath=>"//input[@ng-model=\"alternateContacts.securityContact.phoneNumber\"]"}) 80 | .and_return input 81 | expect(input).to receive(:set).with('888-888-1212').and_return input 82 | 83 | expect(input).to receive(:when_present).exactly(8).times.and_return input 84 | expect(input).to receive(:to_subtype).exactly(8).times.and_return input 85 | 86 | expect(browser).to receive(:button) 87 | .with({:xpath=>"//button[@ng-click=\"updateAlternateContacts()\"]"}) 88 | .and_return button 89 | expect(button).to receive(:when_present).and_return button 90 | expect(button).to receive(:click) 91 | 92 | expect(browser).to receive(:div) 93 | .with({:xpath=>"//div[@ng-show=\"options.status == 'success'\"]"}) 94 | .and_return div 95 | expect(div).to receive(:wait_until_present) 96 | 97 | expect(subject.set('my_user', 'my_password', contacts)).to be_truthy 98 | end 99 | end 100 | -------------------------------------------------------------------------------- /spec/aws_account_utils/challenge_questions_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::ChallengeQuestions do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::ChallengeQuestions.new logger, browser } 6 | let(:browser) { double 'browser' } 7 | let(:a) { double 'browser element a' } 8 | let(:div) { double 'browser element div' } 9 | let(:input) { double 'browser input' } 10 | let(:button) { double 'browser button' } 11 | let(:text_field) { double 'browser text field' } 12 | let(:url) { 'https://portal.aws.amazon.com/gp/aws/manageYourAccount' } 13 | 14 | it "should set the answers to the security questions" do 15 | expect(logger).to receive(:debug).with('Setting security challenge answers.') 16 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}).and_return text_field 17 | expect(text_field).to receive(:when_present).and_return text_field 18 | expect(text_field).to receive(:set) 19 | 20 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}).and_return text_field 21 | expect(text_field).to receive(:when_present).and_return text_field 22 | expect(text_field).to receive(:set) 23 | 24 | expect(browser).to receive(:button).with({:id=>"signInSubmit-input"}).and_return button 25 | expect(button).to receive(:when_present).and_return button 26 | expect(button).to receive(:click) 27 | 28 | expect(browser).to receive(:goto).with(url) 29 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 30 | expect(logger).to receive(:debug).with('Logging into AWS.') 31 | expect(browser).to receive(:a) 32 | .with({:xpath=>"//a[@ng-click=\"toggleEditingSecurityQuestionsInfoState()\"]"}) 33 | .and_return a 34 | expect(a).to receive(:when_present).and_return a 35 | expect(a).to receive(:click) 36 | 37 | expect(browser).to receive(:input) 38 | .with({:xpath => "//input[@ng-model=\"selectedSecurityQuestions.question1.answer\"]"}) 39 | .and_return input 40 | 41 | expect(browser).to receive(:input) 42 | .with({:xpath => "//input[@ng-model=\"selectedSecurityQuestions.question2.answer\"]"}) 43 | .and_return input 44 | 45 | expect(browser).to receive(:input) 46 | .with({:xpath => "//input[@ng-model=\"selectedSecurityQuestions.question3.answer\"]"}) 47 | .and_return input 48 | expect(input).to receive(:to_subtype).exactly(3).times.and_return input 49 | expect(input).to receive(:when_present).exactly(3).times.and_return input 50 | expect(input).to receive(:set).exactly(3).times 51 | 52 | expect(browser).to receive(:button) 53 | .with({:xpath=>"//button[@ng-click=\"updateSecurityQuestions()\"]"}) 54 | .and_return button 55 | expect(button).to receive(:when_present).and_return button 56 | expect(button).to receive(:click) 57 | 58 | expect(browser).to receive(:a) 59 | .with({:xpath=>"//a[@ng-click=\"toggleEditingSecurityQuestionsInfoState()\"]"}) 60 | .and_return a 61 | expect(a).to receive(:wait_until_present) 62 | 63 | 64 | expect(subject.create('my_user', 65 | 'my_password', 66 | {1 => 'answer1', 67 | 2 => 'answer2', 68 | 3 => 'answer3'})).to eq({1=>"answer1", 69 | 2=>"answer2", 70 | 3=>"answer3"}) 71 | 72 | end 73 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/company_name_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::CompanyName do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::CompanyName.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:a) { double 'browser element a' } 9 | let(:div) { double 'browser element div' } 10 | let(:input) { double 'browser input' } 11 | let(:button) { double 'browser button' } 12 | let(:text_field) { double 'browser text field' } 13 | let(:url) { 'https://console.aws.amazon.com/billing/home?#/account' } 14 | let(:name) { 'company_name' } 15 | 16 | it "should update Contact Details" do 17 | expect(logger).to receive(:debug).with('Updating Company Name details.') 18 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}).and_return text_field 19 | expect(text_field).to receive(:when_present).and_return text_field 20 | expect(text_field).to receive(:set) 21 | 22 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}).and_return text_field 23 | expect(text_field).to receive(:when_present).and_return text_field 24 | expect(text_field).to receive(:set) 25 | 26 | expect(browser).to receive(:button).with({:id=>"signInSubmit-input"}).and_return button 27 | expect(button).to receive(:when_present).and_return button 28 | expect(button).to receive(:click) 29 | 30 | expect(browser).to receive(:goto).with(url) 31 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 32 | expect(logger).to receive(:debug).with('Logging into AWS.') 33 | 34 | expect(browser).to receive(:a) 35 | .with({:xpath=>"//a[@ng-click=\"toggleEditingContactInfoState()\"]"}) 36 | .and_return a 37 | expect(a).to receive(:when_present).and_return a 38 | expect(a).to receive(:click) 39 | 40 | 41 | expect(browser).to receive(:input) 42 | .with({:xpath=>"//input[@ng-model=\"address.company\"]"}) 43 | .and_return input 44 | expect(input).to receive(:to_subtype).and_return input 45 | expect(input).to receive(:set).with('company_name').and_return input 46 | 47 | 48 | expect(browser).to receive(:button) 49 | .with({:xpath=>"//button[@ng-click=\"updateContactInformation()\"]"}) 50 | .and_return button 51 | expect(button).to receive(:when_present).and_return button 52 | expect(button).to receive(:click) 53 | 54 | expect(browser).to receive(:div) 55 | .with({:xpath=>"//div[@ng-show=\"options.status == 'success'\"]"}) 56 | .and_return div 57 | expect(div).to receive(:wait_until_present) 58 | 59 | expect(subject.set('my_user', 'my_password', 'company_name')).to be_truthy 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /spec/aws_account_utils/consolidated_billing_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::ConsolidatedBilling do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::ConsolidatedBilling.new logger, browser } 6 | let(:browser) { double 'browser' } 7 | let(:h2) { double 'browser element h2' } 8 | let(:input) { double 'browser input' } 9 | let(:button) { double 'browser button' } 10 | let(:text_field) { double 'browser text field' } 11 | let(:url) { 'https://console.aws.amazon.com/billing/home?#/consolidatedbilling/sendrequest' } 12 | 13 | it "should confirm consolidated billing" do 14 | expect(logger).to receive(:debug) 15 | .with('Submitting consolidated billing request from master account master_acct_user to acct_email@test.com') 16 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}).and_return text_field 17 | expect(text_field).to receive(:when_present).and_return text_field 18 | expect(text_field).to receive(:set) 19 | 20 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}).and_return text_field 21 | expect(text_field).to receive(:when_present).and_return text_field 22 | expect(text_field).to receive(:set) 23 | 24 | expect(browser).to receive(:button).with({:id=>"signInSubmit-input"}).and_return button 25 | expect(button).to receive(:when_present).and_return button 26 | expect(button).to receive(:click) 27 | 28 | expect(browser).to receive(:goto).with(url) 29 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 30 | expect(logger).to receive(:debug).with('Logging into AWS.') 31 | 32 | expect(browser).to receive(:text_field).with({:name=>"emailaddresses"}).and_return text_field 33 | expect(text_field).to receive(:when_present).and_return text_field 34 | expect(text_field).to receive(:set) 35 | 36 | expect(browser).to receive(:button).with({:class=>"btn btn-primary margin-left-10"}).and_return button 37 | expect(button).to receive(:when_present).and_return button 38 | expect(button).to receive(:click) 39 | 40 | expect(browser).to receive(:h2).with({:text=>/Manage Requests and Accounts/}).and_return h2 41 | expect(h2).to receive(:wait_until_present) 42 | 43 | expect(subject.request('master_acct_user', 44 | 'master_acct_password', 45 | 'acct_email@test.com')).to be_nil 46 | end 47 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/customer_information_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::CustomerInformation do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::CustomerInformation.new logger, browser } 6 | let(:browser) { double 'browser' } 7 | let(:h2) { double 'browser element h2' } 8 | let(:input) { double 'browser input' } 9 | let(:text) { double 'browser text' } 10 | let(:button) { double 'browser button' } 11 | let(:checkbox) { double 'browser checkbox' } 12 | let(:link) { double 'browser link' } 13 | let(:select_list) { double 'browser select list' } 14 | let(:text_field) { double 'browser text field' } 15 | let(:url) { 'https://portal.aws.amazon.com/billing/signup#/account' } 16 | let(:customer_details) { { 'fullName' => 'Hermen Munster', 17 | 'company' => 'The Munsters', 18 | 'addressLine1' => '1313 Mockingbird Lane', 19 | 'city' => 'Mockingbird Heights', 20 | 'state' => 'CA', 21 | 'postalCode' => '92000', 22 | 'phoneNumber' => '(800) 555-1212', 23 | 'guess' => 'Test Account' } } 24 | 25 | before (:each) do 26 | expect(logger).to receive(:debug).with('Entering customer details.') 27 | 28 | expect(browser).to receive(:text_field).with({:id=>"ap_email"}).and_return text_field 29 | expect(text_field).to receive(:when_present).and_return text_field 30 | expect(text_field).to receive(:set) 31 | 32 | expect(browser).to receive(:text_field).with({:id=>"ap_password"}).and_return text_field 33 | expect(text_field).to receive(:when_present).and_return text_field 34 | expect(text_field).to receive(:set) 35 | 36 | expect(browser).to receive(:button).with({:id=>"signInSubmit-input"}).and_return button 37 | expect(button).to receive(:when_present).and_return button 38 | expect(button).to receive(:click) 39 | 40 | expect(browser).to receive(:goto).with(url) 41 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 42 | expect(logger).to receive(:debug).with('Logging into AWS.') 43 | 44 | expect(browser).to receive(:wait_until).and_return text 45 | 46 | expect(browser).to receive(:select_list) 47 | .with({:ng_model=>"address.countryCode"}) 48 | .and_return select_list 49 | expect(select_list).to receive(:when_present).and_return select_list 50 | expect(select_list).to receive(:select).with("United States") 51 | 52 | customer_details.each do |key, value| 53 | expect(browser).to receive(:text_field).with({:name=>"#{key}"}) 54 | .and_return text_field 55 | expect(text_field).to receive(:when_present).and_return text_field 56 | expect(text_field).to receive(:set).with(value) 57 | end 58 | 59 | expect(browser).to receive(:checkbox).with(:name, /ccepted/) 60 | .and_return checkbox 61 | expect(checkbox).to receive(:when_present).and_return checkbox 62 | expect(checkbox).to receive(:set) 63 | 64 | expect(browser).to receive(:button).with({:text=>/Continue/}) 65 | .and_return button 66 | expect(button).to receive(:when_present).and_return button 67 | expect(button).to receive(:click) 68 | 69 | expect(browser).to receive(:h2).with({:text=>/Payment Information/}) 70 | .and_return h2 71 | expect(h2).to receive(:wait_until_present) 72 | 73 | expect(subject).to receive(:screenshot).with(browser, "1") 74 | expect(subject).to receive(:screenshot).with(browser, "2") 75 | end 76 | 77 | it "should set the customer information" do 78 | expect(browser).to receive(:text).and_return('good response') 79 | 80 | expect(browser).to receive(:input).with({:id=>"accountId", :value=>''}) 81 | .and_return input 82 | expect(browser).to receive(:input).with({:id=>"accountId"}).and_return input 83 | expect(input).to receive(:wait_while_present).with(30) 84 | expect(input).to receive(:value).and_return('123456789012') 85 | 86 | 87 | expect(subject.submit('my_email', 88 | 'my_password', 89 | customer_details)).to eq '123456789012' 90 | end 91 | 92 | it "should raise and error if there is an error on the webpage" do 93 | expect(browser).to receive(:text).and_return('correct the error') 94 | 95 | expect(subject).to receive(:screenshot).with(browser, "error") 96 | 97 | expect{subject.submit('my_email', 'my_password', customer_details)} 98 | .to raise_error(StandardError, 99 | 'Aws returned error on the page when submitting customer information.') 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /spec/aws_account_utils/customize_url_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::CustomizeUrl do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::CustomizeUrl.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:strong) { double 'browser strong' } 9 | let(:h2) { double 'browser element h2' } 10 | let(:input) { double 'browser input' } 11 | let(:button) { double 'browser button' } 12 | let(:text_field) { double 'browser text field' } 13 | let(:url) { 'https://console.aws.amazon.com/iam/home?#home' } 14 | 15 | it "should create a url alias" do 16 | expect(logger).to receive(:debug).with('Creating URL alias: my.alternateurl.com') 17 | expect(browser).to receive(:text_field).with({:id => "ap_email"}).and_return text_field 18 | expect(text_field).to receive(:when_present).and_return text_field 19 | expect(text_field).to receive(:set) 20 | 21 | expect(browser).to receive(:text_field).with({:id => "ap_password"}).and_return text_field 22 | expect(text_field).to receive(:when_present).and_return text_field 23 | expect(text_field).to receive(:set) 24 | 25 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}).and_return button 26 | expect(button).to receive(:when_present).and_return button 27 | expect(button).to receive(:click) 28 | 29 | expect(browser).to receive(:goto).with(url) 30 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 31 | expect(logger).to receive(:debug).with('Logging into AWS.') 32 | 33 | expect(browser).to receive(:h2).with({:text => /Welcome to Identity and Access Management/}).and_return h2 34 | expect(h2).to receive(:wait_until_present) 35 | 36 | expect(browser).to receive(:button).with({:text => /Customize/}).and_return button 37 | expect(button).to receive(:when_present).and_return button 38 | expect(button).to receive(:click) 39 | 40 | expect(browser).to receive(:input).with({:id => 'alias_input'}).and_return input 41 | expect(input).to receive(:when_present).and_return input 42 | expect(input).to receive(:to_subtype).and_return input 43 | expect(input).to receive(:set).with('my.alternateurl.com') 44 | 45 | expect(browser).to receive(:button).with({:text => /Yes, Create/}).and_return button 46 | expect(button).to receive(:when_present).and_return button 47 | expect(button).to receive(:click) 48 | 49 | expect(browser).to receive(:strong).with({:text => "https://my.alternateurl.com.signin.aws.amazon.com/console"}).and_return strong 50 | expect(strong).to receive(:wait_until_present) 51 | 52 | expect(subject.execute('my_user', 'my_password', 'my.alternateurl.com')).to be_truthy 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /spec/aws_account_utils/email_preferences_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::EmailPreferences do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::EmailPreferences.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:strong) { double 'browser strong' } 9 | let(:h3) { double 'browser element h3' } 10 | let(:input) { double 'browser input' } 11 | let(:button) { double 'browser button' } 12 | let(:text_field) { double 'browser text field' } 13 | let(:url) { 'https://aws.amazon.com/email-preferences/' } 14 | 15 | it "should set email preferences" do 16 | expect(logger).to receive(:debug).with('Setting email preferences.') 17 | expect(browser).to receive(:text_field).with({:id => "ap_email"}) 18 | .and_return text_field 19 | expect(text_field).to receive(:when_present).and_return text_field 20 | expect(text_field).to receive(:set) 21 | 22 | expect(browser).to receive(:text_field).with({:id => "ap_password"}) 23 | .and_return text_field 24 | expect(text_field).to receive(:when_present).and_return text_field 25 | expect(text_field).to receive(:set) 26 | 27 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}) 28 | .and_return button 29 | expect(button).to receive(:when_present).and_return button 30 | expect(button).to receive(:click) 31 | 32 | expect(browser).to receive(:goto).with(url) 33 | expect(browser).to receive(:url) 34 | .and_return('https://www.amazon.com/ap/signin?') 35 | 36 | expect(logger).to receive(:debug).with('Logging into AWS.') 37 | 38 | expect(browser).to receive(:input) 39 | .with({:id => 'email_preferences_optout_all_true'}) 40 | .and_return input 41 | expect(input).to receive(:when_present).and_return input 42 | expect(input).to receive(:click) 43 | 44 | expect(browser).to receive(:input).with({:value => 'Save Changes'}) 45 | .and_return input 46 | expect(input).to receive(:when_present).and_return input 47 | expect(input).to receive(:click) 48 | 49 | expect(browser).to receive(:h3) 50 | .with({:text => /You have successfully updated your email preferences/}) 51 | .and_return h3 52 | expect(h3).to receive(:wait_until_present) 53 | 54 | expect(subject.opt_out('my_user', 'my_password')).to be_nil 55 | end 56 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/enterprise_support_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::EnterpriseSupport do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::EnterpriseSupport.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:span) { double 'browser span' } 9 | let(:p) { double 'browser element p' } 10 | let(:input) { double 'browser input' } 11 | let(:button) { double 'browser button' } 12 | let(:text_field) { double 'browser text field' } 13 | let(:url) { 'https://portal.aws.amazon.com/gp/aws/developer/registration/index.html' } 14 | let(:status_url) { 'https://console.aws.amazon.com/support/home' } 15 | confirmation_text = "Thank you for creating an Amazon Web Services (AWS) " 16 | confirmation_text << "Account. We are in the process of activating your " 17 | confirmation_text << "account. For most customers, activation only takes a " 18 | confirmation_text << "couple minutes, but it can sometimes take a few hours " 19 | confirmation_text << "if additional account verification is required. We will " 20 | confirmation_text << "notify you by email when your account is activated." 21 | 22 | before (:each) do 23 | expect(browser).to receive(:text_field).with({:id => "ap_email"}) 24 | .and_return text_field 25 | expect(text_field).to receive(:when_present).and_return text_field 26 | expect(text_field).to receive(:set) 27 | 28 | expect(browser).to receive(:text_field).with({:id => "ap_password"}) 29 | .and_return text_field 30 | expect(text_field).to receive(:when_present).and_return text_field 31 | expect(text_field).to receive(:set) 32 | 33 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}) 34 | .and_return button 35 | expect(button).to receive(:when_present).and_return button 36 | expect(button).to receive(:click) 37 | end 38 | 39 | it "should enable enterprise support" do 40 | expect(logger).to receive(:debug).with('Enabling enterprise support.') 41 | 42 | expect(browser).to receive(:goto).with(url) 43 | expect(browser).to receive(:url) 44 | .and_return('https://www.amazon.com/ap/signin?') 45 | 46 | expect(logger).to receive(:debug).with('Logging into AWS.') 47 | 48 | expect(browser).to receive(:input).with({:value => 'AWSSupportEnterprise'}) 49 | .and_return input 50 | expect(input).to receive(:when_present).and_return input 51 | expect(input).to receive(:click) 52 | 53 | expect(browser).to receive(:span).with({:text => /Continue/}) 54 | .and_return span 55 | expect(span).to receive(:when_present).with(60).and_return span 56 | expect(span).to receive(:click) 57 | 58 | expect(browser).to receive(:p) 59 | .with({:text => confirmation_text}) 60 | .and_return p 61 | expect(p).to receive(:wait_until_present) 62 | 63 | expect(subject.enable('my_user', 'my_password')).to be true 64 | end 65 | 66 | it 'should return true if enterprise support is enabled' do 67 | expect(logger).to receive(:debug).with('Checking to see if enterprise support is enabled.') 68 | 69 | expect(browser).to receive(:goto).with(status_url) 70 | expect(browser).to receive(:url) 71 | .and_return('https://www.amazon.com/ap/signin?') 72 | 73 | expect(logger).to receive(:debug).with('Logging into AWS.') 74 | 75 | expect(browser).to receive(:text).and_return browser 76 | expect(browser).to receive(:include?).with("Enterprise Support Plan").and_return true 77 | 78 | expect(subject.existing_support?('my_user', 'my_password')).to be true 79 | end 80 | 81 | it 'should return false if enterprise support is not enabled' do 82 | expect(logger).to receive(:debug).with('Checking to see if enterprise support is enabled.') 83 | 84 | expect(browser).to receive(:goto).with(status_url) 85 | expect(browser).to receive(:url) 86 | .and_return('https://www.amazon.com/ap/signin?') 87 | 88 | expect(logger).to receive(:debug).with('Logging into AWS.') 89 | 90 | expect(browser).to receive(:text).and_return browser 91 | expect(browser).to receive(:include?).with("Enterprise Support Plan").and_return false 92 | 93 | expect(subject.existing_support?('my_user', 'my_password')).to be false 94 | end 95 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/iam_billing_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::IamBilling do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::IamBilling.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:strong) { double 'browser strong' } 9 | let(:a) { double 'browser element a' } 10 | let(:input) { double 'browser input' } 11 | let(:label) { double 'browser label' } 12 | let(:button) { double 'browser button' } 13 | let(:text_field) { double 'browser text field' } 14 | let(:url) { 'https://portal.aws.amazon.com/gp/aws/manageYourAccount' } 15 | 16 | it "should create a url alias" do 17 | expect(logger).to receive(:debug).with('Enabling IAM User Access to Billing Information') 18 | expect(browser).to receive(:text_field).with({:id => "ap_email"}).and_return text_field 19 | expect(text_field).to receive(:when_present).and_return text_field 20 | expect(text_field).to receive(:set) 21 | 22 | expect(browser).to receive(:text_field).with({:id => "ap_password"}).and_return text_field 23 | expect(text_field).to receive(:when_present).and_return text_field 24 | expect(text_field).to receive(:set) 25 | 26 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}).and_return button 27 | expect(button).to receive(:when_present).and_return button 28 | expect(button).to receive(:click) 29 | 30 | expect(browser).to receive(:goto).with(url) 31 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 32 | expect(logger).to receive(:debug).with('Logging into AWS.') 33 | 34 | expect(browser).to receive(:a).with({:xpath => '//a[@ng-click="toggleEditingIAMPreferencesInfoState()"]'}).and_return a 35 | expect(a).to receive(:when_present).and_return a 36 | expect(a).to receive(:click) 37 | 38 | expect(browser).to receive(:label).with({:xpath => '//label[@ng-show="isEditingIAMPreferencesInfo"]'}).and_return label 39 | expect(label).to receive(:when_present).and_return label 40 | expect(label).to receive(:click) 41 | 42 | expect(browser).to receive(:button).with({:xpath => '//button[@ng-click="updateIAMPreferences()"]'}).and_return button 43 | expect(button).to receive(:when_present).and_return button 44 | expect(button).to receive(:click) 45 | 46 | expect(browser).to receive(:strong).with({:text => /IAM user access to billing information is activated./}).and_return strong 47 | expect(strong).to receive(:wait_until_present) 48 | 49 | expect(subject.enable('my_user', 'my_password')).to be_nil 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /spec/aws_account_utils/login_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::AccountRegistration do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::Login.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:strong) { double 'browser strong' } 9 | let(:a) { double 'browser element a' } 10 | let(:input) { double 'browser input' } 11 | let(:label) { double 'browser label' } 12 | let(:button) { double 'browser button' } 13 | let(:text_field) { double 'browser text field' } 14 | let(:url) { 'https://portal.aws.amazon.com/gp/aws/manageYourAccount' } 15 | 16 | it "should log into aws if presented with login page" do 17 | expect(browser).to receive(:text_field).with({:id => "ap_email"}) 18 | .and_return text_field 19 | expect(text_field).to receive(:when_present).and_return text_field 20 | expect(text_field).to receive(:set) 21 | 22 | expect(browser).to receive(:text_field).with({:id => "ap_password"}) 23 | .and_return text_field 24 | expect(text_field).to receive(:when_present).and_return text_field 25 | expect(text_field).to receive(:set) 26 | 27 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}) 28 | .and_return button 29 | expect(button).to receive(:when_present).and_return button 30 | expect(button).to receive(:click) 31 | 32 | expect(browser).to receive(:goto).with(url) 33 | expect(browser).to receive(:url) 34 | .and_return('https://www.amazon.com/ap/signin?') 35 | expect(logger).to receive(:debug).with('Logging into AWS.') 36 | 37 | expect(subject.execute(url, 'my_user', 'my_password')).to be_nil 38 | end 39 | 40 | it "should not attempt to log into aws if login page is not displayed" do 41 | expect(browser).to receive(:goto).with(url) 42 | expect(browser).to receive(:url).and_return(url) 43 | 44 | expect(subject.execute(url, 'my_user', 'my_password')).to be true 45 | end 46 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/logout_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::Logout do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::Logout.new logger, browser } 6 | let(:browser) { double 'browser' } 7 | let(:url) { 'https://console.aws.amazon.com/support/logout!doLogout' } 8 | 9 | it "should log out of aws console" do 10 | expect(logger).to receive(:debug).with('Logging out of AWS.') 11 | expect(browser).to receive(:goto).with(url) 12 | expect(browser).to receive(:wait_until).and_return browser 13 | expect(browser).to receive(:text).and_return browser 14 | expect(browser).to receive(:include?).with("Sign In to the Console").and_return true 15 | 16 | expect(subject.execute).to be true 17 | end 18 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/password_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::Password do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::Password.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:h1) { double 'browser element h1' } 9 | let(:h6) { double 'browser element h6' } 10 | let(:div) { double 'browser div' } 11 | let(:button) { double 'browser button' } 12 | let(:text_field) { double 'browser text field' } 13 | let(:error_header) { "There was a problem with your request" } 14 | let(:error_body) { "invalid password" } 15 | let(:url) { url = "https://www.amazon.com/ap/cnep?_encoding=UTF8" 16 | url<< "&openid.assoc_handle=aws" 17 | url<< "&openid.return_to=https%3A%2F%2Fconsole.aws.amazon.com%2Fbilling%2Fhome%23%2Faccount" 18 | url<< "&openid.mode=id_res&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0" 19 | url<< "&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" 20 | url<< "&openid.pape.max_auth_age=600" 21 | url<< "&openid.pape.preferred_auth_policies=http%3A%2F%2Fschemas.openid.net%2Fpape%2Fpolicies%2F2007%2F06%2Fmulti-factor-physical" 22 | url<< "&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0" 23 | url<< "&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" } 24 | 25 | it "should change the master account password" do 26 | expect(logger).to receive(:debug).with('Changing root password.') 27 | expect(browser).to receive(:text_field).with({:id => "ap_email"}).and_return text_field 28 | expect(text_field).to receive(:when_present).and_return text_field 29 | expect(text_field).to receive(:set) 30 | 31 | expect(browser).to receive(:text_field).with({:id => "ap_password"}).and_return text_field 32 | expect(text_field).to receive(:when_present).and_return text_field 33 | expect(text_field).to receive(:set) 34 | 35 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}).and_return button 36 | expect(button).to receive(:when_present).and_return button 37 | expect(button).to receive(:click) 38 | 39 | expect(browser).to receive(:goto).with(url) 40 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 41 | expect(logger).to receive(:debug).with('Logging into AWS.') 42 | 43 | expect(browser).to receive(:h1).with({:text => /Change Name, E-mail Address, or Password/}).and_return h1 44 | expect(h1).to receive(:wait_until_present) 45 | 46 | expect(browser).to receive(:button).with({:id => 'cnep_1A_change_password_button-input'}).and_return button 47 | expect(button).to receive(:when_present).and_return button 48 | expect(button).to receive(:click) 49 | 50 | expect(browser).to receive(:text_field).with({:id => "ap_password"}).and_return text_field 51 | expect(text_field).to receive(:when_present).and_return text_field 52 | expect(text_field).to receive(:set) 53 | 54 | expect(browser).to receive(:text_field).with({:id => "ap_password_new"}).and_return text_field 55 | expect(text_field).to receive(:when_present).and_return text_field 56 | expect(text_field).to receive(:set) 57 | 58 | expect(browser).to receive(:text_field).with({:id => "ap_password_new_check"}).and_return text_field 59 | expect(text_field).to receive(:when_present).and_return text_field 60 | expect(text_field).to receive(:set) 61 | 62 | expect(browser).to receive(:button).with({:id => "cnep_1D_submit_button-input"}).and_return button 63 | expect(button).to receive(:when_present).and_return button 64 | expect(button).to receive(:click) 65 | 66 | expect(browser).to receive(:div).with({:id=>/message_(error|warning)/}).and_return div 67 | expect(div).to receive(:exist?).and_return false 68 | 69 | expect(browser).to receive(:h6).with({:text => /Success/}).and_return h6 70 | expect(h6).to receive(:exist?).and_return true 71 | 72 | expect(subject.change('my_user', 'my_old_password', 'my_new_password')).to be true 73 | end 74 | 75 | it "should change the master account password" do 76 | expect(logger).to receive(:debug).with('Changing root password.') 77 | expect(browser).to receive(:text_field).with({:id => "ap_email"}).and_return text_field 78 | expect(text_field).to receive(:when_present).and_return text_field 79 | expect(text_field).to receive(:set) 80 | 81 | expect(browser).to receive(:text_field).with({:id => "ap_password"}).and_return text_field 82 | expect(text_field).to receive(:when_present).and_return text_field 83 | expect(text_field).to receive(:set) 84 | 85 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}).and_return button 86 | expect(button).to receive(:when_present).and_return button 87 | expect(button).to receive(:click) 88 | 89 | expect(browser).to receive(:goto).with(url) 90 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 91 | expect(logger).to receive(:debug).with('Logging into AWS.') 92 | 93 | expect(browser).to receive(:h1).with({:text => /Change Name, E-mail Address, or Password/}).and_return h1 94 | expect(h1).to receive(:wait_until_present) 95 | 96 | expect(browser).to receive(:button).with({:id => 'cnep_1A_change_password_button-input'}).and_return button 97 | expect(button).to receive(:when_present).and_return button 98 | expect(button).to receive(:click) 99 | 100 | expect(browser).to receive(:text_field).with({:id => "ap_password"}).and_return text_field 101 | expect(text_field).to receive(:when_present).and_return text_field 102 | expect(text_field).to receive(:set) 103 | 104 | expect(browser).to receive(:text_field).with({:id => "ap_password_new"}).and_return text_field 105 | expect(text_field).to receive(:when_present).and_return text_field 106 | expect(text_field).to receive(:set) 107 | 108 | expect(browser).to receive(:text_field).with({:id => "ap_password_new_check"}).and_return text_field 109 | expect(text_field).to receive(:when_present).and_return text_field 110 | expect(text_field).to receive(:set) 111 | 112 | expect(browser).to receive(:button).with({:id => "cnep_1D_submit_button-input"}).and_return button 113 | expect(button).to receive(:when_present).and_return button 114 | expect(button).to receive(:click) 115 | 116 | expect(browser).to receive(:div).with(:id => /message_(error|warning)/) 117 | .and_return(browser) 118 | expect(browser).to receive(:exist?).and_return(true) 119 | expect(subject).to receive(:screenshot).with(browser, "1") 120 | expect(subject).to receive(:screenshot).with(browser, "2") 121 | expect(subject).to receive(:screenshot).with(browser, "3") 122 | expect(subject).to receive(:screenshot).with(browser, "error") 123 | expect(browser).to receive(:div).with(:id => /message_(error|warning)/) 124 | .and_return(browser) 125 | expect(browser).to receive(:h6).and_return(browser) 126 | expect(browser).to receive(:text).and_return(error_header) 127 | expect(browser).to receive(:div).with(:id => /message_(error|warning)/) 128 | .and_return(browser) 129 | expect(browser).to receive(:p).and_return(browser) 130 | expect(browser).to receive(:text).and_return(error_body) 131 | 132 | expect{subject.change('my_user', 'my_old_password', 'my_new_password')} 133 | .to raise_error(StandardError, 134 | "AWS Password Change Error: \"#{error_header}: #{error_body}\"") 135 | end 136 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/root_access_keys_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe AwsAccountUtils::RootAccessKeys do 4 | let(:logger) { Logger.new(STDOUT) } 5 | let(:subject) { AwsAccountUtils::RootAccessKeys.new logger, browser } 6 | let(:login) { AwsAccountUtils::Login.new logger, browser } 7 | let(:browser) { double 'browser' } 8 | let(:label) { double 'browser label' } 9 | let(:div) { double 'browser div' } 10 | let(:element) { double 'browser element' } 11 | let(:i) { double 'browser i' } 12 | let(:a) { double 'browser a' } 13 | let(:button) { double 'browser button' } 14 | let(:text_field) { double 'browser text field' } 15 | let(:warning_text) { 'You are accessing the security credentials page for your AWS account. The account credentials provide unlimited access to your AWS resources.'} 16 | let(:url) { 'https://console.aws.amazon.com/iam/home?#security_credential' } 17 | 18 | it "should create secret/access keys" do 19 | expect(logger).to receive(:debug).with('Creating root access/secret key') 20 | expect(browser).to receive(:text_field).with({:id => "ap_email"}) 21 | .and_return text_field 22 | expect(text_field).to receive(:when_present).and_return text_field 23 | expect(text_field).to receive(:set) 24 | 25 | expect(browser).to receive(:text_field).with({:id => "ap_password"}) 26 | .and_return text_field 27 | expect(text_field).to receive(:when_present).and_return text_field 28 | expect(text_field).to receive(:set) 29 | 30 | expect(browser).to receive(:button).with({:id => "signInSubmit-input"}) 31 | .and_return button 32 | expect(button).to receive(:when_present).and_return button 33 | expect(button).to receive(:click) 34 | 35 | expect(browser).to receive(:goto).with(url) 36 | expect(browser).to receive(:url).and_return('https://www.amazon.com/ap/signin?') 37 | expect(logger).to receive(:debug).with('Logging into AWS.') 38 | 39 | expect(browser).to receive(:div) 40 | .with({:id => 'modal-content', :text => warning_text}) 41 | .and_return label 42 | expect(label).to receive(:wait_until_present) 43 | 44 | expect(browser).to receive(:label) 45 | .with({:text => /Don't show me this message again/}).and_return label 46 | 47 | expect(browser).to receive(:element).with({:id => 'continue'}).and_return element 48 | expect(element).to receive(:when_present).and_return element 49 | expect(element).to receive(:click) 50 | 51 | expect(browser).to receive(:i) 52 | .with({:xpath => "id('credaccordion')/div[3]/div[1]/div/div[1]/i"}) 53 | .and_return i 54 | expect(i).to receive(:when_present).and_return i 55 | expect(i).to receive(:click) 56 | 57 | expect(browser).to receive(:button).with({:text => /Create New Access Key/}) 58 | .and_return button 59 | expect(button).to receive(:when_present).and_return button 60 | expect(button).to receive(:click) 61 | 62 | expect(browser).to receive(:a).with({:text => /Show Access Key/}).and_return a 63 | expect(a).to receive(:when_present).and_return a 64 | expect(a).to receive(:click) 65 | 66 | expect(browser).to receive(:text) 67 | .and_return "my_access_key\n\nmy_secret_key\nA bunch of words\n" 68 | 69 | expect(subject.create('my_user', 'my_password')) 70 | .to eq({:access_key=>"my_access_key", :secret_key=>"my_secret_key"}) 71 | end 72 | end -------------------------------------------------------------------------------- /spec/aws_account_utils/watir_browser_spec.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intuit/aws_account_utils/dfd2f8d73d12078365d6d7bd987105bb69cb65c0/spec/aws_account_utils/watir_browser_spec.rb -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'simplecov' 4 | require 'webmock/rspec' 5 | require 'coveralls' 6 | Coveralls.wear! 7 | 8 | WebMock.disable_net_connect!(allow_localhost: true) 9 | 10 | SimpleCov.start do 11 | add_filter "/spec/" 12 | end 13 | 14 | Dir[File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "**", '*.rb'))].each {|f| require f} 15 | --------------------------------------------------------------------------------