Chef Analytics Rules¶
Note
This documentation is meant to support existing Chef customers using Analytics.
If you are a new Chef customer, or are looking to gain better insight into your fleet, try Chef Automate. You’ll get a graphical interface and query language that gives you insight into operational, compliance, and workflow events. Download Chef Automate here.
Chef Analytics includes a powerful rules processing system that allows notifications to be generated based on observed events in the data stream, such as:
- Cookbook uploads
- Modifications to environments
- Machines on which chef-client runs have failed
- Machines on which audit-mode runs have failed
- Resources that were updated as a result of a chef-client run
Notifications may be sent to any email address, a chat service like HipChat or Slack, or to a webhook-based service for generic integrations.
Note
This feature is included as part of the Chef Automate license agreement and is available via subscription.
Rule Syntax¶
The syntax for a Chef Analytics rule is as follows:
rules 'name'
with priority=n
rule 'name' on message_type
when
// comment
function()
then
// comment
function()
otherwise
// comment
function()
end
rule ...
...
end
...
end
where:
rules
defines a rules group which is comprised of individual rules (rule
)rule
defines an individual rule; each rule must be contained in its ownrule
blockwith priority=n
is a positive or negative integer that defines the relative priority of a rules group as compared to all other rules groups'name'
is name of the rule group and/or the name of the rule; required forrules
, optional for eachrule
message_type
is one of the following:action
,run_control
,run_control_group
,run_converge
,run_resource
, orrun_start
when
is a series of evaluations that result intrue
orfalse
then
is a comma-separated group of statements that are used to test dataotherwise
is a comma-separated group of statements that are used to test datafunction()
is a statement that tests a value in the JSON object; functions may be one ofarray:contains()
,alert:<level>()
,datetime:component()
,get()
,log()
, ormustache_template()
. (See “Functions” below for more information about the individual functions.)- A comment starts with two forward slashes–
//
—and continues to the end of the line on which the comment begins - Whitespace is ignored by the rules parser unless it contained within single- or double-quoted strings. For example, the parser will preserve the white space in
'white space'
and"white space"
Message Types¶
Each individual rule
must be associated with a specific message type. As a rule is triggered during the chef-client run, a message is sent to the Chef Analytics server. A rule may be configured to send notifications about a message to recipients that are located outside of the Chef Analytics server.
A message type must be one of the following:
Message Type | Description |
---|---|
action |
Use to build rules for messages about actions that occur on the Chef server. |
run_control |
Use to build rules for a single audit to be evaluated. |
run_control_group |
Use to build rules for a group of audits to be evaluated. |
run_converge |
Use to build rules for messages that are sent at the end of a chef-client run. |
run_resource |
Use to build rules for messages that are sent as each resource is converged during a chef-client run. |
run_start |
Use to build rules for messages that are sent at the start of a chef-client run. |
when¶
Use when
to define an expression. Multiple expressions may be joined using and
and or
. Expressions may be grouped using parentheses (( )
). Expressions may use nested function calls on either side of the expression. The following operators may be used:
Operator | Description |
---|---|
= |
equal to |
!= |
not equal to |
> |
greater than |
< |
less than |
>= |
greater than or equal to; also known as “optimistically greater than”, or “optimistic” |
<= |
less than or equal to |
=~ |
a regular expression |
not |
negates the expression |
For example:
rule on action when
max(1000, data.some_value) = 1000
then
set(#some_value, data.some_other_value)
end
or:
rule on action when
some_value > 1000 and
(max(data.some_other_value, max(100,data.max_field)) = 1000 or data.foo='Some Value')
then
set(#some_value, data.some_other_value)
end
Expressions¶
An expression defines a specific test in a rule and uses fields within the expression that are specific to the message type for the rule. For example:
total_resource_count > 1 and
updated_resource_count > 0
array:contains(run_list, 'role[opscode-reporting]')
where both total_resource_count
, updated_resource_count
, and run_list
are the fields specific to a message type.
then¶
Use the then
statement to specify what to do when a rule in the when
statement is matched. For example:
rule on action when
data.name='app1'
then
set(#foo, '100')
end
When the name matches app1
, #foo
will be set to 100
.
otherwise¶
Use the otherwise
statement to specify what to do when a rule in the when
statement is matched, but is not handled by the then
statement. For example:
rule on action when
data.name='app1'
then
set(#foo, '100')
otherwise
set(#foo, '200")
end
When the name matches app1
, #foo
will be set to 100
and if the name does not match app1
, #foo
will be set to 200
.
with priority¶
Use the with priority
statement to specify a positive or negative integer that defines the relative priority of a rules group as compared to all other rules groups. For example:
rules 'rule name'
with priority=100
rule on action ...
...
end
A rules group with a higher integer value will have priority over any rules groups with lower integer values.
Comments¶
Use a comment to document the behavior of the rules. A comment starts with a double forward slash—//
—and continues to the end of the line on which the comment started. For example:
rules 'user-agent matching'
rule on action
when
// this rule always matches
true
then
// raise an audit for every action
alert:info('This rule matches all actions')
end
end
Whitespace¶
Whitespace is ignored by the rules parser unless it is contained within single- or double-quotes. For example, the following rules are parsed the same way:
rules 'rule'
rule on action
when
true
then
alert:info('string')
end
end
and:
rules 'rule' rule on action when true then audit:info('string') end end
The rules parser does not ignore spaces that are contained within single- or double-quotes. For example
'This is a string. The parser will not ignore the whitespace.'
or:
"This is a string. The parser will not ignore the whitespace."
Strings¶
A string must be contained in single- or double-quotes and may contain any valid UTF-8 character. For example, a single-quoted string:
'A string.'
or a double-quoted string:
"A string."
or a valid UTF-8 character:
"ᚠᛇᚻ᛫ᛒᛦᚦ᛫ᚠᚱᚩᚠᚢᚱ᛫ᚠᛁᚱᚪ᛫ᚷᛖᚻᚹᛦᛚᚳᚢᛗ"
Use a backslash—\
—to escape single-quotes that must appear within a single-quoted string. For example:
'This is a string with \'escaped single quotes\'.'
to escape double-quotes that must appear within a double-quoted string:
"This is a string with \"escaped double quotes\"."
Single-quotes that appear within a double-quoted string do not need to be escaped. Double-quotes that appear in a single-quoted string do not need to be escaped.
For example:
rules 'string example'
rule on action
when
// this rule always matches
true
then
// single quoted string,
alert:info('This rule matches all \'action\' messages')
end
end
Numbers¶
Numbers may be positive or negative integers or floating point values.
- The valid range for integers is
-9223372036854775808
to9223372036854775807
- The valid range for floating point numbers is
4.9E-324
to1.7976931348623157E308
; scientific notation is not supported and rounding will occur outside of this range
Numbers may be compared with the following operators:
Operator | Description |
---|---|
= |
Equality. |
!= |
Inequality. |
> |
Greater than. |
>= |
Greater than equal. |
< |
Less than. |
<= |
Less than equal. |
Note
If a number is compared to a non-number, the rule will not match and an error is logged.
For example, all of the following are valid numbers:
1
or:
-99999999
or:
1.99999
or:
-999999.000123
For example:
rules 'Match control groups with failures'
rule on run control group
when
name = 'mysql audit' and number_failed > 0
then
alert:error('Control group failures detected')
end
end
Regular Expressions¶
Use a regular expression to define a search pattern to match against a rule. Use the =~
operator to define the regular expression:
string_to_match =~ regular_expression
For example:
rules 'regex demo'
rule on action
when
// match if the user_agent starts with the string 'Chef Manage'
user_agent =~ 'Chef Manage.*'
or
// match 1 or more lower case characters followed by a single digit
entity_name =~ '[a-z]+\d'
then
notify('my_webhook')
end
end
Use the following to match constructs:
Construct | Description |
---|---|
x |
Use to match the x character. |
\ |
Use to match the backslash character. |
\t |
Use to match the tab character ('\u0009' ). |
\n |
Use to match the newline (line feed) character ('\u000A' ). |
\r |
Use to match the carriage-return character ('\u000D' ). |
Use the following to match characters:
Characters | Description |
---|---|
[abc] |
Use to match a, b, or c. |
[^abc] |
Use to match any character except a, b, or c. |
[a-zA-Z] |
Use to match a through z or A through Z, inclusive. |
. |
Use to match any character or a line terminator. |
\d |
Use to match a digit. For example: [0-9] . |
\D |
Use to match a non-digit. For example: [^0-9] . |
\s |
Use to match a whitespace character. For example: [ \t\n\x0B\f\r] . |
\S |
Use to match a non-whitespace character. For example: [^\s] . |
\w |
Use to match a word character. For example: [a-zA-Z_0-9] . |
\W |
Use to match a non-word character. For example: [^\w] . |
Use the following to match boundaries:
Boundary | Description |
---|---|
^ |
Use to match the beginning of a line. |
$ |
Use to match the end of a line. |
\b |
Use to match a word boundary. |
\B |
Use to match a non-word boundary. |
Nested Fields, Arrays¶
Some messages that contain nested fields or arrays.
- Use dot syntax—
.foo
—to access integer values in nested fields. - Use square bracket syntax—
[index]
—to access integer values in arrays.
Note
If the field does not exist, the rule will return false.
For example, accessing integer values in a nested field:
rules 'Control group matches'
rule on run control group
when
run.chef_server_fqdn = 'mysql.production.foo.com'
or
// any node_name with 'production' in it's name
run.node_name =~ '.*production.*'
then
alert:info('production control group match')
end
end
And accessing integer values in an array:
rules 'Run resource matches'
rule on run resource
when
converge.run_list[0] = 'role[opscode-reporting]'
or
some_other.property[0].another_property[99] != 100
then
alert:error('Run resource match')
end
end
Message Fields¶
The following sections describe the fields that may be used for each of the specific message types.
actions¶
The following fields are available for the action
message type:
Field | Type | Description |
---|---|---|
entity_name |
string | The name of the entity. For example: 'app1' . |
entity_type |
string | The type of entity. For example: 'node' . |
id |
string | The globally-unique identifier for this message. For example: '12345678-9012-3456-7890-12345678901211' . |
organization_name |
string | The short name of the organization to which the node belongs. For example: 'chef' . |
parent_name |
string | The name of the parent entity. For example: 'apache2' . |
parent_type |
string | The type of entity of the parent entity. For example: 'cookbook' . |
recorded_at |
string | The ISO timestamp at which the action occurred. For example: '2014-06-05T10:34:35Z' . |
remote_hostname |
string | The IP address from which the action was initiated. For example: '127.0.0.1' . |
remote_request_id |
string | The request identifier generated by the remote client. For example: '12345678-9012-3456-7890-12345678901211' . |
request_id |
string | The Chef server request identifier. For example: 'tG3MRbYB7NFWjFU8shs1YeSxq8CIIMJudpnHJXDnWEWzFSVW' . |
requestor_name |
string | The name of the chef-client or user that initiated the action. For example: 'grantmc' . |
requestor_type |
string | Indicates if the requestor was a chef-client or a user. For example: 'user' . |
service_hostname |
string | The FQDN for the Chef server against which the instance is running. For example: 'api.chef.io' . |
task |
string | The description of the action that was performed. For example: delete . |
user_agent |
string | The User-Agent of the requestor. For example: 'Chef Client/12.0.2 (ruby-2.0.0-p598; x86_64-linux; +http://chef.io)' . |
run_control¶
The following fields are available for the run_control
message type:
Field | Type | Description |
---|---|---|
context |
array | |
control_group |
object | A JSON object that contains the control group identifier, the name of the control group, the number of tests that passed and failed, and its final status. |
control_group.control_group_id |
string | The identifier of the control group object. For example: '12345678-9012-3456-7890-12345678901211' . |
control_group.name |
string | The name of the control group. For example: 'mysql audit' . |
control_group.number_failed |
integer | The number of tests within the control group that failed. For example: 7 . |
control_group.number_succeeded |
integer | The number of tests within the control group that passed. For example: 4 . |
control_group.status |
string | The status of the control group. For example: 'success' . |
details |
[“string”, “null”] | Details about the control object. |
id |
string | The globally-unique identifier for this message. For example: '12345678-9012-3456-7890-12345678901211' . |
name |
string | The name of the control object. For example: 'should be installed' . |
organization_name |
string | The short name of the organization to which the node belongs. For example: 'chef' . |
resource_name |
[“string”, “null”] | The name of the resource in which the control object is present. For example: 'mysql' . |
resource_type |
[“string”, “null”] | The resource type for the control object. For example: 'Package' . |
run |
object | A JSON object that contains run data, including the chef-client run identifier, the FQDN for the Chef server, the name of the node, and the times at which the chef-client started and finished. |
run.chef_server_fqdn |
string | The FQDN for the Chef server against which the instance is running. For example: 'api.chef.io' . |
run.end_time |
string | The ISO timestamp at which the chef-client run finished. For example: '2014-06-05T10:39:43Z' . |
run.node_name |
string | The name of the node on which the chef-client run occurred. For example: 'grantmc01-abc' . |
run.run_id |
string | The internal message identifier for the chef-client run. For example: '12345678-9012-3456-7890-12345678901211' . |
run.start_time |
string | The ISO timestamp at which the chef-client run started. For example: '2014-06-05T10:34:35Z' . |
sequence_number |
integer | The sequence number at which the resource converged. For example: 2 . |
status |
string | The status of the control object. For example: 'success' . |
run_control_group¶
The following fields are available for the run_control_group
message type:
Field | Type | Description |
---|---|---|
error |
string | The error reported by the chef-client. For example: "error": {
"class": "#<TypeError: user[chef] (/var/file.rb line 56) has error",
"message": "user[chef] (/var/file.rb line 87) has error",
"backtrace": "[\"/opt/chef/embedded/.../chef/unix.rb:103 \"]",
"description": {
"title": "Errorexecutingaction`create`onresource'user[chef]'",
"sections": [
{ "TypeError": "can'tconvertArrayintoString" },
{ "CookbookTrace: ": "/var/chef/file.rb: 11: action: create\n" }
]
}
}
|
id |
string | The globally-unique identifier for this message. For example: '12345678-9012-3456-7890-12345678901211' . |
name |
string | The name of the control group object. For example: 'mysql audit' . |
number_failed |
integer | The number of tests within the control group that failed. For example: 7 . |
number_succeeded |
integer | The number of tests within the control group that passed. For example: 4 . |
organization_name |
string | The short name of the organization to which the node belongs. For example: 'chef' . |
run |
object | A JSON object that contains run data, including the chef-client run identifier, the FQDN for the Chef server, the name of the node, and the times at which the chef-client started and finished. |
run.chef_server_fqdn |
string | The FQDN for the Chef server against which the instance is running. For example: 'api.chef.io' . |
run.end_time |
string | The ISO timestamp at which the chef-client run finished. For example: '2014-06-05T10:39:43Z' . |
run.node_name |
string | The name of the node on which the chef-client run occurred. For example: 'grantmc01-abc' . |
run.run_id |
string | The internal message identifier for the chef-client run. For example: '12345678-9012-3456-7890-12345678901211' . |
run.start_time |
string | The ISO timestamp at which the chef-client run started. For example: '2014-06-05T10:34:35Z' . |
status |
string | The status of the control object. For example: 'failure' . |
run_converge¶
The following fields are available for the run_converge
message type:
Field | Type | Description |
---|---|---|
chef_server_fqdn |
string | The FQDN for the Chef server against which the instance is running. For example: 'api.chef.io' . |
end_time |
string | The ISO timestamp at which the chef-client run finished. For example: '2014-06-05T10:39:43Z' . |
error |
object | The details of errors that occurred during the chef-client run, if present. For example: "error": {
"class": "#<TypeError: user[chef] (/var/file.rb line 87) has error",
"message": "user[chef] (/var/file.rb line 87) has error",
"backtrace": "[\"/opt/chef/embedded/.../chef/unix.rb:103 \"]",
"description": {
"title": "Errorexecutingaction`create`onresource'user[chef]'",
"sections": [
{ "TypeError": "can'tconvertArrayintoString" },
{ "CookbookTrace: ": "/var/chef/file.rb: 11: action: create\n" }
]
}
}
|
id |
string | The internal message identifier for the chef-client run. For example: '12345678-9012-3456-7890-12345678901211' . |
node_name |
string | The name of the node on which the chef-client run occurred. For example: 'grantmc01-abc' . |
organization_name |
string | The short name of the organization to which the node belongs. For example: 'chef' . |
resources |
array | An array of resources that were converged during the chef-client run. |
run_id |
string | The identifier for the chef-client run. For example: '67890123-4567-8901-2345-67890123456789' . |
run_list |
array | The run-list used during the chef-client run. For example: [ 'role[opscode-reporting]' ] . |
start_time |
string | The ISO timestamp at which the chef-client run started. For example: '2014-06-05T10:34:35Z' . |
status |
string | The status of the chef-client run. For example: 'success' . |
total_resource_count |
integer | The total number of resources in the resource collection for the chef-client run. For example: 4 . |
updated_resource_count |
integer | The total number of resources that were updated during the chef-client run. For example: 2 . |
run_resource¶
The following fields are available for the run_resource
message type:
Field | Type | Description |
---|---|---|
converge |
object | A JSON object that contains the status of the chef-client run, the name of the organization, the run-list, total resource count, updated resource count, the run identifier, and the times at which the chef-client started and finished. |
converge.end_time |
string | The ISO timestamp at which the chef-client run finished. For example: '2014-06-05T10:39:43Z' . |
converge.id |
string | The internal message identifier for the chef-client run. For example: '12345678-9012-3456-7890-12345678901211' . |
converge.organization_name |
string | The name of the organization to which the node belongs. For example: 'chef' . |
converge.run_list |
array | The run-list used during the chef-client run. For example: [ 'role[opscode-reporting]' ] . |
converge.start_time |
string | The ISO timestamp at which the chef-client run started. For example: '2014-06-05T10:34:35Z' . |
converge.status |
string | The status of the chef-client run. For example: 'success' . |
converge.total_resource_count |
integer | The total number of resources that were converged during the chef-client run. For example: 4 . |
converge.updated_resource_count |
integer | The total number of resources that were updated during the chef-client run. For example: 2 . |
cookbook_name |
string | The name of the cookbook that initiated the changes made by this chef-client run. For example: 'chef_handler' . |
cookbook_version |
string | The version of the cookbook initiated the changes made by this chef-client run. For example: '0.2.3' . |
delta |
string | The difference between the initial and final value of resource. For example: --- /etc/motd.tail
2013-06-30 17:41:31.667050237 -0600\n
+++ /tmp/chef-rendered-template 18:11:54.7 -0600\n
@@ -3,7 +3,7 @@\n
Chef-Client - jenkins\n
Hostname: jenkins.int.housepub.org\n
Chef Server: https://api.chef.io/orgs/org\n
-Last Run: 2013-06-30 17:41:31 -0600\n
+Last Run:2013-06-30 18:11:54 -0600\n
\n
Roles:\n
debian
|
duration |
string | The duration of the chef-client run. For example: '1200' . |
final_state |
object | A JSON object that contains the final state of the resource, including a checksum, owner, group, and mode. |
id |
string | The internal message identifier for the chef-client run. For example: '12345678-9012-3456-7890-12345678901211' . |
initial_state |
object | A JSON object that contains the initial state of the resource, including a checksum, owner, group, and mode. |
resource_id |
string | The resource identifier. For example: '/var/cache/mod_auth_openid/mod_auth_openid.db' . |
resource_name |
string | The name of the resource. For example: '/var/cache/mod_auth_openid/mod_auth_openid.db' . |
resource_result |
string | The resource result. For example: 'delete' . |
resource_type |
string | The resource type. For example: 'file' . |
run |
object | A JSON object that contains run data, including the chef-client run identifier, the FQDN for the Chef server, the name of the node, and the times at which the chef-client started and finished. |
run.chef_server_fqdn |
string | The FQDN for the Chef server against which the instance is running. For example: 'api.chef.io' . |
run.end_time |
string | The ISO timestamp at which the chef-client run finished. For example: '2014-06-05T10:39:43Z' . |
run.node_name |
string | The name of the node on which the chef-client run occurred. For example: 'grantmc01-abc' . |
run.run_id |
string | The identifier for the chef-client run. For example: '67890123-4567-8901-2345-67890123456789' . |
run.start_time |
string | The ISO timestamp at which the chef-client run started. For example: '2014-06-05T10:34:35Z' . |
sequence_number |
integer | The sequence number at which the resource converged. For example: 0 . |
run_start¶
The following fields are available for the run_start
message type:
Field | Type | Description |
---|---|---|
chef_server_fqdn |
string | The FQDN for the Chef server against which the instance is running. For example: 'api.chef.io' . |
id |
string | The internal message identifier for the chef-client run. For example: '12345678-9012-3456-7890-12345678901211' . |
node_name |
string | The name of the node on which the chef-client run occurred. For example: 'grantmc01-abc' . |
organization_name |
string | The short name of the organization to which the node belongs. For example: 'chef' . |
run_id |
string | The identifier for the chef-client run. For example: '67890123-4567-8901-2345-67890123456789' . |
start_time |
string | The ISO timestamp at which the chef-client run started. For example: '2014-06-05T10:34:35Z' . |
Functions¶
Use a function to help specify how rules are applied. A function may be used in when
, then
, and otherwise
sections in rules. A function has the following syntax:
function_name(param1, param2, paramN)
Note
A function that is defined in the when
section of a rule MUST return a Boolean value, or it will fail.
alert:<level>()¶
Use alert:<level>()
to generate an audit.
The syntax for this function:
alert:<level>(description)
where:
<level>
is the audit level:error
,info
, orwarn
description
is a user-defined value (and may be a Mustache template)
array:contains()¶
Use array:contains()
to look for an attribute in the JSON object, and then determine its value.
The syntax for this function:
array:contains(field, valueToFind)
where:
field
is an attribute in the JSON objectvalueToFind
is the value for that attribute
For example:
array:contains(organization_name = 'ponyville')
datetime:component()¶
Use datetime:component()
to specify the date and time at which a rule is applied.
The syntax for this function:
datetime:component(field, 'dateTimeComponent')
where:
field
is an attribute in the JSON objectdateTimeComponent
must be one of the following (lower or uppercase) as a quoted string:era
,year_of_era
,century_of_era
,year_of_century
,year
,day_of_year
,month_of_year
,day_of_month
,weekyear_of_century
,weekyear
,week_of_weekyear
,day_of_week
,halfday_of_day
,hour_of_halfday
,clockhour_of_halfday
,clockhour_of_day
,hour_of_day
,minute_of_day
,minute_of_hour
,second_of_day
,second_of_minute
,millis_of_day
, ormillis_of_second
For example:
datetime:component(adate, 'era')
get()¶
Use get()
to identify a field, and then identify an associated value.
The syntax for this function:
get(variableToGet, valueToSet OR defaultIfMissing)
where:
variableToGet
specifies the field to look forvalueToSet
specifies the value to usedefaultIfMissing
specifies to use the default value if there is no user-defined value
For example:
rule on action when
get(foo, false) = false
then
notify('some_alias')
end
will pass if foo
is missing in the JSON object.
log()¶
Use log()
to generate a message using the configured logger as a string.
The syntax for this function:
log(messageToLog)
where:
messageToLog
is the message that is added to the log
For example:
log('Added rule for org <obj.organization_name>')
mustache_template()¶
Use mustache_template()
to render an expression that is defined in a Mustache template. If the Mustache template is invalid, an error is logged and the expression will return an empty, non-null string.
The syntax for this function:
mustache_template('message_type = {{message.json_attribute}}')
where:
message_type
is a string that represents the message typemessage
is the JSON message to be passed injson_attribute
is a user-defined value in the JSON object
For example:
rule 'test_rule' on action
when
true
then
set(#foo, mustache_template('Organization = {{message.organization_name}}.'))
end
For more information on the Mustache template format, see https://mustache.github.io.
notify()¶
Use notify()
to configure notifications for a rule. Notifications may be sent with the following notification types: email, webhook, HipChat, and Splunk.
The syntax for this function:
notify(notificationName, stringTemplate)
where:
notificationName
is the name of the notification to trigger.stringTemplate
is an optional Mustache template that defines the notification. The template must evaluate to a valid JSON string.
Field names in the Mustache template must be prefixed by message.
, e.g. {{message.reported_at}}
using a valid field name for the message type. For more information on the Mustache template format, see https://mustache.github.io.
For example:
rules 'Send notification'
rule on action
when
organization_name = 'ponyville' and
(entity_type = 'foo' or entity_type = 'bar') and
remote_hostname =~ '33\.3[0-9].*'
then
set value #foo = '100'
set value #xyz = 'test'
notify('slack', '{
"text": "{{message.requestor_name}} did something at {{message.recorded_at}}!"
}')
end
end
set()¶
Use set()
to set a user-defined value in the JSON object. A user-defined value always begins with #
. Prepend values saved by the set()
function with user_defined_values
to access them later from a notify()
or alert()
function. Values that are not user-defined may not be modified.
The syntax for this function:
set(#variableToSet, valueToSet)
where:
variableToSet
is the location of a user-defined valuevalueToSet
is the value
For example:
set(#organization_name, 'ponyville')
Later on in the same rule or another rule in the same group, do:
alert:warn("Check out the org name {{user_defined_values.#organization_name}}")
Examples¶
The following examples show how to define Chef Analytics rules.
Always Run a Rule¶
A rule that always fire for the specified message type:
rule "test_rule" on action
when
true
then
notify("some_alias")
end
where every action
will notify "some_alias"
.
Raise Audit¶
The following rule raises an alert when a run_control_group
fails, signifying that one or more controls failed:
rules "throw errors on control group failure"
rule on run_converge
when
true
then
alert:info("Run converge detected at {{ message.end_time }} ")
end
rule on run_control_group
when
true
then
// the run_control_group name will appear in double quotes
alert:info("Run control group \"{{ message.name }}\" failed on {{ message.run.node_name }}")
end
end
Send a Notification¶
Using the notify()
function, notifications can be sent when a rule’s conditions are met.
Once you’ve created a notification you’ll use its name as the first argument given to the notify()
function. For example, suppose you’ve created a notification with the name email-admins
:
This notification could then be triggered by creating a rule that calls notify()
, e.g.:
notify("email-admins", "Your message here.")
The below rule would trigger this notification for every run_start
message:
rule "Email notification" on run_start
when
true
then
notify("email-admins", "Run started on {{message.node_name}}")
end
Regular Expressions¶
The following rule shows using a regular expression:
rules "user-agent matching"
rule on action
when
get(#user_agent, false) != false
then
log("Something else set #user_agent")
end
rule on action
when
// match if the user_agent starts with the string "Chef Manage"
user_agent =~ "Chef Manage.*"
then
// if #user_agent has been set before
// this command will overwrite it's value
set(#user_agent, "Chef Manage")
end
rule on action
when
// match if the user_agent starts with the string "Chef Client"
user_agent =~ "Chef Client.*"
then
set(#user_agent, "Chef Client")
end
rule on action
when
get(#user_agent, false) != false
then
alert:info("User agent {{user_defined_values.#user_agent}}")
end
end
Notify on Port 23¶
The following rule shows how to define a rule that sends a notification when a machine is listening for connections on port 23:
rules "pci check telnet port"
rule on run_control
when
name = "should be listening" and
resource_type = "port" and
resource_name = 23 and
status != "success"
then
alert:error("Encrypt all non-console administrative access such as browser/Web-based management tools.")
notify("some_alias", "A machine is listening for connections on port 23!")
end
end
User-defined Values¶
The following rule sets, and then uses a user-defined value:
rules "user-agent matching"
rule on action
when
entity_name = "app1"
then
set(#foo, requestor_name)
otherwise
set(#bar, task)
end
// ... other rules could go here
rule on action
when
// #foo might be undefined, so use get()
// to supply a default value of false to perform the
// test
get(#foo, false) != false
then
alert:info(#foo)
end
end
Verify Dates¶
The following rule checks the day of the week on which an action runs:
rules "Check deploy day of week"
rule "my rule" on action
when
// DAY_OF_WEEK uses 1 -> 7 for Monday -> Sunday
datetime:component(recorded_at, "DAY_OF_WEEK") >= 5
then
// set a user defined value
set(#alert, 'action detected on a Friday, Saturday, or Sunday'),
end
end
Verify Resource Updates¶
The following rule verifies if resources have been updated on a run_converge
:
rules "Match a run converge"
rule on run_converge
when
total_resource_count > 1 and
updated_resource_count > 0
then
alert:info("Run converge detected at {{ message.end_time }} ")
end
end
Verify Run-lists¶
The following rule verifies if a specific role appears in a run-list:
rules "Check a converge run_list"
rule on run_converge
when
array:contains(run_list, 'role[opscode-reporting]')
then
alert:info("run_list contains role[opscode-reporting]")
end
end