This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Providers

Providers are the policy engines which evaluate the input data from the specified domain. Currently supported Providers are:

  • OPA (Open Policy Agent)
  • Kyverno

The provider block of a Lula Validation is given as follows, where the sample is indicating the OPA provider is in use:

# ... Rest of Lula Validation
provider:
    type: opa   # opa or kyverno accepted
    opa-spec:
        # ... Rest of opa-spec
# ... Rest of Lula Validation

Each domain specification retreives a specific dataset, and each will return that data to the selected Provider in a domain-specific format. However, this data will always take the form of a JSON object when input to a Provider. For that reason, it is important that Domain and Providerspecifications are not built wholly independently in a given Validation.

1 - Kyverno Provider

The Kyverno provider provides Lula with the capability to evaluate the domain in against a Kyverno policy.

Payload Expectation

The validation performed should use the form of provider with the type of kyverno and using the kyverno-spec, along with a valid domain.

Example:

domain: 
  type: kubernetes
  kubernetes-spec:
    resources:
    - name: podsvt
      resource-rule:
        group:
        version: v1
        resource: pods
        namespaces: [validation-test]
provider: 
  type: kyverno
  kyverno-spec:
    policy:
      apiVersion: json.kyverno.io/v1alpha1          # Required
      kind: ValidatingPolicy                        # Required
      metadata:
        name: pod-policy                            # Required
      spec:
        rules:
          - name: no-latest                         # Required
            # Match payloads corresponding to pods
            match:                                  # Optional
              any:                                  # Assertion Tree
              - apiVersion: v1
                kind: Pod
            assert:                                 # Required
              all:                                  # Assertion Tree
              - message: Pod `{{ metadata.name }}` uses an image with tag `latest`
                check:
                  ~.podsvt:
                    spec:
                      # Iterate over pod containers
                      # Note the `~.` modifier, it means we want to iterate over array elements in descendants
                      ~.containers:
                        image:
                          # Check that an image tag is present
                          (contains(@, ':')): true
                          # Check that the image tag is not `:latest`
                          (ends_with(@, ':latest')): false

You can have mutiple policies defined. Optionally, output.validation can be specified in the kyverno-spec to control which (Policy, Rule) pair control validation allowance/denial, which is in the structure of a comma separated list of rules: policy-name1.rule-name-1,policy-name-1.rule-name-2. If you have a desired observation to include, output.observations can be added to payload to observe violations by a certain (Policy, Rule) pair such as:

domain: 
  type: kubernetes
  kubernetes-spec:
    resources:
    - name: podsvt
      resource-rule: 
        group: 
        version: v1 
        resource: pods
        namespaces: [validation-test] 
provider: 
  type: kyverno
  kyverno-spec:
    policy:
      apiVersion: json.kyverno.io/v1alpha1
      kind: ValidatingPolicy
      metadata:
        name: labels
      spec:
        rules:
        - name: foo-label-exists
          assert:
            all:
            - check:
                ~.podsvt:
                  metadata:
                    labels:
                      foo: bar
    output:
      validation: labels.foo-label-exists
      observations:
      - labels.foo-label-exists

The validatation and observations fields must specify a (Policy, Rule) pair. These observations will be printed out in the remarks section of relevant-evidence in the assessment results.

2 - OPA Provider

The OPA provider provides Lula with the capability to evaluate the domain against a rego policy.

Payload Expectation

The validation performed should use the form of provider with the type of opa and using the opa-spec, along with a valid domain.

Example:

domain: 
  type: kubernetes
  kubernetes-spec:
    resources:
    - name: podsvt
      resource-rule:
        group:
        version: v1
        resource: pods
        namespaces: [validation-test]
provider:
  type: opa
  opa-spec:
    rego: |                                   # Required - Rego policy used for data validation
      package validate                        # Required - Package name

      import future.keywords.every            # Optional - Any imported keywords

      validate {                              # Required - Rule Name for evaluation - "validate" is the only supported rule
        every pod in input.podsvt {
          podLabel == "bar"
        }
      }

Optionally, an output can be specified in the opa-spec. Currently, the default validation allowance/denial is given by validate.validate, which is really of the structure <package-name>.<json-path-to-boolean-variable>. If you have a desired alternative validation boolean variable, as well as additional observations to include, an output can be added such as:

domain: 
  type: kubernetes
  kubernetes-spec:
    resource-rules: 
    - group: 
      version: v1 
      resource: pods
      namespaces: [validation-test] 
provider:
  type: opa
  opa-spec:
    rego: |
      package mypackage 

      result {
        input.kind == "Pod"
        podLabel := input.metadata.labels.foo
        podLabel == "bar"
      }
      test := "my test string"
    output:
      validation: mypackage.result
      observations:
      - validate.test

The validatation field must specify a json path that resolves to a boolean value. The observations array currently only support variables that resolve as strings. These observations will be printed out in the remarks section of relevant-evidence in the assessment results.

Policy Creation

The required structure for writing a validation in rego for Lula to validate is as follows:

rego: |
  package validate 

  validate {

  }

This structure can be utilized to evaluate an expression directly:

rego: |
  package validate 

  validate {
    input.kind == "Pod"
    podLabel := input.metadata.labels.foo
    podLabel == "bar"
  }

The expression can also use multiple rule bodies as such:

rego: |
  package validate

  foolabel {
    input.kind == "Pod"
    podLabel := input.metadata.labels.foo
    podLabel == "bar"
  }

  validate {
    foolabel
  }

[!IMPORTANT] package validate and validate are required package and rule for Lula use currently when an output.validation value has not been set.