dsv-k8s

module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2022 License: Apache-2.0

README

Delinea DevOps Secrets Vault Kubernetes Secret Injector

Docker GitHub Package Registry Red Hat Quay

A Kubernetes Mutating Webhook that injects Secret data from Delinea DevOps Secrets Vault (DSV) into Kubernetes Secrets. The webhook can be hosted as a pod or as a stand-alone service.

The webhook works by intercepting CREATE and UPDATE Secret admissions and mutating the Secret with data from DSV. The webhook configuration consists of one or more role to Client Credential Tenant mappings. It updates Kubernetes Secrets based on annotations on the Secret itself.

The webhook uses the Golang SDK to communicate with the DSV API.

It was tested with Minikube and Minishift.

Configure

The webhook requires a JSON formatted list of role to Client Credential and Tenant mappings. The role is a simple name that does not relate to Kubernetes Roles. It simply selects which credentials to use to get the Secret from DSV.

{
  "my-role": {
    "credentials": {
      "clientId": "93d866d4-635f-4d4e-9ce3-0ef7f879f319",
      "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxx-xxxxx"
    },
    "tenant": "mytenant"
  },
  "default": {
    "credentials": {
      "clientId": "64241412-3934-4aed-af26-95b1eaba0e6a",
      "clientSecret": "xxxxxxxxxxxxxxxxxxxxxxxxx-xxxxxxxxxxx-xxxxx"
    },
    "tenant": "mytenant"
  }
}

NOTE: the injector uses the default role when it mutates a Kubernetes Secret that does not have a roleAnnotation. See below

Run

The injector is a Golang executable that runs a built-in HTTPS server hosting the Kubernetes Mutating Webhook Webservice.

$ /usr/bin/dsv-injector-svc -?
flag provided but not defined: -?
Usage of ./dsv-injector-svc:
  -cert string
        the path of the certificate file in PEM format (default "injector.pem")
  -hostport string
        the host:port e.g. localhost:8080 (default ":18543")
  -key string
        the path of the certificate key file in PEM format (default "injector.key")
  -roles string
        the path of JSON formatted roles file (default "roles.json")

Thus the injector can run "anywhere," but, typically, the injector runs as a POD in the Kubernetes cluster that uses it.

Build

NOTE: Building the dsv-injector image is not required to install it as it is available on multiple public registries.

Building the injector requires Docker or Podman. To build it, run:

make image
Minikube and Minishift

Remember to run eval $(minikube docker-env) in the shell to push the image to Minikube's Docker daemon.💡 Likewise for Minishift except its eval $(minishift docker-env).

To publish the image to the Minikube (or Minishift) registry, enable it:

minikube addons enable registry

Then start Minikube's tunnel in a separate terminal to make the service available on the host.

minikube tunnel

It will run continuously. Stopping it will render the registry inaccessible.

Publish

NOTE: Publishing is not required unless the cluster cannot download the image from the internet.

To publish, set $(REGISTRY) to the target registry, e.g., registry.example.com/myusername:

make release REGISTRY=registry.example.com/me

The Makefile sets it using kubectl:

kubectl get -n kube-system service registry -o jsonpath="{.spec.clusterIP}{':'}{.spec.ports[0].port}"

Thus make release without setting $(REGISTRY) will assume that the cluster hosts a registry and will push the image there.

Install

Installation requires Helm.

The Makefile demonstrates a typical installation via the Helm chart. It imports roles.json as a file that it templates as a Kubernetes Secret for the injector.

The Helm values.yaml file image.repository is thycotic/dsv-injector:

image:
  repository: thycotic/dsv-injector
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: ""

That means, by default, make install will pull from Docker, GitHub, or Quay.

make install

However, the Makefile contains an install-image target that configures Helm to use the image built with make image:

make install-image

make uninstall uninstalls the Helm Chart.

make clean removes the Docker image.

Use

Once the injector is available in the Kubernetes cluster, and the MutatingAdmissionWebhook is in place, any appropriately annotated Kubernetes Secrets are modified on create and update.

The four annotations that affect the behavior of the webhook are:

const(
    roleAnnotation   = "dsv.thycotic.com/role"
    setAnnotation    = "dsv.thycotic.com/set-secret"
    addNotation      = "dsv.thycotic.com/add-to-secret"
    updateAnnotation = "dsv.thycotic.com/update-secret"
)

roleAnnotation selects the credentials that the injector uses to retrieve the DSV Secret. If the role is present, it must map to Client Credential and Tenant mapping. If the role is absent, the injector will use the default Credential and Tenant a mapping.

The setAnnotation, addAnnotation and updateAnnotation contain the path to the DSV Secret that the injector will use to mutate the Kubernetes Secret.

  • addAnnotation adds missing fields without overwriting or removing existing fields.
  • updateAnnotation adds and overwrites existing fields but does not remove fields.
  • setAnnotation overwrites fields and removes fields that do not exist in the DSV Secret.

NOTE: A Kubernetes Secret should specify only one of the "add," "update," or "set" annotations. The order of precedence is setAnnotation, then addAnnotation, then updateAnnotation when multiple are present.

Examples
---
apiVersion: v1
kind: Secret
metadata:
  name: example-secret
  annotations:
    dsv.thycotic.com/role: my-role
    dsv.thycotic.com/set-secret: /test/secret
type: Opaque
data:
  username: dW5tb2RpZmllZC11c2VybmFtZQ==
  domain: dW5tb2RpZmllZC1kb21haW4=
  password: dW5tb2RpZmllZC1wYXNzd29yZA==

The above example specifies a Role, so a mapping for that role must exist in the current webhook configuration. It uses the setAnnotation so the data in the injector will overwrite the existing contents of the Kubernetes Secret; if /test/secret contains a username and password but no domain, then the Kubernetes Secret would get the username and password from the DSV Secret Data but, the injector will remove the domain field.

There are more examples in the examples directory. Each one shows how each annotation works when run against an example with only a username and private-key in it but no domain.

Directories

Path Synopsis
pkg

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL