Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Install Open-policy-agent and create a ingress-conflicts policy. #242

Merged
merged 11 commits into from
Apr 12, 2019
32 changes: 32 additions & 0 deletions terraform/cloud-platform-components/opa.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
data "template_file" "values" {
template = "${file("${path.module}/templates/opa/values.yaml.tpl")}"
}

resource "helm_release" "open-policy-agent" {
name = "opa"
namespace = "opa"
repository = "stable"
chart = "opa"
version = "1.3.2"

values = [
"${data.template_file.values.rendered}",
]

lifecycle {
ignore_changes = ["keyring"]
}
}

resource "null_resource" "open-policy-agent_policies" {
depends_on = ["helm_release.open-policy-agent"]

provisioner "local-exec" {
command = "kubectl apply -n opa -f ${path.module}/resources/opa/"
}

provisioner "local-exec" {
when = "destroy"
command = "kubectl delete -n opa --ignore-not-found -f ${path.module}/resources/opa/"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This YAML applies a ConfigMap that contains the main OPA policy and default response.
# This policy is used as an entry-point for policy evaluations and returns allowed:true if policies are not matched to inbound data.

kind: ConfigMap
apiVersion: v1

metadata:
name: policy-default
namespace: opa
labels:
openpolicyagent.org/policy: rego
data:
main: |
package system

import data.cloud_platform.admission

main = {
"apiVersion": "admission.k8s.io/v1beta1",
"kind": "AdmissionReview",
"response": response,
}

default response = {"allowed": true}

response = {
"allowed": false,
"status": {
"reason": reason,
},
} {
reason := concat(", ", deny)
reason != ""
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# This policy prevents Ingress objects in different namespaces from sharing the same hostname.

kind: ConfigMap
apiVersion: v1
metadata:
name: policy-ingress-conflicts
namespace: opa
labels:
openpolicyagent.org/policy: rego
data:
ingress-conflicts.rego: |
package cloud_platform.admission

import data.kubernetes.ingresses

deny[msg] {
input.request.kind.kind == "Ingress"
host := input.request.object.spec.rules[_].host
other_hosts := data.kubernetes.ingresses[namespace][name].spec.rules[_].host
host == other_hosts
msg := sprintf("ingress host (%v) conflicts with ingress %v/%v", [host, namespace, name])
}
170 changes: 170 additions & 0 deletions terraform/cloud-platform-components/templates/opa/values.yaml.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Default values for opa.
# -----------------------
#
# The 'opa' key embeds an OPA configuration file. See
# https://www.openpolicyagent.org/docs/configuration.html for more details.
opa:
# services:
# controller:
# url: "https://www.openpolicyagent.org"
# bundle:
# service: controller
# name: "helm-kubernetes-quickstart"
# default_decision: "/helm_kubernetes_quickstart/main"

# To enforce mutating policies, change to MutatingWebhookConfiguration.
admissionControllerKind: ValidatingWebhookConfiguration

# To _fail closed_ on failures, change to Fail. During initial testing, we
# recommend leaving the failure policy as Ignore.
admissionControllerFailurePolicy: Fail

# To restrict the kinds of operations and resources that are subject to OPA
# policy checks, see the settings below. By default, all resources and
# operations are subject to OPA policy checks.
admissionControllerRules:
- operations: ["CREATE", "UPDATE"]
apiGroups: ["extensions"]
apiVersions: ["*"]
resources: ["ingresses"]

# Controls a PodDisruptionBudget for the OPA pod. Suggested use if having opa
# always running for admission control is important
podDisruptionBudget:
enabled: false
minAvailable: 1
# maxUnavailable: 1

# The helm Chart will automatically generate a CA and server certificate for
# the OPA. If you want to supply your own certificates, set the field below to
# false and add the PEM encoded CA certificate and server key pair below.
#
# WARNING: The common name name in the server certificate MUST match the
# hostname of the service that exposes the OPA to the apiserver. For example.
# if the service name is created in the "default" nanamespace with name "opa"
# the common name MUST be set to "opa.default.svc".
#
# If the common name is not set correctly, the apiserver will refuse to
# communicate with the OPA.
generateAdmissionControllerCerts: true
admissionControllerCA: ""
admissionControllerCert: ""
admissionControllerKey: ""

authz:
# Disable if you don't want authorization.
# Mostly useful for debugging.
enabled: true

# Docker image and tag to deploy.
image: openpolicyagent/opa
imageTag: 0.10.5
imagePullPolicy: IfNotPresent

mgmt:
enabled: true
image: openpolicyagent/kube-mgmt
imageTag: 0.8
imagePullPolicy: IfNotPresent
extraArgs: []
resources: {}
configmapPolicies:
enabled: true
namespaces: [opa] # kube-mgmt automatically discovers policies stored in ConfigMaps,created in a namespace listed here.
requireLabel: true
replicate:
# NOTE IF you use these, remember to update the RBAC rules above to allow
# permissions to replicate these things
cluster:
- "v1/namespaces"
namespace:
- "extensions/v1beta1/ingresses"
path: kubernetes

# Log level for OPA ('debug', 'info', 'error') (app default=info)
logLevel: info

# Log format for OPA ('text', 'json') (app default=text)
logFormat: text

# Number of OPA replicas to deploy. OPA maintains an eventually consistent
# cache of policies and data. If you want high availability you can deploy two
# or more replicas.
replicas: 1

# To control how the OPA is scheduled on the cluster, set the tolerations and
# nodeSelector values below. For example, to deploy OPA onto the master nodes:
#
# tolerations: [{key: "node-role.kubernetes.io/master", effect: NoSchedule, operator: Exists}]
# nodeSelector: {"kubernetes.io/role": "master"}
tolerations: []
nodeSelector: {}

# To control the CPU and memory resource limits and requests for OPA, set the
# field below.
resources: {}

rbac:
# If true, create & use RBAC resources
#
create: true
rules:
cluster:
- apiGroups:
- ""
resources:
- configmaps
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an additional comment, it's pretty bad the the helm chart will only set up a ClusterRole so we end up having to give it full access to configmaps. Since it will only ever need to parse configmaps from its own namespace, do you think it's worth the effort to extract this and create a Role and RoleBinding externally?

Copy link
Contributor

@alkar alkar Apr 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No we can't :(

open-policy-agent/kube-mgmt#11

@vijay-veeranki-moj has tested this and it's the same behaviour on the latest versions

verbs:
- update
alkar marked this conversation as resolved.
Show resolved Hide resolved
- patch
- get
- list
- watch
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- extensions
resources:
- ingresses
verbs:
- get
- list
- watch

serviceAccount:
# Specifies whether a ServiceAccount should be created
create: true
# The name of the ServiceAccount to use.
# If not set and create is true, a name is generated using the fullname template
name:

# This proxy allows opa to make Kubernetes SubjectAccessReview checks against the
# Kubernetes API. You can get a rego function at github.com/open-policy-agent/library
sar:
enabled: false
image: lachlanevenson/k8s-kubectl
imageTag: latest
imagePullPolicy: IfNotPresent
resources: {}

# To control the liveness and readiness probes change the fields below.
readinessProbe:
httpGet:
path: /
scheme: HTTPS
port: 443
initialDelaySeconds: 3
periodSeconds: 5
livenessProbe:
httpGet:
path: /
scheme: HTTPS
port: 443
initialDelaySeconds: 3
periodSeconds: 5