Sentinel
Sentinel CLI Configuration File Syntax
The Sentinel CLI's configuration file can be used to control the behavior
of the simulator during apply
and
test
operations.
Usage
The configuration file is used in different ways depending on what operation you are trying to execute.
Apply
When using sentinel apply
, supply the configuration file by using the
-config=FILE
flag, where FILE
is the path to the configuration file. The
default is sentinel.json
.
See the apply command reference for more details.
Test
When using sentinel test, each file matching test/<policy>/*.json
is a
configuration file representing a single test case, where <policy>
is the name
of the policy being tested. Configure assertions for each test
case using the test section.
See the test command reference for more details.
Configuration File Reference
The format of the configuration file is JSON. The available keys are:
mock
- A map of mock import data.imports
- A map of available imports via import plugins.global
- Data that is inserted into the global scope.param
- Values for parameters defined in the policy.test
- Test cases for the test command.
Mock Imports
Mock imports allow running a policy with an import that you may not have access to or is too difficult to run. For example, it can be easier to mock data for Terraform Enterprise locally instead of having to run a workspace through a plan/policy check cycle.
Mock imports are specified in the mock
key, as a map to mock data, keyed by
the import name that you want to mock. For example, if you wanted to mock the
time
import, you could create an entry with the time
key pointing to the
data you want to mock.
The data can take one of two forms:
Mocking static data
Static data can be mocked directly by supplying a JSON object as the mock data.
Example:
{
"mock": {
"time": {
"now": {
"hour": 9,
"minute": 42
}
}
}
}
With the above configuration, the following policy would pass:
import "time"
main = time.now.hour == 9
Mocking with Sentinel code
There are some Sentinel types that static JSON data cannot mock, such as
functions, and maps that don't have string keys. To mock this data, you can use
a Sentinel file itself. In this case, the parameter to your import key is the
file with the Sentinel code in it, relative to the current working directory in
the event of apply
, or relative to the configuration file location in the
event of test
.
Note that main
is not required in a mock data file.
Example:
{
"mock": {
"foo": "mock-foo.sentinel"
}
}
mock-foo.sentinel
would contain:
bar = func() {
return "baz"
}
With the above configuration, the following policy would pass:
import "foo"
main = foo.bar() == "baz"
Imports
Imports allow you to run a real import plugin
with a policy. The sentinel
binary will launch the plugin, connect to it,
configure it, and execute it as needed by the policy.
Note the difference between this and mock imports above is that this configuration specifies real import plugins to execute. The mock data fakes an import with static data.
Imports are specified by the import
key. The value of this is a map
where the key is the name of the import and the value is another map with
configuration about that import. The configuration map has the following keys:
path
(string, required) - Path to the import plugin executable.args
(list of string, optional) - A list of arguments to pass to the executable when starting it.env
(map of string to string, optional) - A set of environmental variables to set when launching the plugin.config
(map, optional) - Configuration for the plugin itself. This is specific to each individual plugin. Please reference the documentation for the plugin for more information.
Example:
{
"imports": {
"time": {
"path": "/path/to/sentinel-import-time",
"config": { "fixed_time": 1504155600 }
}
}
}
With the above configuration, the following policy would pass assuming the import configuration is valid:
import "time"
main = time.now.day == 31
Global
Global data is injected directly into the global scope of the policy. This can be used to simulate global data that may be injected by a Sentinel-enabled application.
Global data is specified by the global
key. The value is a map of
variables to inject directly into the running policy.
Example:
{
"global": {
"time": {
"now": {
"day": 31
}
}
}
}
With the above configuration, the following policy would pass. Notice
that we don't have to do any import
. The values of global
are
injected directly into the global scope.
main = time.now.day == 31
Parameters
The param
section allows you to supply values for the
parameters found in a policy. Values
entered here will satisfy required parameters in a policy, in addition to
override any defaults. Note that any of the manual parameter value methods
supported by sentinel apply
will override the values set here.
{
"param": {
"foo": "bar"
}
}
Test Cases
Test cases specify the test cases for the test command.
Tests are specified by the test
key. The value of this is a map of
string to boolean. The key is the name of a rule and the value is the
expected value of that rule. If a rule is not specified, than any value is
allowed.
Example:
{
"test": {
"main": true,
"valid_day": false
}
}
For the policy:
valid_day = rule { 2 < 1 } # This is just an example!
main = rule { not valid_day }
For more information, read about the test command.