OPA to Integrate with Kubernetes Admission Control → Ingresses: Restrict Hostnames

What Is OPA?

It is a project that started in 2016 to unify policy enforcement across different technologies and systems. Today, OPA is used by giant players within the tech industry. For example, Netflix uses OPA to control its internal API resources. Chef uses it to provide IAM capabilities in their end-user products. In addition, many other companies like Cloudflare, Pinterest, and others use OPA to enforce policies on their platforms (like Kubernetes clusters). Currently, OPA is part of CNCF as an incubating project.

Introduction to OPA:

The Open Policy Agent (OPA, pronounced “oh-pa”) is an open-source, general-purpose policy engine that unifies policy enforcement across the stack. OPA provides a high-level declarative language that lets you specify policy as code and simple APIs to offload policy decision-making from your software. You can use OPA to enforce policies in microservices, Kubernetes, CI/CD pipelines, API gateways, and more.

Image Source: OPA Architecture

Download OPA:

To get started, download an OPA binary for your platform from GitHub releases:

On macOS (64-bit):

curl -L -o opa https://openpolicyagent.org/downloads/v0.36.1/opa_darwin_amd64

On Linux (64-bit):

curl -L -o opa https://openpolicyagent.org/downloads/v0.36.1/opa_linux_amd64_static

Set permissions on the OPA executable:

chmod 755 ./opa

OPA includes an interactive shell or REPL (Read-Eval-Print-Loop). You can use the REPL to experiment with policies and prototype new ones.

To start the REPL just:

./opa run

What Does OPA Bring To The Table?

You may be wondering: How did OPA come about? What problems does it try to solve? Indeed, policy enforcement over APIs and microservices is as old as microservices themselves. There’s never been a production-grade application that didn’t enforce access control, authorization, and policy enforcement of some kind.

OPA Internals

To fully understand OPA and start implementing it in your projects, you must familiarize yourself with its features and components. So let’s start with how you define your policies.

Policy Language: Rego

Rego is a high-level declarative language that was explicitly built for OPA. It makes it very easy to define policies and address questions like:

is Bob allowed to perform a GET request on /api/v1/products?

Which records is he allowed to view?

Let’s look at Kubernetes as an example:

  • Using Ingress controllers without TLS allows unencrypted, unsecured traffic to the application.

How do we do that?

We created a declarative policy language, Rego, a distributed authorization agent, Open Policy Agent (OPA), and a comprehensive control plane, Styra Declarative Authorization Service (DAS), to help you build, deploy and manage your policies and agents. We can quickly build, deploy, and manage policy for numerous use cases for things like Kubernetes admission control to application authorization policies with these tools.

Introduction to Styra DAS:

Styra automatically monitors and enforces policies about the server and data center resources you put into production to ensure your organization meets its security, operational, compliance, and regulatory goals and requirements.

If Styra can address your organization’s specific requirements, (For example, when you put a Kubernetes cluster into production and want administrative guardrails to keep your deployment secure) your next step is to sign up for a service or service to request a downloadable package to install.

Before you get started, decide whether you want to do the following:

  • Register for a cloud-based Styra tenant that provides Software-as-a-Services (SaaS).
  • If you don’t have a Styra DAS tenant, you can sign up for a free tenant here(Signup)
  • Deploy the software on-site in your network, in a private cloud, or a public cloud instance you manage.

After this initial decision, the following steps you take to define, enforce, and monitor policies to safeguard your network and application resources are similar.

This tutorial guides you through the process of how to configure, validate, and publish rules.

Kubernetes Admission Control:

In Kubernetes, Admission Controllers enforce semantic validation of objects during create, update, and delete operations. With OPA, you can enforce custom policies on Kubernetes objects without recompiling or reconfiguring the Kubernetes API server.

This tutorial will define one Kubernetes audit and admission control rule that prevents users from creating conflicting inbound entry point ingresses for a system.

This specific rule is an example of a predefined built-in rule that implements a best practice. In this case, the rule helps you prevent an action—for example, a test application receiving internet traffic from a production application.

This tutorial guides you through the following basic tasks:

1. Add a system.

2. Install an agent.

3. Configure a built-in rule.

4. Validate your configuration.

5. Publish the rule in enforcing and monitoring modes.

This tutorial assumes that you are using the Open Policy Agent (OPA) to integrate with the Kubernetes admission control framework and that you access the Styra control plane using a cloud-based Styra tenant: <das-id>.styra.com for policy authoring, validation, and distribution.

In this scenario, OPA decides whether to allow or deny operations by evaluating your policies for Kubernetes resources each time the Kubernetes API is called.

Goals:

This tutorial shows how to enforce custom policies on Kubernetes objects using OPA. In this tutorial, you will define admission control rules that prevent users from creating Kubernetes Ingress objects that violate the following organization policy:

  • Ingress hostnames must be whitelisted on the Namespace containing the Ingress.
  • Two ingresses in different namespaces must not have the same hostname.

Prerequisites →Before you begin this tutorial, verify the following:

  • You must have Kubernetes 1.9 (or newer) installed. If you did not install Kubernetes, you could download minikube (version v0.28+) with Kubernetes 1.10 to run the tutorial locally.
  • You must have administrative access to the cloud-based Styra tenant: <das-id>.styra.com or have downloaded and installed Styra on your network or private cloud. Note: If you don’t have a Styra DAS tenant, you can sign up for a free tenant here(Signup).
  • If you have not installed a minikube and a Hypervisor locally, you can also download and install the minikube with HyperKit.

Installing Kubernetes:

For this tutorial, you must have a Kubernetes cluster available. For testing and evaluation purposes, you can start with the Kubernetes minikube.

  1. Download and install Kubernetes (minikube), if necessary. If you use minikube for this tutorial, use the following steps to set up a test environment.
  • Verify that virtualization is supported.
  • Install kubectl.
  • Install a virtualization Hypervisor.
  • Install minikube.

Start the minikube service by running the following command:

minikube start

Confirm the installation by running the following command:

minikube status

The following output is displayed only when your cluster is installed and running.

host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Steps: OPA to integrate with the Kubernetes admission control:

1. Add a System:

To connect your Kubernetes cluster to, you must create a new Styra System.

  1. Then, click the plus sign (+) next to the Systems section in the left navigation panel.
  2. Next, select a System type from the list of available types.
  3. For this tutorial, keep the default Kubernetes system-type as selected.
  4. Next, type a human-friendly System name that helps you identify the target for a set of policies.
  5. For example, if the System type is Kubernetes, you should provide a name that helps you recognize which Kubernetes cluster you are managing.
  6. Type an optional Description to provide additional details about this cluster.
  7. For example, if the System type is Kubernetes, you can also optionally set HTTPS, HTTP, and bypass proxy information for the cluster.
  8. Leave the Read-only switch ON to prevent other users from editing policy for this system using the policy control plane console.
  9. Leave the Launch Quick Start switch on. After this system is added, the QuickStart sidebar will guide you through configuring the system.
  10. Click Add System.

2.Install the Agent:

After you click Add System, the console displays the instructions for installing components onto the Kubernetes cluster in the styra-system namespace.

You can copy and paste the instructions from the console to run the commands in a terminal shell.

*NOTE: The command-line instructions displayed in the console are generated specifically for the Styra system you added in the above step.

To install the Styra OPA for a Kubernetes system:

  1. Configure helm (or helm3), if you are using helm as your package manager for Kubernetes applications.
  2. Configure kubectl to install the Styra OPA for the cluster, you want to connect to.
  3. You must copy and paste the commands into a terminal to do the following:
  • Add a label to the kube-system Namespace to prevent policies from being applied to it.
  • Install the Styra OPA.
Installation Steps for Styra on Kubernetes by using kubectl, helm,helm3 & kustomize

The following output is displayed on your terminal when installing the Styra OPA.

namespace/styra-system created
configmap/trusted-ca-certs created
secret/opa-server created
configmap/opa-config created
clusterrolebinding.rbac.authorization.k8s.io/opa-viewer created
service/opa created
deployment.apps/opa created
validatingwebhookconfiguration.admissionregistration.k8s.io/
opa-validating-webhook created
secret/styra-access created
configmap/datasources-agent-config created
clusterrole.rbac.authorization.k8s.io/read-all-global created
clusterrolebinding.rbac.authorization.k8s.io/datasources-agent-read-all created
deployment.apps/datasources-agent created

4. Configure kustomize if you are using kustomize to configure applications for running on the Kubernetes cluster.

3.Configure a built-in rule/Define a Policy:

For Kubernetes systems, you can start defining policies by selecting built-in rules that you can configure and deploy.

The built-in rules enable you to implement common security recommendations with little or no configuration. However, if any configuration is required, the built-in rules provide simple parameters that you can customize to suit your organization and operational goals.

*NOTE: You can always write your own custom rules if required. This tutorial, however, illustrates how to configure and deploy a built-in rule. In this case, the built-in rule prevents administrators, developers, and operators from deploying Ingress that may cause a conflict.

To configure the built-in rule:

  1. Under Systems in the left navigation panel, expand the system you added in Add a System.
  2. Expand Validating or Mutating, then select Rules.
  3. Click Add rule in the top section of the right pane.
  4. Start typing Ingress to display the list of rules related to Ingresses.
  5. Select the Ingresses: Restrict Hostnames rule.
Add rule by selecting →Ingresses: Restrict Hostnames rule (i.e builtin rule)
  1. Now, you have created a draft policy placed in Not configured mode. When making changes to systems, it is generally considered a best practice to evaluate the impact of the change before enforcing it. Therefore, change your drafted policy to Monitor mode, but do not publish the change yet. This will allow you to evaluate the effect of the policy before enforcing it.
  2. Finally, add the hostPaths .foo.com hooli.com in parameters (allow text box under the rule).

Policy

package policy["com.styra.kubernetes.validating"].rules.rulesenforce[decision] {
  parameters := {
    "whitelist": {
      ".foo.com hooli.com"
    }
  }data.library.v1.kubernetes.admission.network.v1.deny_ingress_hostname_not_in_whitelist[message]
    with data.library.parameters as parametersdecision := {
    "allowed": false,
    "message": message
  }
}

4. Validate to Analyze the Impact of the Policy:

Before you enforce the selected built-in rule, make sure to run some validation checks to see how your change will impact the cluster.

To see how deploying the policy affects the cluster:

  1. Click Validate button in the top section of the right pane.
  2. Verify that the Tests column displays No tests. This column is empty because you are working with a built-in rule and have not written any custom unit tests for the rule.
  3. If you write a custom rule, you also write unit tests for that rule and check the results for running those tests before deploying your rule.
  4. Verify the results in the Compliance column to see if any resources in your current cluster violate the policy.
  5. Verify the results in the Decisions column to see a list of previous admission control decisions that may have changed if the current policy were enforced.

Depending on your cluster, empty results will appear at the start. To illustrate a more typical result, you can create two identical ingresses with conflicting names.

To create two ingresses:

  1. Create a new file named ingress.yaml in a text editor.
  2. Copy and paste the following configuration settings into the ingress.yaml file:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: prod
spec:
  rules:
  - host: initech.com
    http:
        paths:
        - path: /finance
          pathType: Prefix
          backend:
            service:
                name: productpage
                port:
                    number: 80

3. Save the file and close the text editor.

4. Apply the configuration from the ingress.yaml file by running the following command:

kubectl apply -f ingress.yaml

*NOTE: You can successfully create the Ingress with an unapproved host because the Ingresses: Restrict Hostnames rule is not yet being enforced.

5. Click Validate to repeat the validation process and review the new results to see the compliance violations reported.

compliance violations reportes

5.Enforce the policy / Publish the rule in enforce and monitor modes:

After validating the potential impact of your policy and analyzing the results, you can make changes to the policy you want to deploy or to the configuration of your cluster before you are ready to start enforcing a policy. Once you are satisfied with the pre-deployment validation results, you can enforce the policy by clicking the Publish icon.

To enforce the policy:

  1. Change the Ingresses: Restrict Hostnames rule from Monitor to Enforce and then click Publish changes in the top section of the right pane.
  2. Confirm enforcement by clicking Publish changes.
  3. Try to recreate the ingressby deleting the existing one and creating it again with the following commands.
  • Delete ingress kubectl delete ingress prod.
  • Create ingress kubectl apply -f filename.yaml.
  1. Verify the error message from the API server saying that this new ingress conflicts with the other two.
Error message from the API server →new ingress conflicts with the other two
Verify the error message from the API server

View Activity on Dashboards:

Now that you have a policy deployed for a system, you can get a high-level, time-based view of the operations requested and the compliance violations detected using the Decisions and Compliance dashboards.

To view the activity on Dashboards:

  1. Click on a system name in the left navigation panel.
  2. Review the Decisions dashboard to see time-series data about the decisions made by the Open Policy Agent, including:
  • OPA has received the total number of operations requests as an admission controller.
  • How many operations are allowed?
  • How many operations are denied?
  • How many operations resulted in errors during policy evaluation (where OPA returned an error instead of allowing or denying).
  • The time required for OPA to make a decision.
Decisions dashboard →How many operations are allowed/denied.
  1. You can drill down into more details by clicking the Decisions tab to see a log of decisions made by OPA for admission control. You can filter the decision log using the Filter field at the bottom of the right pane, then expand individual decisions to see what inputs were provided to OPA when it made a decision.
Decisions tab to see a log of decisions made by OPA for admission control

2. Review the Compliance dashboard to see time-series data about the policy violations detected by the Open Policy Agent.

Summary:

You have completed the basic steps for getting started with Styra by deploying a policy for a Kubernetes cluster. Now, you have learned the basic steps involved and how to perform the following key tasks:

  • How to select built-in rules to define the policies that reflect your organization’s requirements.
  • How to validate the impact of policies on your cluster before enforcing them.
  • How to enforce policies once you are comfortable with the results.

References:

→Learn more about policy authoring at the Styra Academy — it’s FREE!

→The Open Policy Agent documentation has a lot more info on policy testing.

→If you want to add more essential policies for Kubernetes, check out openpolicyagent.org