ShieldGuard provides a CLI tool sg
for running policy checks.
sg
is available on Linux, Mac OS and Windows. We can download the pre-built binaries
from release page.
sg
is written in Go. We can install it from source code:
$ go install github.com/Azure/ShieldGuard/sg@latest
Once we successfully installed sg
, we can invoke as:
$ sg -h
Enables best security practices for your project from day zero.
Usage:
sg [command]
Available Commands:
help Help about any command
test Test targets under the project.
Flags:
-h, --help help for sg
Use "sg [command] --help" for more information about a command.
Policy checks are expressed using Rego language, which are compiled and executed by Open Policy Agent (OPA).
We can use Rego to express a set of expectations to a collection of data.
In this tutorial, we will validate if a Kubernetes deployment spec is setting a required label app/name=<app-name-value>
.
The full sample and code can be found from ./samples/001-get-started.
In ShieldGuard, policies and data are organized into a project
: each project contains one ore more data targets and zero or more policies. These mappings are defined with sg-project.yaml
.
We can bootstrap a test project as follow:
$ mkdir -p 001-get-started/data 001-get-started/policy
$ cat <<EOF > 001-get-started/sg-project.yaml
files:
- name: 001-get-started
paths:
- data
policies:
- policy
EOF
ℹ️ In this project, we will store the data under the
data
folder, while putting policies under thepolicy
folder. We can update to different layouts in real world projects by specifying in thesg-project.yaml
.
Now, we will create two example deployment specs with following content:
$ cat <<EOF > 001-get-started/data/mysql-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
labels:
app/name: mysql
spec:
selector:
matchLabels:
component: mysql
strategy:
type: Recreate
template:
metadata:
labels:
component: mysql
spec:
containers:
- image: mysql:5.6
name: mysql
EOF
$ cat <<EOF > 001-get-started/data/postgres-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
spec:
selector:
matchLabels:
component: postgres
strategy:
type: Recreate
template:
metadata:
labels:
component: postgres
spec:
containers:
- image: postgres:15.1
name: postgres
EOF
ℹ️ In above two samples, the mysql deployment has the required label
app/name=mysql
, while postgres one is missing. We expect to usesg
to detect such issue in this tutorial.
$ cat <<EOF > 001-get-started/policy/001-app-name-required.rego
package main
deny_app_name_required[msg] {
input.apiVersion
input.metadata
not input.metadata.labels["app/name"]
msg := sprintf("app name label app/name is required for %s/%s .", [input.kind, input.metadata.name])
}
EOF
ℹ️ To learn more about Rego/OPA, please refer to the official guide.
With all the test data and policies ready, now we can invoke the test on this project:
$ sg test -c 001-get-started/sg-project.yaml ./001-get-started -o json
[
{
"filename": "data/mysql-app-deployment.yaml",
"namespace": "main",
"success": 1,
"failures": [],
"warnings": [],
"exceptions": []
},
{
"filename": "data/postgres-app-deployment.yaml",
"namespace": "main",
"success": 0,
"failures": [
{
"query": "data.main.deny_app_name_required",
"rule": {
"name": "app_name_required"
},
"message": "app name label app/name is required for Deployment/postgres ."
}
],
"warnings": [],
"exceptions": []
}
]
Error: test failed: found 1 failure(s), 0 warning(s)
As we can see, sg
failed because of the postgres deployment is missing the required app/name
label.
We can fix it by adding the label:
$ cat <<EOF > 001-get-started/data/postgres-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgres
labels:
app/name: postgres
spec:
selector:
matchLabels:
component: postgres
strategy:
type: Recreate
template:
metadata:
labels:
component: postgres
spec:
containers:
- image: postgres:15.1
name: postgres
EOF
Then re-run the test command:
$ sg test -c 001-get-started/sg-project.yaml ./001-get-started -o json
[
{
"filename": "data/mysql-app-deployment.yaml",
"namespace": "main",
"success": 1,
"failures": [],
"warnings": [],
"exceptions": []
},
{
"filename": "data/postgres-app-deployment.yaml",
"namespace": "main",
"success": 1,
"failures": [],
"warnings": [],
"exceptions": []
}
]
That's it! You have successfully defined and ran the test in your project. For next steps, please checkout our other guides.