Class: Setup
- Inherits:
-
Object
- Object
- Setup
- Defined in:
- lib/cht/aws.rb,
lib/cht/output.rb,
lib/cht/policy.rb,
lib/cht/mechanize.rb,
lib/cloudhealth-setup.rb,
lib/cht/error_handling.rb
Constant Summary collapse
- AWS_LOGIN_URL =
'https://www.amazon.com/ap/signin?openid.assoc_handle=aws&openid.return_to=https%3A%2F%2Fportal.aws.amazon.com%2Fgp%2Faws%2Fdeveloper%2Faccount%2Findex.html%3Fie%3DUTF8%26action%3Dactivity-summary&openid.mode=checkid_setup&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select&action=&disableCorpSignUp=&clientContext=&marketPlaceId=&poolName=&authCookies=&pageId=aws.ssop&siteState=&accountStatusPolicy=&sso=&openid.pape.preferred_auth_policies=MultifactorPhysical&openid.pape.max_auth_age=3600&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&server=%2Fap%2Fsignin%3Fie%3DUTF8&accountPoolAlias='
Instance Attribute Summary collapse
-
#account_name ⇒ Object
Returns the value of attribute account_name.
-
#aws_account_id ⇒ Object
Returns the value of attribute aws_account_id.
-
#aws_acct_alias ⇒ Object
Returns the value of attribute aws_acct_alias.
-
#aws_key ⇒ Object
Returns the value of attribute aws_key.
-
#aws_pass ⇒ Object
Returns the value of attribute aws_pass.
-
#aws_ro_name ⇒ Object
Returns the value of attribute aws_ro_name.
-
#aws_secret ⇒ Object
Returns the value of attribute aws_secret.
-
#aws_url ⇒ Object
Returns the value of attribute aws_url.
-
#aws_user ⇒ Object
Returns the value of attribute aws_user.
-
#input_file ⇒ Object
Returns the value of attribute input_file.
-
#output_file ⇒ Object
Returns the value of attribute output_file.
-
#setup_bucket ⇒ Object
Returns the value of attribute setup_bucket.
Class Method Summary collapse
Instance Method Summary collapse
- #account_consolidated ⇒ Object
- #aws_ro_policy ⇒ Object
- #bucket_has_policy ⇒ Object
- #bucket_policy ⇒ Object
- #check_iam_credentials ⇒ Object
- #check_web_credentials ⇒ Object
- #create_user_password ⇒ Object
- #critical_failure(message) ⇒ Object
- #dump_page(page) ⇒ Object
- #ensure_options(input) ⇒ Object
- #get_page ⇒ Object
- #iam ⇒ Object
-
#initialize(options) ⇒ Setup
constructor
A new instance of Setup.
- #mech_browser ⇒ Object
- #response ⇒ Object
- #s3 ⇒ Object
- #setup_account_alias ⇒ Object
- #setup_checkboxes ⇒ Object
- #setup_cost_alloc ⇒ Object
- #setup_detailed_billing ⇒ Object
- #setup_monthly_report ⇒ Object
- #setup_prog_access ⇒ Object
- #setup_ro_user ⇒ Object
- #setup_s3_bucket ⇒ Object
- #test_account_alias ⇒ Object
- #test_checkboxes ⇒ Object
- #test_consolidated ⇒ Object
- #test_cost_alloc ⇒ Object
- #test_detailed_billing ⇒ Object
- #test_monthly_report ⇒ Object
- #test_prog_access ⇒ Object
- #test_ro_user ⇒ Object
- #test_s3_bucket ⇒ Object
- #uninstall_ro_user ⇒ Object
- #user_exists ⇒ Object
- #user_has_policy ⇒ Object
- #warning(e) ⇒ Object
Constructor Details
#initialize(options) ⇒ Setup
Returns a new instance of Setup.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/cloudhealth-setup.rb', line 128 def initialize() manual_input = () .merge!(manual_input) @aws_key = [:aws_key] @aws_secret = [:aws_secret] @output_file = [:output_file] @input_file = [:input_file] @aws_user = [:aws_user] @aws_pass = [:aws_pass] @setup_bucket = [:setup_bucket] @aws_ro_name = [:aws_ro_name] @aws_acct_alias = [:aws_acct_alias] @aws_account_id = nil @verbose = [:verbose] @overwrite_file = [:overwrite_file] @ro_user_exists = [:ro_user_exists] @mfa = [:multi_factor_code] || nil @created_account = {} @iam = iam @s3 = s3 @browser = mech_browser @mode = ARGV[0] end |
Instance Attribute Details
#account_name ⇒ Object
Returns the value of attribute account_name.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def account_name @account_name end |
#aws_account_id ⇒ Object
Returns the value of attribute aws_account_id.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_account_id @aws_account_id end |
#aws_acct_alias ⇒ Object
Returns the value of attribute aws_acct_alias.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_acct_alias @aws_acct_alias end |
#aws_key ⇒ Object
Returns the value of attribute aws_key.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_key @aws_key end |
#aws_pass ⇒ Object
Returns the value of attribute aws_pass.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_pass @aws_pass end |
#aws_ro_name ⇒ Object
Returns the value of attribute aws_ro_name.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_ro_name @aws_ro_name end |
#aws_secret ⇒ Object
Returns the value of attribute aws_secret.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_secret @aws_secret end |
#aws_url ⇒ Object
Returns the value of attribute aws_url.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_url @aws_url end |
#aws_user ⇒ Object
Returns the value of attribute aws_user.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def aws_user @aws_user end |
#input_file ⇒ Object
Returns the value of attribute input_file.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def input_file @input_file end |
#output_file ⇒ Object
Returns the value of attribute output_file.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def output_file @output_file end |
#setup_bucket ⇒ Object
Returns the value of attribute setup_bucket.
126 127 128 |
# File 'lib/cloudhealth-setup.rb', line 126 def setup_bucket @setup_bucket end |
Class Method Details
.run ⇒ Object
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
# File 'lib/cloudhealth-setup.rb', line 196 def self.run cli = MyCLI.new cli. = "Usage: cloudhealth-setup test|install|uninstall (options)" cli. accounts_to_setup = [] accounts_processed = [] if ARGV[0].nil? puts cli.opt_parser exit end if cli.config[:input_file] puts "Starting CloudHealth setup in multi-account setup mode, using input file #{cli.config[:input_file]}" accounts_to_setup << CsvImport.import_file(cli.config[:input_file]) else puts "Starting CloudHealth setup in single account mode." accounts_to_setup << cli.config end accounts_to_setup.each do || new_account = Setup.new() case ARGV[0] when "install" new_account.check_iam_credentials new_account.check_web_credentials new_account.setup_monthly_report new_account.setup_s3_bucket new_account.setup_prog_access new_account.setup_detailed_billing new_account.setup_cost_alloc new_account.setup_checkboxes new_account.setup_ro_user new_account.setup_account_alias new_account.account_consolidated accounts_processed << new_account.response when "test" new_account.test_monthly_report new_account.test_s3_bucket new_account.test_prog_access new_account.test_detailed_billing new_account.test_cost_alloc new_account.test_checkboxes new_account.test_ro_user new_account.test_account_alias new_account.test_consolidated when "uninstall" new_account.uninstall_ro_user else puts cli.opt_parser end end Setup.write_csv(accounts_processed, cli.config[:output_file]) if ARGV[0] == "install" end |
.write_csv(accounts, filename) ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/cht/output.rb', line 2 def self.write_csv(accounts, filename) file_exists = File.exists?(filename) mode = if file_exists if @overwrite_file puts "CSV Output file #{filename} exists! Overwriting the file per --overwrite." "wb" else puts "CSV Output file #{filename} exists! Appending to existing file." "ab" end else "wb" end count = 0 CSV.open(filename, mode) do |csv| unless mode == "ab" csv << ["Account ID", "Console URL", "IAM Username", "IAM Password", "AWS Access Key", "AWS Access Secret", "S3 Bucket", "Is Consolidated?"] end accounts.each do |account| count += 1 csv << [account[:account_id], account[:account_url], account[:user], account[:user_pass], account[:access_key], account[:secret_key], account[:s3_bucket], account[:consolidated]] end end puts "Finished setting up #{count} account(s). CSV File path: #{filename}" end |
Instance Method Details
#account_consolidated ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/cht/mechanize.rb', line 107 def account_consolidated page = @browser.get("https://portal.aws.amazon.com/gp/aws/developer/account?ie=UTF8&action=consolidated-billing") consolidated_link = page.link_with(:href => "https://portal.aws.amazon.com/gp/aws/developer/subscription/index.html?ie=UTF8&productCode=AWSCBill") if consolidated_link.nil? @created_account.merge!(:consolidated => true) puts "Account is on consolidated billing" else #We must be on consolidated billing @created_account.merge!(:consolidated => false) puts "Account is not on consolidated billing" end end |
#aws_ro_policy ⇒ Object
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/cht/policy.rb', line 45 def aws_ro_policy { "Statement" => [ { "Effect" => "Allow", "Action" => [ "aws-portal:ViewBilling", "aws-portal:ViewUsage", "autoscaling:Describe*", "cloudformation:ListStacks", "cloudformation:ListStackResources", "cloudformation:DescribeStacks", "cloudformation:DescribeStackEvents", "cloudformation:DescribeStackResources", "cloudformation:GetTemplate", "cloudfront:Get*", "cloudfront:List*", "cloudwatch:Describe*", "cloudwatch:Get*", "cloudwatch:List*", "dynamodb:DescribeTable", "dynamodb:ListTables", "ec2:Describe*", "elasticache:Describe*", "elasticbeanstalk:Check*", "elasticbeanstalk:Describe*", "elasticbeanstalk:List*", "elasticbeanstalk:RequestEnvironmentInfo", "elasticbeanstalk:RetrieveEnvironmentInfo", "elasticloadbalancing:Describe*", "elasticmapreduce:Describe*", "iam:List*", "iam:Get*", "redshift:Describe*", "route53:Get*", "route53:List*", "rds:Describe*", "rds:ListTagsForResource", "s3:List*", "sdb:GetAttributes", "sdb:List*", "sdb:Select*", "ses:Get*", "ses:List*", "sns:Get*", "sns:List*", "sqs:GetQueueAttributes", "sqs:ListQueues", "sqs:ReceiveMessage", "storagegateway:List*", "storagegateway:Describe*" ], "Resource" => "*" }, { "Effect" => "Allow", "Action" => [ "s3:Get*","s3:List*" ], "Resource" => [ "arn:aws:s3:::#{@setup_bucket}", "arn:aws:s3:::#{@setup_bucket}/*" ] } ] } end |
#bucket_has_policy ⇒ Object
2 3 4 5 6 7 8 9 |
# File 'lib/cht/policy.rb', line 2 def bucket_has_policy begin @s3.get_bucket_policy(@setup_bucket) true rescue false end end |
#bucket_policy ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/cht/policy.rb', line 20 def bucket_policy { "Version" => "2008-10-17", "Id" => "Policy1335892530063", "Statement" => [ { "Sid" => "Stmt1335892150622", "Effect" => "Allow", "Principal" => { "AWS" => "arn:aws:iam::386209384616:root" }, "Action" => ["s3:GetBucketAcl", "s3:GetBucketPolicy"], "Resource" => "arn:aws:s3:::#{@setup_bucket}" }, { "Sid" => "Stmt1335892526596", "Effect" => "Allow", "Principal" => { "AWS" => "arn:aws:iam::386209384616:root" }, "Action" => ["s3:PutObject"], "Resource" => "arn:aws:s3:::#{@setup_bucket}/*" } ] } end |
#check_iam_credentials ⇒ Object
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/cht/aws.rb', line 21 def check_iam_credentials puts "Please wait, ensuring the provided credentials work." begin @iam.list_users rescue => e if @input_file.nil? || @input_file.empty? # Single account mode puts "Could not login to your account with the provided Amazon Web Services credentials. Please check your AWS Access Key and Secret Access Key and try again. If issue persists contact [email protected]." exit else # Multi account mode raise SetupFailed, "Could not login to your account with the provided Amazon Web Services credentials. Please check your AWS Access Key and Secret Access Key and try again. If issue persists contact [email protected]." end end end |
#check_web_credentials ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/cht/mechanize.rb', line 81 def check_web_credentials get_page get_page # We run this twice, only on the second login do we find our account id on the initial page. This primes the pump so to speak anyway for subsequent usage. TODO: Fix me if @aws_account_id.nil? || @aws_account_id.empty? if @input_file.nil? || @input_file.empty? # Single account mode puts "Could not login to your account with the provided Amazon Web Services credentials. Please check your provided email address and password and try again. If issue persists contact [email protected]." exit else # Multi account mode raise SetupFailed, "Could not login to your account with the provided Amazon Web Services credentials. Please check your provided email address and password and try again. If issue persists contact [email protected]." end end end |
#create_user_password ⇒ Object
259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/cht/aws.rb', line 259 def create_user_password puts " Setting user password" pw = SecureRandom.hex begin @iam.create_login_profile(@aws_ro_name, pw) rescue => e if e.response.status == 409 puts " User already had a password set..." else raise e end end pw end |
#critical_failure(message) ⇒ Object
5 6 7 8 |
# File 'lib/cht/error_handling.rb', line 5 def critical_failure() puts #raise SetupFailed, message end |
#dump_page(page) ⇒ Object
120 121 122 123 124 125 126 |
# File 'lib/cht/mechanize.rb', line 120 def dump_page(page) no = rand(500) puts "Writing out page as #{no}.html" File.open("#{no}.html", 'w') do |file| file << page.body end end |
#ensure_options(input) ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/cloudhealth-setup.rb', line 152 def (input) # If things dont exist in the options that are required, or required in a combination. output_opts = {} if input[:aws_key].nil? output_opts[:aws_key] = ask("Input AWS Key: ") do |q| q.responses[:not_valid] = "You must enter a 20 char AWS Access Key ID" q.responses[:invalid_type] = "You must enter a 20 char AWS Access Key ID" q.validate = lambda {|p| p.length == 20 } end end if input[:aws_secret].nil? output_opts[:aws_secret] = ask("Input AWS Secret: ") do |q| q.responses[:not_valid] = "You must enter a 40 char AWS Access Secret Key" q.responses[:invalid_type] = "You must enter a 40 char AWS Access Secret Key" q.validate = lambda {|p| p.length == 40 } end end if input[:aws_user].nil? output_opts[:aws_user] = ask("Input AWS Email/Username: ") do |q| q.responses[:not_valid] = "You must enter a valid Email/Username" q.responses[:invalid_type] = "You must enter a valid Email/Username" q.validate = lambda {|p| p.length > 5 } end end if input[:aws_pass].nil? output_opts[:aws_pass] = ask("Input AWS Password: ") do |q| q.responses[:not_valid] = "You must enter a valid password" q.responses[:invalid_type] = "You must enter a valid password" q.validate = lambda {|p| p.length > 4 } end end if input[:setup_bucket].nil? output_opts[:setup_bucket] = ask("Input S3 Bucket name for billing: ") end output_opts end |
#get_page ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/cht/mechanize.rb', line 16 def get_page begin url = AWS_LOGIN_URL page = @browser.get(url) signed_in = page.link_with(:text => "Sign Out") if signed_in.nil? # Since @browser is shared, sometimes we are already logged in. form = page.form_with(:name => 'signIn') form['email'] = @aws_user form['password'] = @aws_pass login_page = form.submit if login_page.code.to_i != 200 puts "The login page returned error code #{login_page.code}" raise SetupFailed, " Could not login to AWS Web Console, Amazon may be experiencing issues or the credentials you provided are incorrect. HTTP Code: #{login_page.code}" end # A Captcha can be present if they failed to login too many times, Lets detect it here. captcha_form = login_page.form_with(:id => 'ap_signin_form') unless captcha_form.nil? captcha_on = captcha_form.field_with(:id => 'ap_captcha_guess') unless captcha_on.nil? raise SetupFailed, " Your account currently has a captcha on the login screen, This is most likely due to failed logins. Please login to your account at http://aws.amazon.com/ to stop the Captcha and then retry cloudhealth-setup." end end mfa_form = login_page.form_with(:id => 'ap_signin_form') unless mfa_form.nil? if @mfa.nil? @mfa = ask("Multi-Factor Authentication detected, please enter 6 digit pin: ") do |q| q.responses[:not_valid] = "You must enter a 6 digit MFA pin." q.responses[:invalid_type] = "You must enter a 6 digit MFA pin." q.validate = lambda {|p| p.length == 6 } end end mfa_form['tokenCode'] = @mfa mfa_form.submit end end account_id_search = page.search('//span[@class="txtxxsm"]/text()') unless account_id_search.nil? || account_id_search.size == 0 || @created_account[:account_id] firstw, secondw, account_id_long = account_id_search.first.content.strip.split(" ") account_id = account_id_long.gsub("-","") puts " Account ID for this account is: #{account_id.to_s}" if @verbose @aws_account_id = account_id @created_account.merge!(:account_id => account_id) end page = @browser.get("https://portal.aws.amazon.com/gp/aws/developer/account?ie=UTF8&action=billing-preferences") if page.code.to_i != 200 raise SetupFailed, " Could not login to AWS Web Console, Amazon may be experiencing issues or the credentials you provided are incorrect. HTTP Code: #{page.code}" end page rescue => e #TODO: Fix when multi input account works #raise SetupFailed, e puts e exit end end |
#iam ⇒ Object
5 6 7 8 9 10 11 |
# File 'lib/cht/aws.rb', line 5 def iam begin Fog::AWS::IAM.new({:aws_access_key_id => @aws_key, :aws_secret_access_key => @aws_secret}) rescue => e critical_failure("Failed to connect to Amazon AWS IAM: Please ensure your provided credentials are correct and you have internet access. #{e if @verbose}") end end |
#mech_browser ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 |
# File 'lib/cht/mechanize.rb', line 4 def mech_browser # Creating Mechanize object browser = Mechanize.new browser.verify_mode = OpenSSL::SSL::VERIFY_NONE browser.redirect_ok = true # Let's give some header here browser.request_headers['User-Agent'] = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4' browser.request_headers['Accept'] = 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' browser.request_headers['application/xml'] = '*/*' browser end |
#response ⇒ Object
29 30 31 |
# File 'lib/cht/output.rb', line 29 def response @created_account end |
#s3 ⇒ Object
13 14 15 16 17 18 19 |
# File 'lib/cht/aws.rb', line 13 def s3 begin Fog::Storage.new({:provider => 'AWS', :aws_access_key_id => @aws_key, :aws_secret_access_key => @aws_secret}) rescue => e critical_failure("Failed to connect to Amazon AWS S3: Please ensure your provided credentials are correct and you have internet access. #{e if @verbose}") end end |
#setup_account_alias ⇒ Object
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 |
# File 'lib/cht/aws.rb', line 229 def setup_account_alias begin if @aws_acct_alias.nil? puts "AWS account alias not given, will use account id: #{@created_account[:account_id]} -- Skipping alias setup." @created_account.merge!(:account_alias => @created_account[:account_id], :account_url => "https://#{@created_account[:account_id]}.signin.aws.amazon.com/") else puts "Setting up account alias... " begin @iam.create_account_alias(@aws_acct_alias) puts " alias set to #{@aws_acct_alias}..." rescue => e if e.class == Fog::AWS::IAM::EntityAlreadyExists puts " Account alias was already set." elsif e.response.status == 409 puts " Account alias was already set." else raise e end end @created_account.merge!(:account_alias => @aws_acct_alias, :account_url => "https://#{@aws_acct_alias}.signin.aws.amazon.com/") end rescue => e puts " We were unable to create an account alias." puts " Please contact CloudHealth support at [email protected]" warning(e) end end |
#setup_checkboxes ⇒ Object
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 |
# File 'lib/cht/mechanize.rb', line 369 def setup_checkboxes checkbox_setup_error = " We were unable to enable account activity & usage reports.\n This setting can be enabled manually under the Manage Your Account from the AWS account page." begin puts "Enabling account activity & usage reports..." page = @browser.get("https://portal.aws.amazon.com/gp/aws/manageYourAccount?action=updateIAMUserAccess&activateaa=1&activateur=1") json = JSON.parse(page.body) if json["error"] != "0" puts checkbox_setup_error else puts " Activity & Usage reports enabled." end rescue => e puts checkbox_setup_error warning(e) end end |
#setup_cost_alloc ⇒ Object
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 |
# File 'lib/cht/mechanize.rb', line 287 def setup_cost_alloc begin puts "Setting up cost allocation report... " page = get_page cost_alloc_form = page.form_with(:name=>'carOptInForm') car_enabled = cost_alloc_form.field_with(:name => "buttonOptionCAR") if car_enabled.value == "EnableCAR" puts " Enabling cost allocation report... " cost_alloc_form.submit elsif car_enabled.value == "DisableCAR" puts " Report already enabled... " end puts " Report setup finished" rescue => e puts " We were unable to enable cost allocation reports." puts " This setting can be enabled manually under Billing Preferences from the AWS account page." warning(e) end end |
#setup_detailed_billing ⇒ Object
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/cht/mechanize.rb', line 234 def setup_detailed_billing begin puts "Setting up detailed billing report..." page = get_page # This is the regular detailed billing report detailed_billing_form = page.form_with(:name=>'hourlyOptInForm') bill_enabled = detailed_billing_form.field_with(:name => "buttonOptionHourly") # This is the detailed billing report with tags and resources detailed_billing_tag_form = page.form_with(:name => 'hourlyWithResourcesAndTagsOptInForm') tag_bill_enabled = detailed_billing_tag_form.field_with(:name => "buttonOptionHourlyWithResourcesAndTags") if bill_enabled.value == "EnableHourly" puts " Enabling detailed billing report... " detailed_billing_form.submit elsif bill_enabled.value == "DisableHourly" puts " Detailed report already enabled... " end if tag_bill_enabled.value == "EnableHourlyWithResourcesAndTags" puts " Enabling detailed billing report w/ tags & resources... " detailed_billing_tag_form.submit elsif tag_bill_enabled.value == "DisableHourlyWithResourcesAndTags" puts " Detailed report w/ resources & tags already enabled... " end puts " Report setup finished" rescue => e puts " we were unable to enable detailed billing reports." puts " This setting can be enabled manually under Billing Preferences from the AWS account page." warning(e) end end |
#setup_monthly_report ⇒ Object
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/cht/mechanize.rb', line 146 def setup_monthly_report begin puts "Setting up monthly report access... " page = get_page monthly_report_form = page.form_with(:name => "csvReportOptInForm") mrf_enabled = monthly_report_form.field_with(:name => "buttonOption") if mrf_enabled.value == "EnableCSVReport" puts " Report not enabled, enabling... " monthly_report_form.submit elsif mrf_enabled.value == "CancelCSVReport" puts " Report already enabled... " end puts " Monthly report access setup complete." rescue => e puts " We were unable to setup monthly report access." puts " This setting can be enabled manually under Billing Preferences from the AWS Account page." warning(e) end end |
#setup_prog_access ⇒ Object
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/cht/mechanize.rb', line 185 def setup_prog_access begin puts "Setting up programmatic access to billing... " page = get_page prog_access_form = page.form_with(:name => "paOptInForm") paf_enabled = prog_access_form.field_with(:name => "existingS3BucketName") if paf_enabled.nil? puts " Enabling access in bucket #{@setup_bucket}... " prog_access_form['s3BucketName'] = @setup_bucket prog_access_form.submit else puts " Access already enabled..." end puts " Setup of programmatic access to billing finished" rescue => e puts " We were unable to setup programmatic access to your billing information." puts " You can manually enable this by following these instructions: http://docs.aws.amazon.com/awsaccountbilling/latest/about/programaccess.html" warning(e) end end |
#setup_ro_user ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/cht/aws.rb', line 107 def setup_ro_user user_created = nil begin puts "Setting up AWS Read only user... " if @aws_ro_name.nil? puts " Name not specified -- Skipping." else if user_exists if @ro_user_exists puts " User #{@aws_ro_name} exists... continuing due to --user-exists" puts " Note: CSV Output file will NOT be complete. Since we did not create the aws read only user" puts " You must fill in the blanks of the CSV if you plan on importing the CSV on the website." else #TODO This should not exit() in multi-account import mode, it should be raised up and caught. e.g. SetupFailed puts "User #{@aws_ro_name} exists already, If this was your intention please re-run with --user-exists and ensure you update the CSV manually or choose another username via -r <name>" exit end else puts " Creating user... " user_create = @iam.create_user(@aws_ro_name) key_create = @iam.create_access_key('UserName' => @aws_ro_name) access_key = key_create.body['AccessKey']['AccessKeyId'] secret_key = key_create.body['AccessKey']['SecretAccessKey'] arn = user_create.body['User']['Arn'] user_pass = create_user_password @created_account.merge!(:access_key => access_key, :secret_key => secret_key, :user_pass => user_pass, :user => @aws_ro_name) user_created = " The user #{@aws_ro_name} has been created with password #{user_pass}, access key #{access_key}, and secret key #{secret_key}" end if user_has_policy puts " User policy already exists..." else puts " Creating user policy... " @iam.put_user_policy(@aws_ro_name, "CHTRoPolicy", aws_ro_policy) end puts user_created unless user_created.nil? puts " Setup of AWS Read only user completed" end rescue => e puts " We were unable to create a read only user." puts " Please contact CloudHealth support at [email protected]." warning(e) end end |
#setup_s3_bucket ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/cht/aws.rb', line 172 def setup_s3_bucket begin puts "Setting up S3 billing bucket... " if @s3.directories.collect{|d| d.key}.include?(@setup_bucket) puts " Bucket exists..." else puts " Creating bucket... " begin @s3.directories.create(:key => @setup_bucket, :public => false) rescue => e if e.response.status == 409 puts " The bucket you are trying to use is already created, but owned by another account. Please use another bucket name." else raise e end end end if bucket_has_policy puts " Bucket already has policy... " else puts " Creating bucket policy..." @s3.put_bucket_policy(@setup_bucket, bucket_policy) end @created_account.merge!(:s3_bucket => @setup_bucket) puts " Bucket setup finished" rescue => e puts " We were unable to setup an S3 billing bucket. You can manually enable this," puts " by following these instructions: http://docs.aws.amazon.com/awsaccountbilling/latest/about/programaccess.html" warning(e) end end |
#test_account_alias ⇒ Object
214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/cht/aws.rb', line 214 def test_account_alias begin acct_aliases = @iam.list_account_aliases.body['AccountAliases'] if acct_aliases.empty? puts "[ ] AWS Account alias is not setup, Account ID: #{@aws_account_id} used instead -- Not setup" else puts "[X] AWS Account alias(es) are setup (#{acct_aliases.map{|aa| aa.strip}.join(', ')}), ID: #{@aws_account_id} -- Setup" end rescue => e puts " We were unable to check for an account alias." puts " Please contact CloudHealth support at [email protected]" warning(e) end end |
#test_checkboxes ⇒ Object
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
# File 'lib/cht/mechanize.rb', line 308 def test_checkboxes begin get_page page = @browser.get("https://portal.aws.amazon.com/gp/aws/manageYourAccount") checkbox_account_activity_search = page.search('[@id="account_activity_checkbox"]') usage_report_search = page.search('[@id="usage_reports_checkbox"]') = page.search('[@id="activateIAMUserAccess"]') = page.search('[@id="deactivateIAMUserAccess"]') activate_hidden = begin .first.attributes['style'].value.include?("display:none") rescue false end deactivate_hidden = begin .first.attributes['style'].value.include?("display:none") rescue false end if activate_hidden #Activate button is hidden, Deactivate is shown if checkbox_account_activity_search.first.attributes['checked'].nil? # Not checked puts "[ ] IAM access to Account Activity not setup -- Disabled" else # Checked puts "[X] IAM access to Account Activity is setup -- Enabled" end if usage_report_search.first.attributes['checked'].nil? # Not checked puts "[ ] IAM access to Usage Reports not setup -- Disabled" else # Checked puts "[X] IAM access to Usage Reports is setup -- Enabled" end elsif deactivate_hidden #Deactivate button is hidden, Activate shown if checkbox_account_activity_search.first.attributes['checked'].nil? # Not checked puts "[X] IAM access to Account Activity is setup -- Enabled" else # Checked puts "[ ] IAM access to Account Activity not setup -- Disabled" end if usage_report_search.first.attributes['checked'].nil? # Not checked puts "[X] IAM access to Usage Reports is setup -- Enabled" else # Checked puts "[ ] IAM access to Usage Reports not setup -- Disabled" end else puts "[ ] Could not get status of IAM Usage report & Account activity checkboxes - Unknown" end rescue => e warning(e) end end |
#test_consolidated ⇒ Object
96 97 98 99 100 101 102 103 104 105 |
# File 'lib/cht/mechanize.rb', line 96 def test_consolidated page = @browser.get("https://portal.aws.amazon.com/gp/aws/developer/account?ie=UTF8&action=consolidated-billing") consolidated_link = page.link_with(:href => "https://portal.aws.amazon.com/gp/aws/developer/subscription/index.html?ie=UTF8&productCode=AWSCBill") if consolidated_link.nil? puts "[O] Account is setup on consolidated billing - Optional" else #We must be on consolidated billing puts "[O] Account is not on consolidated billing - Optional" end end |
#test_cost_alloc ⇒ Object
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 |
# File 'lib/cht/mechanize.rb', line 269 def test_cost_alloc begin page = get_page cost_alloc_form = page.form_with(:name=>'carOptInForm') car_enabled = cost_alloc_form.field_with(:name => "buttonOptionCAR") if car_enabled.value == "EnableCAR" puts "[ ] Cost allocation report not setup -- Disabled" elsif car_enabled.value == "DisableCAR" puts "[X] Cost allocation report setup -- Enabled" end rescue => e puts " We were unable to test cost allocation reports." puts " This setting can be tested manually under Billing Preferences from the AWS account page." warning(e) end end |
#test_detailed_billing ⇒ Object
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/cht/mechanize.rb', line 207 def test_detailed_billing begin page = get_page detailed_billing_form = page.form_with(:name=>'hourlyOptInForm') bill_enabled = detailed_billing_form.field_with(:name => "buttonOptionHourly") detailed_billing_tag_form = page.form_with(:name => 'hourlyWithResourcesAndTagsOptInForm') tag_bill_enabled = detailed_billing_tag_form = detailed_billing_tag_form.field_with(:name => "buttonOptionHourlyWithResourcesAndTags") if bill_enabled.value == "EnableHourly" puts "[ ] Detailed billing report not setup -- Disabled" elsif bill_enabled.value == "DisableHourly" puts "[X] Detailed billing report setup -- Enabled" end if tag_bill_enabled.value == "EnableHourlyWithResourcesAndTags" puts "[ ] Detailed billing report w/ tags & resources not setup -- Disabled" elsif tag_bill_enabled.value == "DisableHourlyWithResourcesAndTags" puts "[X] Detailed billing report w/ tags & resources setup -- Enabled" end rescue => e puts " We were unable to test detailed billing reports." puts " This setting can be enabled/tested manually under Billing Preferences from the AWS account page." warning(e) end end |
#test_monthly_report ⇒ Object
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/cht/mechanize.rb', line 128 def test_monthly_report begin page = get_page monthly_report_form = page.form_with(:name => "csvReportOptInForm") mrf_enabled = monthly_report_form.field_with(:name => "buttonOption") if mrf_enabled.value == "EnableCSVReport" puts "[ ] Monthly report -- Disabled" elsif mrf_enabled.value == "CancelCSVReport" puts "[X] Monthly report -- Enabled" end rescue => e puts " We were unable to test if monthly report access is enabled." puts " This setting can be checked manually under Billing Preferences from the AWS Account page." warning(e) end end |
#test_prog_access ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/cht/mechanize.rb', line 167 def test_prog_access begin page = get_page prog_access_form = page.form_with(:name => "paOptInForm") paf_enabled = prog_access_form.field_with(:name => "existingS3BucketName") if paf_enabled.nil? puts "[ ] Programmatic access not setup -- Disabled" else puts "[X] Programmatic access is setup -- Enabled" end rescue => e puts " We were unable to test programmatic access to your billing information." puts " You can manually enable/test this by following these instructions: http://docs.aws.amazon.com/awsaccountbilling/latest/about/programaccess.html" warning(e) end end |
#test_ro_user ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/cht/aws.rb', line 37 def test_ro_user begin if user_exists puts "[X] AWS Read-Only user (#{@aws_ro_name}) is setup -- Exists" else puts "[ ] AWS Read-Only user (#{@aws_ro_name}) not setup -- No user" end if user_has_policy puts "[X] AWS Read-Only user has a policy -- Exists" else puts "[ ] AWS Read-Only user has no policy -- No policy" end rescue => e puts " We were unable to test your read only user." puts " Please contact CloudHealth support at [email protected]." warning(e) end end |
#test_s3_bucket ⇒ Object
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/cht/aws.rb', line 152 def test_s3_bucket begin if @s3.directories.collect{|d| d.key}.include?(@setup_bucket) puts "[X] S3 Billing bucket (#{@setup_bucket}) -- Enabled" else puts "[ ] S3 Billing bucket (#{@setup_bucket}) -- Does not exist" end if bucket_has_policy puts "[X] S3 Billing bucket policy -- Exists" else puts "[ ] S3 Billing bucket policy -- No Policy" end rescue => e puts " We were unable to test your S3 billing bucket. You can manually enable this," puts " by following these instructions: http://docs.aws.amazon.com/awsaccountbilling/latest/about/programaccess.html" warning(e) end end |
#uninstall_ro_user ⇒ Object
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/cht/aws.rb', line 56 def uninstall_ro_user begin print "Delete Cloudhealth Read-only user #{@aws_ro_name},attached policies, profiles (y/n)? " k = get_character if k.chr == "y" puts "Deleting user #{@aws_ro_name} and all associated policies and login profiles..." user_policies = @iam.list_user_policies(@aws_ro_name) user_policies.body['PolicyNames'].each do |policy| puts " Deleting user policy #{policy} attached to this user." @iam.delete_user_policy(@aws_ro_name, policy) end puts " Deleting users access keys..." access_keys = @iam.list_access_keys('UserName' => @aws_ro_name).body access_keys['AccessKeys'].each do |access_key| puts " Deleting access key #{access_key['AccessKeyId']}..." @iam.delete_access_key(access_key['AccessKeyId'], 'UserName' => @aws_ro_name) end begin puts " Deleting login profile..." @iam.delete_login_profile(@aws_ro_name) rescue => e puts " User does not have a login profile, skipping." warning(e) end puts " Deleting user...." @iam.delete_user(@aws_ro_name) puts " IAM User #{@aws_ro_name} deleted." else puts " You did not agree to delete the AWS Read only user #{aws_ro_name}." end rescue => e if defined? e.response if e.response.status == 409 puts " Could not delete user and/or login profile/policy, subordinate entities exist." elsif e.response.status == 404 puts " Could not delete user and/or login profile/policy, user/profile/policy does not exist." else puts " Could not delete User or Policy/profile, unknown error: #{e.response.inspect}" end else puts " Could not delete: #{e.}" warning(e) if @verbose end end end |
#user_exists ⇒ Object
205 206 207 208 209 210 211 212 |
# File 'lib/cht/aws.rb', line 205 def user_exists begin @iam.get_user(@aws_ro_name) true rescue false end end |
#user_has_policy ⇒ Object
11 12 13 14 15 16 17 18 |
# File 'lib/cht/policy.rb', line 11 def user_has_policy begin @iam.get_user_policy("CHTRoPolicy", @aws_ro_name) true rescue false end end |
#warning(e) ⇒ Object
10 11 12 13 14 15 |
# File 'lib/cht/error_handling.rb', line 10 def warning(e) if @verbose puts e puts e.backtrace end end |