Enable the Policy Engine in Armory Continuous Deployment or Spinnaker
Overview of the Armory Policy Engine
The Armory Policy Engine is a proprietary feature for Armory Continuous Deployment and open source Spinnaker. It is designed to enable more complete control of your software delivery process by providing you with the hooks necessary to make assertions about the structure and behavior of pipelines and processes in your environment. The Policy Engine uses the Open Policy Agent (OPA) and input style documents to perform validations on the following:
- Save time validation - Validate pipelines as they’re created or modified. Tasks with no policies are not validated.
- Runtime validation - Validate deployments as a pipeline is executing. Tasks with no policies are not validated.
- Entitlements using API Authorization - Enforce restrictions on who can perform certain actions. Note that if you enable policies for API authorization, you must configure who can make API calls or else the API service (Gate) rejects all API calls.
If no policies are configured for these policy checks, all actions are allowed.
At a high level, adding policies for the Policy Engine to use is a two-step process:
- Create the policies and save them to a
.rego
file. - Add the policies to the OPA server with a ConfigMap or API request.
These policies are evaluated against the packages that Armory Continuous Deployment sends between its services. For a list of packages that you can write policies against, see Policy Engine Packages.
Enabling the Policy Engine consists of the following steps:
Before you begin
- The Policy Engine requires an Open Policy Agent (OPA) server, version 0.12.x or later. You can use the example on this page to deploy a server in the same Kubernetes cluster as Armory Continuous Deployment. Alternately, see the OPA documentation for information about how to deploy an OPA server. Specifically, the OPA v1 API must be available.
- You have identified the Policy Engine plugin that is compatible with your version of Armory Continuous Deployment or Spinnaker. See the Supported versions section.
- If you are using Spinnaker, you are familiar with installing and using plugins in Spinnaker.
Supported versions
Armory CD (Spinnaker) Version | Armory Policy Agent Plugin Version |
---|---|
2.28.x (1.28.x) | 0.2.2 |
2.27.x (1.27.x) | 0.2.1 |
2.26.x (1.26.x) | 0.1.6 |
Deploy an OPA server
The Policy Engine supports the following OPA server deployments:
- An OPA server deployed in the same Kubernetes cluster as an Armory CD or Spinnaker deployment. The Use ConfigMaps for Open Policy Agent policies section contains a ConfigMap you can use.
- An OPA cluster that is not in the same Kubernetes cluster as an Armory CD or Spinnaker deployment. See the OPA documentation for more information about installing an OPA server in a separate cluster.
Use ConfigMaps for Open Policy Agent policies
If you want to use ConfigMaps for OPA policies, you can use the following manifest as a starting point. This example manifest deploys an OPA server and applies the configuration for things like RoleBinding and a static DNS. When using the example, keep the following guidelines in mind:
- The manifest does not configure any authorization requirements for the OPA server it deploys. This means that anyone can add a policy.
- The manifest deploys the OPA server to a namespace called
opa
. - The OPA server uses
"--require-policy-label=true"
. This configures the OPA server to look for a specific label so that it does not check all ConfigMaps for new policies. For information about how to apply the relevant label to your policy ConfigMaps, see Add the policy to your OPA server.
Show the manifest
---
apiVersion: v1
kind: Namespace
metadata:
name: opa # Change this to install OPA in a different namespace
---
# Grant service accounts in the 'opa' namespace read-only access to resources.
# This lets OPA/kube-mgmt replicate resources into OPA so they can be used in policies.
# The subject name should be `system:serviceaccounts:` where `` is the namespace where OPA will be installed
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: opa-viewer-spinnaker
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:serviceaccounts:opa # Change this to the namespace OPA is installed in
apiGroup: rbac.authorization.k8s.io
---
# Define role in the `opa` namespace for OPA/kube-mgmt to update configmaps with policy status.
# The namespace for this should be the namespace where policy configmaps will be created
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: opa # Change this to the namespace where policies will live
name: configmap-modifier
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["update", "patch"]
---
# Bind the above role to all service accounts in the `opa` namespace
# The namespace for this should be the namespace where policy configmaps will be created
# The subject name should be `system:serviceaccounts:` where `` is the namespace where OPA will be installed
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: opa # Change this to the namespace where policies will live
name: opa-configmap-modifier
roleRef:
kind: Role
name: configmap-modifier
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
name: system:serviceaccounts:opa # Change this to the namespace OPA is installed in
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: opa-deployment
namespace: opa # Change this to the namespace OPA is installed in
labels:
app: opa
spec:
replicas: 1
selector:
matchLabels:
app: opa
template:
metadata:
labels:
app: opa
spec:
containers:
# WARNING: OPA is NOT running with an authorization policy configured. This
# means that clients can read and write policies in OPA. If you are
# deploying OPA in an insecure environment, be sure to configure
# authentication and authorization on the daemon. See the Security page for
# details: https://www.openpolicyagent.org/docs/security.html.
- name: opa
image: openpolicyagent/opa:0.28.0
args:
- "run"
- "--server"
- "--addr=http://0.0.0.0:8181"
readinessProbe:
httpGet:
path: /health
scheme: HTTP
port: 8181
initialDelaySeconds: 3
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
scheme: HTTP
port: 8181
initialDelaySeconds: 3
periodSeconds: 5
- name: kube-mgmt
image: openpolicyagent/kube-mgmt:0.9
args:
# Change this to the namespace where you want OPA to look for policies
- "--policies=opa"
# Configure the OPA server to only check ConfigMaps with the relevant label
- "--require-policy-label=true"
---
# Create a static DNS endpoint for Spinnaker to reach OPA
apiVersion: v1
kind: Service
metadata:
name: opa
namespace: opa # Change this to the namespace OPA is installed in
spec:
selector:
app: opa
ports:
- protocol: TCP
port: 8181
targetPort: 8181
Enable the Policy Engine plugin
You have three options for enabling the Policy Engine plugin:
- Armory Operator or Spinnaker Operator
- Spinnaker services local files (Spinnaker only)
- Halyard (Spinnaker only)
Armory Operator or Spinnaker Operator
You can enable the Policy Engine plugin using the Armory Operator or the Spinnaker Operator and the sample manifest, which uses Kustomize and is in the spinnaker-kustomize-patches repository.
-
The sample manifest is for the Armory Operator and Armory CD. If you are using the Spinnaker Operator and Spinnaker, you must replace the
apiVersion
value “spinnaker.armory.io/” with “spinnaker.io/”. For example:- Armory Operator:
apiVersion: spinnaker.armory.io/v1alpha2
- Spinnaker Operator:
apiVersion: spinnaker.io/v1alpha2
- Armory Operator:
-
In the
gate.spinnaker.extensibility.deck-proxy.plugins.Armory.PolicyEngine.version
entry, make sure to replace the version number listed after&version
with the version of the plugin you want to use. For example, if you are using Armory CD 2.27.x (Spinnaker 1.27.x), you would use version 0.2.1:gate: spinnaker: extensibility: plugins: Armory.PolicyEngine: enabled: true deck-proxy: enabled: true plugins: Armory.PolicyEngine: enabled: true version: &version 0.2.1
If you don’t use Kustomize, you should manually patch your SpinSvc
config with the entries in the sample manifest.
Show the manifest
#------------------------------------------------------------------------------
# Example configuration for enabling the Policy Agent plugin to enforce rules
# in Armory Enterprise pipelines.
#
# Feature documentation:
# https://docs.armory.io/continuous-deployment/armory-admin/policy-engine/policy-engine-enable/policy-engine-plug-enable/
#
# Make sure you check the plugin compatibility for each release before deciding
# on a version. For example, for Armory Enterprise 2.28.1 you can find the
# matrix here:
# https://docs.armory.io/continuous-deployment/release-notes/rn-armory-spinnaker/armoryspinnaker_v2-28-1/#plugin-compatibility
#
# Actual policies are defined in the "policies" folder and loaded into a
# ConfigMap.
#------------------------------------------------------------------------------
apiVersion: spinnaker.armory.io/v1alpha2 # Replace this value with spinnaker.io/v1alpha2 if you are using Spinnaker and the Spinnaker Operator
kind: SpinnakerService
metadata:
name: spinnaker
spec:
spinnakerConfig:
profiles:
# Configs in the spinnaker profile get applied to all services
spinnaker:
armory:
policyEngine:
opa:
# Replace with the actual URL to your Open Policy Agent deployment
baseUrl: http://opa:8181/v1/data
# Optional. The number of seconds that the Policy Engine will wait for a response from the OPA server. Default is 10 seconds if omitted.
# timeoutSeconds: <integer>
spinnaker:
extensibility:
repositories:
policyEngine:
enabled: true
url: https://raw.githubusercontent.com/armory-plugins/policy-engine-releases/master/repositories.json
gate:
spinnaker:
extensibility:
plugins:
Armory.PolicyEngine:
enabled: true
deck-proxy:
enabled: true
plugins:
Armory.PolicyEngine:
enabled: true
version: &version 0.2.0
orca:
spinnaker:
extensibility:
plugins:
Armory.PolicyEngine:
enabled: true
version: *version
front50:
spinnaker:
extensibility:
plugins:
Armory.PolicyEngine:
enabled: true
version: *version
clouddriver:
spinnaker:
extensibility:
plugins:
Armory.PolicyEngine:
enabled: true
version: *version
Timeout settings
You can configure the amount of time that the Policy Engine waits for a response from your OPA server. If you have network or latency issues, increasing the timeout can make Policy Engine more resilient. Use spec.spinnakerConfig.profiles.spinnaker.armory.policyEngine.opa.timeoutSeconds
to set the timeout in seconds. The default timeout is 10 seconds if you omit the config.
Spinnaker services local files
Warning
The Policy Engine plugin extends Orca, Gate, Front50, Clouddriver, and Deck. To avoid each service restarting and downloading the plugin, do not add the plugin using Halyard. Instead, configure the plugin in the service’s local profile.The Policy Engine plugin extends Orca, Gate, Front50, Clouddriver, and Deck. You must create or update the extended service’s local profile in the same directory as the other Halyard configuration files. This is usually ~/.hal/default/profiles
on the machine where Halyard is running.
-
Add the following to
gate-local.yml
,orca-local.yml
,front50-local.yml
, andclouddriver.yml
:armory: policyEngine: failOpen: false opa: # Replace with the actual URL to your Open Policy Agent deployment baseUrl: http://localhost:8181/v1/data # Optional. The number of seconds that the Policy Engine will wait for a response from the OPA server. Default is 10 seconds if omitted. # timeoutSeconds: <integer> spinnaker: extensibility: plugins: Armory.PolicyEngine: enabled: true policyEngine: url: https://raw.githubusercontent.com/armory-plugins/pluginRepository/master/repositories.json
-
Save your files and apply your changes by running
hal deploy apply
.
Halyard
Warning
The Policy Engine plugin extends Orca, Gate, Front50, Clouddriver, and Deck. When Halyard adds a plugin to a Spinnaker installation, it adds the plugin repository information to each service. This means that when you restart Spinnaker, each service restarts, downloads the plugin, and checks if an extension exists for that service. Each service restarting is not ideal for large Spinnaker installations due to service restart times. Clouddriver can take an hour or more to restart if you have many accounts configured.-
Add the plugins repository
hal plugins repository add policyEngine \ --url=https://raw.githubusercontent.com/armory-plugins/pluginRepository/master/repositories.json
This creates the following entry in your
.hal/config
:repositories: policyEngine: enabled: true url: https://raw.githubusercontent.com/armory-plugins/pluginRepository/master/repositories.json
-
Add the plugin
Be sure to replace
<version>
with the version that’s compatible with your Spinnaker instance.hal plugins add Armory.PolicyEngine --version=<version> --enabled=true
If you specified version 0.2.2, Halyard creates the following entry in your
.hal/config
file:spinnaker: extensibility: plugins: Armory.PolicyEngine: id: Armory.PolicyEngine enabled: true version: 0.2.2
-
Apply the changes by executing
hal deploy apply
.
Release notes
Show the release notes
- 0.2.2 - Fixed bug for createApplication button with Spinnaker 1.28, to be included in 2.28 release
- 0.2.1 - Fixed bug with the projects tab on deck for Armory Continuous Deployment 2.27.1 and later
- 0.2.0 - Update plugin to be compatible with Armory Continuous Deployment 2.27.0 and later.
- 0.1.6 - The Policy Engine Plugin is now generally available.
- If you are new to using the Policy Engine, use the plugin instead of the extension project.
- Entitlements using API Authorization no longer requires at least one policy. Previously, if you had no policies set, Policy Engine prevented any action from being taken. Now, Entitlements for Policy Engine allows any action to be taken if there are no policies set.
- 0.1.4 - Adds the
opa.timeoutSeconds
property, which allows you to configure how long the Policy Engine waits for a response from the OPA server. - 0.1.3 - Fixes an issue introduced in v0.1.2 where the Project Configuration button’s name was changing when Policy Engine is enabled.
- 0.1.2 - Adds support for writing policies against the package
spinnaker.ui.entitlements.isFeatureEnabled
to show/hide the following UI buttons:- Create Application
- Application Config
- Create Project
- 0.0.25 - Fixes an unsatisfied dependency error in the API (Gate) when using SAML and x509 certificates. This fix requires Armory Continuous Deployment 2.26.0 later.
- 0.0.19 - Adds forced authentication feature and fixes NPE bug
- 0.0.17 - Initial plugin release
What’s next
Feedback
Was this page helpful?
Thank you for letting us know!
Sorry to hear that. Please tell us how we can improve.
Last modified December 14, 2022: (501e971)