class CfnGuardian::Cli
Public Instance Methods
__print_version()
click to toggle source
# File lib/cfnguardian.rb, line 21 def __print_version puts CfnGuardian::VERSION end
compile()
click to toggle source
# File lib/cfnguardian.rb, line 44 def compile set_log_level(options[:debug]) set_region(options[:region],options[:validate]) s3 = CfnGuardian::S3.new(options[:bucket],options[:path]) compiler = CfnGuardian::Compile.new(options[:config]) compiler.get_resources compiler.compile_templates(s3.bucket,s3.path) logger.info "Cloudformation templates compiled successfully in out/ directory" if options[:validate] s3.create_bucket_if_not_exists() validator = CfnGuardian::Validate.new(s3.bucket) if validator.validate logger.error("One or more templates failed to validate") exit(1) else logger.info "Cloudformation templates were validated successfully" end end logger.warn "AWS cloudwatch alarms defined in the templates will cost roughly $#{'%.2f' % compiler.cost} per month" if options[:template_config] logger.info "Generating a AWS CodePipeline template configuration file template-config.guardian.json" parameters = compiler.load_parameters(options) compiler.genrate_template_config(parameters) end end
deploy()
click to toggle source
# File lib/cfnguardian.rb, line 89 def deploy set_log_level(options[:debug]) set_region(options[:region],true) s3 = CfnGuardian::S3.new(options[:bucket],options[:path]) compiler = CfnGuardian::Compile.new(options[:config]) compiler.get_resources compiler.compile_templates(s3.bucket,s3.path) parameters = compiler.load_parameters(options) logger.info "Cloudformation templates compiled successfully in out/ directory" s3.create_bucket_if_not_exists validator = CfnGuardian::Validate.new(s3.bucket) if validator.validate logger.error("One or more templates failed to validate") exit(1) else logger.info "Cloudformation templates were validated successfully" end deployer = CfnGuardian::Deploy.new(options,s3.bucket,parameters) deployer.upload_templates change_set, change_set_type = deployer.create_change_set() deployer.wait_for_changeset(change_set.id) deployer.execute_change_set(change_set.id) deployer.wait_for_execute(change_set_type) end
disable_alarms()
click to toggle source
# File lib/cfnguardian.rb, line 366 def disable_alarms set_region(options[:region],true) alarm_names = CfnGuardian::CloudWatch.get_alarm_names(options[:group],options[:alarm_prefix]) CfnGuardian::CloudWatch.disable_alarms(alarm_names) logger.info "Disabled #{alarm_names.length} alarms" end
enable_alarms()
click to toggle source
# File lib/cfnguardian.rb, line 385 def enable_alarms set_region(options[:region],true) alarm_names = CfnGuardian::CloudWatch.get_alarm_names(options[:group],options[:alarm_prefix]) CfnGuardian::CloudWatch.enable_alarms(alarm_names) logger.info "#{alarm_names.length} alarms enabled" end
show_alarms()
click to toggle source
# File lib/cfnguardian.rb, line 156 def show_alarms set_log_level(options[:debug]) set_region(options[:region],options[:compare]) if options[:config] config_file = options[:config] elsif options[:defaults] config_file = default_config() else logger.error('one of `--config YAML` or `--defaults` must be supplied') exit -1 end compiler = CfnGuardian::Compile.new(config_file) compiler.get_resources alarms = filter_compiled_alarms(compiler.alarms,options[:filter]) if alarms.empty? logger.error "No matches found" exit 1 end headings = ['Property', 'Config'] formatter = CfnGuardian::DisplayFormatter.new(alarms) if options[:compare] && !options[:defaults] metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_prefix(prefix: 'guardian') metric_alarms = CfnGuardian::CloudWatch.filter_alarms(filters: options[:filter], alarms: metric_alarms) formatted_alarms = formatter.compare_alarms(metric_alarms) headings.push('Deployed') else formatted_alarms = formatter.alarms() end if formatted_alarms.any? formatted_alarms.each do |fa| puts Terminal::Table.new( :title => fa[:title], :headings => headings, :rows => fa[:rows]) end else if options[:compare] && !options[:defaults] logger.info "No difference found between you config and alarms in deployed AWS" else logger.warn "No alarms found" end end end
show_config_history()
click to toggle source
# File lib/cfnguardian.rb, line 305 def show_config_history set_region(options[:region],true) history = CfnGuardian::CodeCommit.new(options[:repository]).get_commit_history(options[:branch], options[:count]) if history.any? puts Terminal::Table.new( :headings => history.first.keys.map{|h| h.to_s.to_heading}, :rows => history.map(&:values)) end end
show_drift()
click to toggle source
# File lib/cfnguardian.rb, line 125 def show_drift set_region(options[:region],true) rows = [] drift = CfnGuardian::Drift.new(options[:stack_name]) nested_stacks = drift.find_nested_stacks nested_stacks.each do |stack| drift.detect_drift(stack) rows << drift.get_drift(stack) end if rows.any? puts Terminal::Table.new( :title => "Guardian Alarm Drift".green, :headings => ['Alarm Name', 'Property', 'Expected', 'Actual', 'Type'], :rows => rows.flatten(1)) exit(1) end end
show_history()
click to toggle source
# File lib/cfnguardian.rb, line 260 def show_history set_log_level(options[:debug]) set_region(options[:region],true) if options[:alarm_names] metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_name(alarm_names: options[:alarm_names], state: options[:state]) else metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_prefix(prefix: options[:alarm_prefix], state: options[:state]) end metric_alarms = CfnGuardian::CloudWatch.filter_alarms(filters: options[:filter], alarms: metric_alarms) case options[:type] when 'state' type = 'StateUpdate' headings = ['Date', 'Summary', 'Reason'] when 'config' type = 'ConfigurationUpdate' headings = ['Date', 'Summary', 'Type'] end formatter = CfnGuardian::DisplayFormatter.new() metric_alarms.each do |alarm| history = CfnGuardian::CloudWatch.get_alarm_history(alarm.alarm_name,type) rows = formatter.alarm_history(history,type) if rows.any? puts Terminal::Table.new( :title => alarm.alarm_name.green, :headings => headings, :rows => rows) puts "\n" end end end
show_pipeline()
click to toggle source
# File lib/cfnguardian.rb, line 323 def show_pipeline set_region(options[:region],true) pipeline = CfnGuardian::CodePipeline.new(options[:pipeline]) source = pipeline.get_source() build = pipeline.get_build() create = pipeline.get_create_changeset() deploy = pipeline.get_deploy_changeset() puts Terminal::Table.new( :title => "Stage: #{source[:stage]}", :rows => source[:rows]) puts "\t|" puts "\t|" puts Terminal::Table.new( :title => "Stage: #{build[:stage]}", :rows => build[:rows]) puts "\t|" puts "\t|" puts Terminal::Table.new( :title => "Stage: #{create[:stage]}", :rows => create[:rows]) puts "\t|" puts "\t|" puts Terminal::Table.new( :title => "Stage: #{deploy[:stage]}", :rows => deploy[:rows]) end
show_state()
click to toggle source
# File lib/cfnguardian.rb, line 217 def show_state set_log_level(options[:debug]) set_region(options[:region],true) action_prefix = nil if options[:filter].has_key?('topic') action_prefix = get_topic_arn_from_stack(options[:filter]['topic']) elsif options[:filter].has_key?('maintenance-group') action_prefix = "arn:aws:sns:#{Aws.config[:region]}:#{CfnGuardian::CloudWatch.aws_account_id()}:#{options[:filter]['maintenance-group']}MaintenanceGroup" end if options[:alarm_names] metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_name(alarm_names: options[:alarm_names], state: options[:state], action_prefix: action_prefix) else metric_alarms = CfnGuardian::CloudWatch.get_alarms_by_prefix(prefix: options[:alarm_prefix], state: options[:state], action_prefix: action_prefix) end metric_alarms = CfnGuardian::CloudWatch.filter_alarms(filters: options[:filter], alarms: metric_alarms) formatter = CfnGuardian::DisplayFormatter.new() rows = formatter.alarm_state(metric_alarms) if rows.any? puts Terminal::Table.new( :title => "Alarm State", :headings => ['Alarm Name', 'State', 'Changed', 'Notifications'], :rows => rows) else logger.warn "No alarms found" end end
Private Instance Methods
default_config()
click to toggle source
# File lib/cfnguardian.rb, line 425 def default_config() return "#{File.expand_path(File.dirname(__FILE__))}/cfnguardian/config/defaults.yaml" end
filter_compiled_alarms(alarms,filters)
click to toggle source
# File lib/cfnguardian.rb, line 415 def filter_compiled_alarms(alarms,filters) filters = filters.slice('group', 'resource', 'alarm', 'topic', 'maintenance-group') alarms.select! {|alarm| alarm.group.downcase == filters['group'].downcase} if filters.has_key?('group') alarms.select! {|alarm| alarm.resource_id.downcase == filters['resource'].downcase} if filters.has_key?('resource') alarms.select! {|alarm| alarm.name.downcase.include? filters['alarm'].downcase} if filters.has_key?('alarm') alarms.select! {|alarm| alarm.alarm_action.include? filters['topic']} if filters.has_key?('topic') alarms.select! {|alarm| alarm.maintenance_groups.include? "#{filters['maintenance-group']}MaintenanceGroup"} if filters.has_key?('maintenance-group') return alarms end
get_topic_arn_from_stack(topic)
click to toggle source
# File lib/cfnguardian.rb, line 429 def get_topic_arn_from_stack(topic) client = Aws::CloudFormation::Client.new() resp = client.describe_stacks({ stack_name: @stack_name }) stack = resp.stacks.first parameter = stack.parameters.find {|p| p.parameter_key == topic} return !parameter.nil? ? parameter.parameter_value : nil end
set_log_level(debug)
click to toggle source
# File lib/cfnguardian.rb, line 411 def set_log_level(debug) logger.level = debug ? Logger::DEBUG : Logger::INFO end
set_region(region,required)
click to toggle source
# File lib/cfnguardian.rb, line 396 def set_region(region,required) if !region.nil? Aws.config.update({region: region}) elsif !ENV['AWS_REGION'].nil? Aws.config.update({region: ENV['AWS_REGION']}) elsif !ENV['AWS_DEFAULT_REGION'].nil? Aws.config.update({region: ENV['AWS_DEFAULT_REGION']}) else if required logger.error("No AWS region found. Please suppy the region using option `--region` or setting environment variables `AWS_REGION` `AWS_DEFAULT_REGION`") exit(1) end end end