Custom Rules Reference¶
Note
For an overview on custom rules, see Writing Rules.
See also Simple Custom Rules and Advanced Custom Rules.
Rule Templates¶
Simple rule template¶
Here’s a template for writing a simple rule:
package rules.my_rule # Optional, but recommended
# Metadata is required for uploading rules via `fugue sync rules`
__rego__metadoc__ := {
"title": "My Awesome Rule",
"description": "My awesome rule description",
"custom": {
"providers": ["PROVIDER_GOES_HERE", "ANOTHER_PROVIDER"],
"severity": "Medium"
}
}
input_type = "my_input_type" # Required for REPOSITORY rules
resource_type = "my_resource_type" # Fugue name for runtime-only rules, Terraform name for repository and repository + runtime rules
default allow = false # Required for repository environments; use `default deny = false` if writing a deny rule
allow {
# Rule logic for pass condition
}
Advanced rule template¶
Here’s a template for writing an advanced rule:
package rules.my_rule # Optional, but recommended
import data.fugue # Optional, but recommended
# Metadata is required for uploading rules via `fugue sync rules`
__rego__metadoc__ := {
"title": "My Awesome Rule",
"description": "My awesome rule description",
"custom": {
"providers": ["PROVIDER_GOES_HERE", "ANOTHER_PROVIDER"],
"severity": "Medium"
}
}
input_type = "my_input_type" # Required for REPOSITORY rules
resource_type = "MULTIPLE" # Required, even if rule does not involve multiple resource types
resources = fugue.resources("some_resource_type") # Fugue name for runtime-only rules, Terraform name for repository and repository + runtime rules
policy[r] {
resource = resources[_]
# Rule logic for pass condition
r = fugue.allow_resource(resource)
} {
resource = resources[_]
# Rule logic for fail condition
r = fugue.deny_resource(resource)
}
Rule parameter overview¶
A rule requires certain parameters, which – depending on the parameter – can be defined in the rule code, in metadata, or via the UI/CLI/API:
-
Runtime:
AWS
(AWS commercial)AWS_GOVCLOUD
AZURE
(Azure and Azure Government)GOOGLE
Infrastructure as code (IaC):
REPOSITORY
Any combination (e.g.,
["AZURE", "REPOSITORY"]
)
Input type, for the
REPOSITORY
provider:Default:
tf
(Terraform HCL and JSON plans)tf_plan
(Terraform JSON plans)cfn
(CloudFormation templates)k8s
(Kubernetes YAML manifests)
Resource types. Here are a few examples:
Amazon VPCs (
AWS.EC2.Vpc
,aws_vpc
,AWS::EC2::Vpc
)Azure virtual networks (
Azure.Network.VirtualNetwork
,azurerm_virtual_network
)Google VPCs (
Google.Compute.Network
,google_compute_network
)Kubernetes pods (
Pod
)A combination (advanced rules only); must use the same input type (e.g.,
AWS.EC2.Vpc
,AWS.EC2.SecurityGroup
; oraws_vpc
,aws_security_group
; orAWS::EC2::Vpc
,AWS::EC2::SecurityGroup
). Note that theresource_type
parameter must be set to"MULTIPLE"
, and the resource types themselves must be defined elsewhere in the code. See Step 2.
Provider¶
Specify one or more providers
for the rule. The provider determines what type of environments the rule will be applied to: runtime (AWS
, AWS_GOVCLOUD
, AZURE
, GOOGLE
) and/or REPOSITORY
.
Provider: |
Resource type name: |
Input type: |
Applied to: |
---|---|---|---|
AWS |
Fugue name |
None |
AWS runtime |
AWS |
Terraform name |
None (defaults to tf) |
|
AWS |
Terraform name |
tf_plan |
|
AWS_GOVCLOUD |
Fugue name |
None |
AWS GovCloud runtime |
AWS_GOVCLOUD |
Terraform name |
None (defaults to tf) |
|
AWS_GOVCLOUD |
Terraform name |
tf_plan |
|
AZURE |
Fugue name |
None |
|
AZURE |
Terraform name |
None (defaults to tf) |
|
AZURE |
Terraform name |
tf_plan |
|
Fugue name |
None |
Google runtime |
|
Terraform name |
None (defaults to tf) |
|
|
Terraform name |
tf_plan |
|
|
REPOSITORY |
Terraform name |
None (defaults to tf) |
|
REPOSITORY |
Terraform name |
tf_plan |
Terraform plans (platform according to resource type) |
REPOSITORY |
CloudFormation name |
cfn |
CloudFormation templates |
REPOSITORY |
Kubernetes name |
k8s |
Kubernetes YAML manifests |
You can also specify multiple providers. For instance:
AWS
andREPOSITORY
, withtf
input, applies to all of:AWS runtime
AWS Terraform HCL
AWS GovCloud Terraform HCL
AWS Terraform plans
AWS GovCloud Terraform plans
AZURE
,GOOGLE
, andREPOSITORY
, withtf_plan
input, applies to all of:Azure runtime
Azure Government runtime
Google runtime
Azure Terraform plans
Azure Government Terraform plans
Google Terraform plans
AWS
andAWS_GOVCLOUD
, withtf
input, applies to all of:AWS runtime
AWS GovCloud runtime
AWS Terraform HCL
AWS GovCloud Terraform HCL
AWS Terraform plans
AWS GovCloud Terraform plans
When including REPOSITORY
as one of the providers, you must use the Terraform name for the resource type.
Note
CloudFormation cannot be combined with AWS/AWS GovCloud runtime.
Input type (IaC only)¶
You only need to specify input_type
for rules using the REPOSITORY
provider.
Default:
tf
(Terraform HCL and JSON plans)tf_plan
(Terraform JSON plans)cfn
(CloudFormation templates)k8s
(Kubernetes manifests)
Resource type¶
Simple rules require the parameter resource_type = {resource}
, where {resource}
is the name of a single resource type.
Advanced rules require the parameter resource_type = "MULTIPLE"
, even if the rule only evaluates one resource type. The name(s) of the actual resource type(s) involved in the rule are specified in the Rego code.
The resource_type
can be defined in the Rego code, or externally via the UI, CLI, or API. See Specifying the resource type via UI, CLI, API.
Resource type names¶
How you specify the resource type depends on whether you want a rule to apply to runtime environments (provider: AWS
, AWS_GOVCLOUD
, AZURE
, GOOGLE
), repository environments (provider: REPOSITORY
), or both.
Runtime resources:
Use the Fugue name (e.g.,
AWS.S3.Bucket
) if you want the rule to apply only to runtime environments.Use the Terraform name (e.g.,
aws_s3_bucket
) if you want the rule to apply to runtime and Terraform HCL/plan repository environments.
IaC resources:
For Terraform HCL (
tf
) and Terraform JSON plans (tf_json
), use the Terraform name (e.g.,aws_s3_bucket
).For CloudFormation templates (
cfn
), use the CloudFormation name (e.g.,AWS::S3::Bucket
).For Kubernetes (
k8s
), use the name in the “KIND” column in the Kubernetes docs (e.g.,Pod
).
Specifying the resource type via UI, CLI, API¶
When using the UI: to create a rule for a REPOSITORY
provider, or multiple providers of any type, the Resource Type dropdown is automatically set to “Defined in code,” and you must define the resource_type
in the rule text (Rego code), e.g.:
resource_type = "aws_s3_bucket"
See Simple Rules and Advanced Rules.
When using the CLI to create a rule for the REPOSITORY
provider, or multiple providers of any type, the rule must be synced to Fugue via the fugue sync rules command and the resource type must be defined in the Rego code, e.g.:
resource_type = "aws_s3_bucket"
When using the API: to create a rule for a REPOSITORY
provider, or multiple providers of any type, the resource_type
request body parameter must be set to DEFINED_IN_CODE
and the resource type must be defined in the rule_text
body parameter (Rego code). For example, in this request body, note the resource_type
body parameter and the separate resource_type
property within the rule_text
body parameter:
{
"name": "Azure storage accounts must be tagged",
"source": "CUSTOM",
"description": "Azure storage accounts must have the environment tag set to staging",
"providers": ["AZURE", "REPOSITORY"],
"severity": "Informational",
"resource_type": "DEFINED_IN_CODE",
"rule_text": "resource_type = \"azurerm_storage_account\"\n\ndefault allow = false\n\nallow {\n input.tags.environment == \"staging\"\n}"
}
Rule metadata¶
Fugue supports the __rego__metadoc__
format for including rule metadata in Rego code. It is used for rules that are synced to Fugue via the fugue sync rules CLI command. (It’s also used with Regula.)
If metadata is provided when not using fugue sync rules
, it will be ignored. Use the UI, CLI fugue create rule command, or API to provide the required information instead.
Note
The HTTP header method of providing metadata in a rule is deprecated, though still supported for backwards compatibility. We recommend using the __rego__metadoc__
format instead, which supports multiple providers.
Metadata fields¶
The __rego__metadoc__
metadata format supports the following fields:
title
: Name of the rule; maps to therule_summary
field in a Regula reportdescription
: Brief description of the rulecustom
: Contains the following fields:providers
: List of one or more providers (AWS
,AWS_GOVCLOUD
,AZURE
,GOOGLE
, and/orREPOSITORY
)severity
: Severity of the rule (Informational
,Low
,Medium
,High
, orCritical
); optional field, defaults to “High”
Example:
__rego__metadoc__ := {
"title": "AWS S3 buckets must be tagged",
"description": "S3 buckets must have the tag key 'stage' and value 'prod'",
"custom": {
"providers": ["AWS", "REPOSITORY"],
"severity": "Medium"
}
}
The fugue sync rules command does not support comments within the __rego__metadoc__
object. You may add comments outside of the __rego__metadoc__
.
Regula supports comments within __rego__metadoc__
, but to ensure compatibility with fugue sync rules, we recommend moving comments outside __rego__metadoc__
.
Note
Regula supports the additional metadata fields id
and custom.controls
. Fugue currently ignores these fields.
Compatibility with Regula¶
If you’re writing a Fugue custom rule that will also be used with Regula, there are a couple extra steps to ensure compatibility.
These steps are optional for rules written strictly for Fugue runtime environments, as Fugue adds the information for you, but it’s a good practice to include them as part of writing any custom rule.
All rules¶
Add a package declaration at the very beginning of the rule, and make sure the package name starts with rules
:
package rules.bucketlabels
__rego__metadoc__ := {
"custom": {
"severity": "Medium",
"providers": ["GOOGLE"]
},
"description": "Google storage buckets should have stage:prod labels",
"title": "Google storage bucket labels"
}
resource_type = "google_storage_bucket"
default allow = false
allow {
input.labels.stage == "prod"
}
Simple rules¶
For simple rules, also ensure that there is a default
specification for the allow
or deny
rule, set to false
:
default allow = false
default deny = false
Advanced rules¶
For advanced rules, also import the Fugue library below the package declaration:
import data.fugue
Example Rules¶
For examples of simple and advanced custom rules, see our GitHub repo.
Managing Rules in the UI, CLI, and API¶
To learn how to manage rules in the UI, see Managing Custom Rules - UI.
To learn how to manage rules in the CLI, see Managing Custom Rules - CLI.
To learn how to manage rules in the API, see Managing Custom Rules - API.
How Deleted and Disabled Rules Affect Compliance¶
If you delete or disable a custom rule, the rule is not removed from an environment until after the next scan. The deleted or disabled rule continues to display in the environment’s compliance tabs and the pass/fail results count toward your compliance posture. After the next scan, the rule is removed from the environment and results are not counted toward your compliance posture.
Learning Rego¶
Below are some resources for learning Rego:
Rego documentation, for writing policy as code
Terraform documentation, for defining resources and attributes to evaluate within the Rego:
Additionally, consider using our open-source tool Fregot to enhance the process of writing Rego rules. Fregot allows you to easily evaluate, debug, and test custom rules (and more). For instructions, see Testing Custom Rules with Fregot.