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:

  • Providers

    • 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; or aws_vpc, aws_security_group; or AWS::EC2::Vpc, AWS::EC2::SecurityGroup). Note that the resource_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 runtime

  • AWS Terraform HCL

  • AWS Terraform plans

  • AWS GovCloud Terraform HCL

  • AWS GovCloud Terraform plans

AWS

Terraform name

tf_plan

  • AWS runtime

  • AWS Terraform plans

  • AWS GovCloud Terraform plans

AWS_GOVCLOUD

Fugue name

None

AWS GovCloud runtime

AWS_GOVCLOUD

Terraform name

None (defaults to tf)

  • AWS GovCloud runtime

  • AWS Terraform HCL

  • AWS Terraform plans

  • AWS GovCloud Terraform HCL

  • AWS GovCloud Terraform plans

AWS_GOVCLOUD

Terraform name

tf_plan

  • AWS GovCloud runtime

  • AWS Terraform plans

  • AWS GovCloud Terraform plans

AZURE

Fugue name

None

  • Azure runtime

  • Azure Government runtime

AZURE

Terraform name

None (defaults to tf)

  • Azure runtime

  • Azure Government runtime

  • Azure Terraform HCL

  • Azure Government Terraform HCL

  • Azure Terraform plans

  • Azure Government Terraform plans

AZURE

Terraform name

tf_plan

  • Azure runtime

  • Azure Government runtime

  • Azure Terraform plans

  • Azure Government Terraform plans

GOOGLE

Fugue name

None

Google runtime

GOOGLE

Terraform name

None (defaults to tf)

  • Google runtime

  • Google Terraform HCL

  • Google Terraform plans

GOOGLE

Terraform name

tf_plan

  • Google runtime

  • Google Terraform plans

REPOSITORY

Terraform name

None (defaults to tf)

  • Terraform HCL (platform according to resource type)

  • Terraform plans (platform according to resource type)

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 and REPOSITORY, with tf input, applies to all of:

    • AWS runtime

    • AWS Terraform HCL

    • AWS GovCloud Terraform HCL

    • AWS Terraform plans

    • AWS GovCloud Terraform plans

  • AZURE, GOOGLE, and REPOSITORY, with tf_plan input, applies to all of:

    • Azure runtime

    • Azure Government runtime

    • Google runtime

    • Azure Terraform plans

    • Azure Government Terraform plans

    • Google Terraform plans

  • AWS and AWS_GOVCLOUD, with tf 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 the rule_summary field in a Regula report

  • description: Brief description of the rule

  • custom: Contains the following fields:

    • providers: List of one or more providers (AWS, AWS_GOVCLOUD, AZURE, GOOGLE, and/or REPOSITORY)

    • severity: Severity of the rule (Informational, Low, Medium, High, or Critical); 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

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:

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.