Class: CfnGuardian::Resource::Base

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/cfnguardian/resources/base.rb

Instance Method Summary collapse

Methods included from Logging

colors, included, logger, #logger, logger=

Constructor Details

#initialize(resource, override_group = nil) ⇒ Base

Returns a new instance of Base.



13
14
15
16
17
18
19
20
21
# File 'lib/cfnguardian/resources/base.rb', line 13

def initialize(resource, override_group = nil)
  @resource = resource
  @override_group = override_group
  @alarms = []
  @events = []
  @checks = []
  @metric_filters = []
  @event_subscriptions = []
end

Instance Method Details

#default_alarmsObject

Overidden by inherited classes to define default alarms



24
25
26
# File 'lib/cfnguardian/resources/base.rb', line 24

def default_alarms()
  return @alarms
end

#default_checksObject

Overidden by inherited classes to define default checks



155
156
157
# File 'lib/cfnguardian/resources/base.rb', line 155

def default_checks()
  return @checks
end

#default_event_subscriptionsObject

Overidden by inherited classes to define default checks



175
176
177
# File 'lib/cfnguardian/resources/base.rb', line 175

def default_event_subscriptions()
  return @event_subscriptions
end

#default_eventsObject

Overidden by inherited classes to define default events



145
146
147
# File 'lib/cfnguardian/resources/base.rb', line 145

def default_events()
  return @events
end

#default_metric_filtersObject

Overidden by inherited classes to define default checks



165
166
167
# File 'lib/cfnguardian/resources/base.rb', line 165

def default_metric_filters()
  return @metric_filters
end

#get_alarms(group, overides = {}) ⇒ Object



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
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
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
# File 'lib/cfnguardian/resources/base.rb', line 28

def get_alarms(group,overides={})
  # deep copying the overrides to preserve its reference before doing any changes to it
  overides = Marshal.load(Marshal.dump(overides))

  # generate default alarms
  default_alarms()

  # override any group properties
  group_overrides = overides.has_key?('GroupOverrides') ? overides['GroupOverrides'] : {}
  overides.delete('GroupOverrides')
  if group_overrides.any?
    @alarms.each do |alarm|
      logger.debug("overriding #{alarm.name} alarm properties for resource #{alarm.resource_id} in resource group #{group} via group overrides") 
      group_overrides.each {|attr,value| update_object(alarm,attr,value)}
    end
  end

  # loop over each override template for the service
  overides.each do |name,properties|       
    # disable default alarms
    if [false].include?(properties)
      alarms = find_alarms(name)
      
      if !alarms.nil?
        alarms.each do |alarm| 
          alarm.enabled = false
          logger.info "disabling alarm '#{name}' for resource #{alarm.resource_id}"
        end
        next
      end
    end

    # continue if the override is in the incorrect format
    unless properties.is_a?(Hash)
      if name != 'Inherit'
        logger.warn "incorrect format for alarm '#{name}'. Should be of type 'Hash', instead got type '#{properties.group}'"
      end
      next
    end

    properties.merge!(group_overrides)

    # Create a new alarm inheriting the defaults of an existing alarm
    if properties.has_key?('Inherit')
      alarm = find_alarm(properties['Inherit'])
      if !alarm.nil?
        logger.debug("creating new alarm #{name} for alarm group #{self.class.to_s.split('::').last} inheriting properties from alarm #{properties['Inherit']}")
        inherited_alarm = alarm.clone
        alarm.name = name
        properties.each {|attr,value| update_object(inherited_alarm,attr,value)}
        @alarms.push(inherited_alarm)
      else
        logger.warn "alarm '#{properties['Inherit']}' doesn't exist and cannot be inherited"
      end
      next
    end
    
    alarms = find_alarms(name)

    if alarms.empty? && !['LogGroup'].any?(group)
      # if the alarm doesn't exist and it's not being inherited from another alarm create a new alarm
      # and is a supported a resource group.
      # unsupported resource groups
      # - LogGroup: this is not required as alarms are defined in the Metric Filters object in the resource group
      resources = @resource.has_key?('Hosts') ? @resource['Hosts'] : [@resource]
      resources.each do |res|
        alarm = Kernel.const_get("CfnGuardian::Models::#{self.class.to_s.split('::').last}Alarm").new(res)
        properties.each {|attr,value| update_object(alarm,attr,value)}
        alarm.name = name
        logger.debug("created new alarm #{alarm.name} for resource #{alarm.resource_id} in resource group #{group}")
        @alarms.push(alarm)
      end
    else
      # if there is an existing alarm update the properties
      alarms.each do |alarm|
        logger.debug("overriding #{alarm.name} alarm properties for resource #{alarm.resource_id} in resource group #{group} via alarm overrides") 
        properties.each {|attr,value| update_object(alarm,attr,value)}
      end
    end
  end
  
  unless @override_group.nil?
    @alarms.each {|a| a.group = @override_group}
  end
  
  @alarms.each do |alarm|
    # String interpolation for alarm dimensions
    unless alarm.dimensions.nil?
      alarm.dimensions.each do |k,v|
        if v.is_a?(String) && v.match?(/^\${Resource::.*[A-Za-z]}$/)
          resource_key = v.tr('${}', '').split('Resource::').last
          if @resource.has_key?(resource_key)
            logger.debug "overriding alarm #{alarm.name} dimension key '#{k}' with value '#{@resource[resource_key]}'" 
            alarm.dimensions[k] = @resource[resource_key]
          end
        end
      end
    end

    # String interpolation for search expressions
    if alarm.search_expression.is_a?(String)
      alarm.search_expression = alarm.search_expression.gsub(/\${Resource::([A-Za-z0-9_]+)}/) do
        resource_key = Regexp.last_match(1)
        if @resource.has_key?(resource_key)
          logger.debug "interpolating search_expression variable '#{resource_key}' with value '#{@resource[resource_key]}' for alarm #{alarm.name}"
          @resource[resource_key]
        else
          "${Resource::#{resource_key}}"
        end
      end
    end
  end

  return @alarms.select{|a| a.enabled}
end

#get_checksObject



159
160
161
162
# File 'lib/cfnguardian/resources/base.rb', line 159

def get_checks()
  default_checks()
  return @checks
end

#get_costObject



228
229
230
# File 'lib/cfnguardian/resources/base.rb', line 228

def get_cost()
  return @alarms.length * 0.10
end

#get_event_subscriptions(group, overides) ⇒ Object



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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/cfnguardian/resources/base.rb', line 179

def get_event_subscriptions(group, overides)
  # generate default event subscriptions
  default_event_subscriptions()

  # override the defaults
  overides.each do |name, properties|
    event_subscription = find_event_subscriptions(name)

    # disable the event subscription if the value is false
    if [false].include?(properties)
      unless event_subscription.nil?
        event_subscription.enabled = false
        logger.info "Disabling event subscription #{name} for #{group} #{event_subscription.resource_id}"
      end

      next
    end

    # ignore all properties not in a proper format
    next unless properties.is_a?(Hash) 

    # Create a new event subscription by inheriting an existing one
    if properties.has_key?('Inherit')
      inherit_event_subscription = find_event_subscriptions(properties['Inherit'])
      
      if inherit_event_subscription.nil?
        logger.warn "Unable to create #{topic} RDSEventSubscription by inheriting #{properties['Inherit']} as it cannot be found"
        next
      end

      event_subscription = inherit_event_subscription.clone
      event_subscription.enabled = true
      event_subscription.name = name
      @event_subscriptions.push(event_subscription) 
      logger.debug "Inheriting RDSEventSubscription #{properties['Inherit']}"
    end

    if event_subscription.nil?
      event_subscription = Kernel.const_get("CfnGuardian::Models::#{self.class.to_s.split('::').last}EventSubscription").new(@resource)
      event_subscription.name = name
      @event_subscriptions.push(event_subscription) 
    end

    properties.each {|attr,value| update_object(event_subscription,attr,value)}
  end

  return @event_subscriptions.select {|es| es.enabled }
end

#get_eventsObject



149
150
151
152
# File 'lib/cfnguardian/resources/base.rb', line 149

def get_events()
  default_events()
  return @events.select{|e| e.enabled}
end

#get_metric_filtersObject



169
170
171
172
# File 'lib/cfnguardian/resources/base.rb', line 169

def get_metric_filters()
  default_metric_filters()
  return @metric_filters
end

#resource_exists?Boolean

Returns:

  • (Boolean)


232
233
234
# File 'lib/cfnguardian/resources/base.rb', line 232

def resource_exists?
  return true
end