Configuration allows you to author flexible Policy Packs that can be reused across your entire organization. As an organization administrator, you can use a single Policy Pack yet vary configuration (e.g. enforcement level, the allowed instance types, cost allowances, etc.) from one Policy Group to the next. For example, you may have a Policy Group for your non-production stacks that allow smaller instance types, while your Production Policy Group allows for use of large instance types.
The process of writing a configurable policy pack entails first creating the configuration schema for the Policy Pack or individual policies and then consuming the configuration from within your policy validation or remediation logic.
The Policy SDK will automatically make the enforcement levels of all policies configurable. You can configure the enforcement level for all policies in a Policy Pack or configure it for each individual policy. The top-level enforcement level under `all` will override the existing enforcement levels of all policies in the Policy Pack. A configured enforcement level for a specific policy will override the policy's existing enforcement level as well as the top-level configured enforcement level.
In the example configuration below, all policies in the Policy Pack would be `disabled` with the exception of the `a-policy` policy, which would be `mandatory`.
```json
{
"all": {
"enforcementLevel": "disabled"
},
"a-policy": {
"enforcementLevel": "mandatory"
}
}
```
As a convenience, when only configuring an enforcement level for a policy, its value can be specified directly. The above example could therefore also be written as:
Policy authors can denote the schema for a particular Policy's configuration using the {{<policy-configschema>}} field. The configuration schema uses [JSON Schema](https://json-schema.org/) to describe the acceptable configuration for a Policy.
At the top level, the {{<policy-configschema>}} for each Policy has only the `properties` and `required` arguments. Within `properties`, you may use the entire breadth of [validations keywords provided by the JSON Schema](https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.6). Validation keywords are fields like `minLength` and `maxLength` in the below example.
The below example shows a `ResourceValidationPolicy` that has an optional `message` config property, which must be between five and fifty characters. Then, from within the {{<policy-validateresource>}} function the configuration value can be accessed using {{<policy-args-getconfig>}}. All config properties are optional by default.
config["message"] = "Setting reasonable defaults is recommended!"
report_violation(f"Here is the configurable message: {config['message']}")
example_policy = ResourceValidationPolicy(
name="example-policy-with-schema",
description="Example policy with schema.",
config_schema=PolicyConfigSchema(
properties={
"message": {
"type": "string",
"minLength": 5,
"maxLength": 50,
},
}
),
validate=example_policy_validator,
)
```
{{% /choosable %}}
{{</chooser>}}
The schema in the above example includes an optional property. If the property value is not set, a reasonable message is set from within the {{<policy-validateresource>}} function. It's generally better to provide policies that have reasonable defaults and can run without setting any configuration values. Configuration should be used to change behavior or opt-in to more specific checks in the case that a specific configuration property is set. For example, a policy that checks encryption is enabled can be done without any configuration, but an optional configuration property for an "id of the encryption key" can be specified to further enforce that a specific key is being used for the encryption.
In some cases, you may need to require a property be set via configuration. This can be done by adding the property to the `required` list as shown in the example below.
If you are using the `pulumi` CLI to run local Policy Packs, you can store the configuration in a file and then use a flag to pass the file to the CLI.
With the above example Policy, we can write the following configuration to a `config.json` file:
```json
{
"all": "mandatory",
"example-policy-with-schema": {
"message": "Here is my message."
}
}
```
To run this Policy Pack locally with the configuration, you can run:
Configuration can also be added, edited and enabled via the Pulumi Cloud. Once a Policy Pack has been published to the Pulumi Cloud, organization administrators can enable the pack with configuration on a Policy Group using the console. Learn more in the [Enforcing a policy pack guide](/docs/using-pulumi/crossguard/get-started#enforcing-a-policy-pack).
If the selected Policy Pack has configuration, a form will appear for you to enter the configuration. The form provides automatic validation to ensure the supplied configuration meets the configuration schema.
The `pulumi` CLI can also be used to interact with Policy Packs enforced by the Pulumi Cloud. The CLI allows you to both validate configuration and enable Policy Packs with configuration files.
If the Policy Pack has already been published to the Pulumi Cloud, you can validate the configuration using the `pulumi policy validate-config` command.
Once you are satisfied with the configuration, (if Policy as Code is enabled for your organization) you can enable the Policy Pack and configuration for your organization's default Policy Group by running: