Skip to content

The-Migus-Group/tss-k8s

 
 

Repository files navigation

Delinea Secret Server Kubernetes Secret Injector

Docker GitHub Package Registry Red Hat Quay

A Kubernetes Mutating Webhook that injects Secret data from Delinea Secret Server (TSS) 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 Secret Server. The webhook configuration is a set of role to Client Credential and Server mappings. It updates Kubernetes Secrets based on annotations on the Secret itself.

The webhook uses the Golang SDK to communicate with the Secret Server 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 Secret Server.

{
    "my-role": {
        "credentials": {
            "username": "appuser1",
            "password": "Password1!"
        },
        "tenant": "corpname"
    },
    "default": {
        "credentials": {
            "username": "appuser2",
            "password": "Password2!"
        },
        "ServerURL": "https://hostname/SecretServer"
    }
}

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/tss-injector-svc -?
flag provided but not defined: -?
Usage of ./tss-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 tss-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/tss-injector:

image:
  repository: thycotic/tss-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.

Helm and Make

The use of make is optional. Running helm install works too:

helm install --set-file rolesJson=configs/roles.json tss-injector charts/tss-injector

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   = "secretserver.delinea.com/role"
    setAnnotation    = "secretserver.delinea.com/set-secret"
    addNotation      = "secretserver.delinea.com/add-to-secret"
    updateAnnotation = "secretserver.delinea.com/update-secret"
)

roleAnnotation selects the credentials that the injector uses to retrieve the Secret Server 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 specify the numeric ID of the Secret Server 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 Secret Server 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:
    secretserver.delinea.com/role: my-role
    secretserver.delinea.com/set-secret: "1"
type: Opaque
data:
  username: dW5tb2RpZmllZC11c2VybmFtZQ==
  private-key: b21pdHRlZAo=

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 the Secret with ID 1 contains a username and password but no domain, then the Kubernetes Secret would get the username and password from the Secret Server Secret but, the injector will remove the domain field.

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

About

A Delinea Secret Server Kubernetes Secrets Injector

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Go 65.5%
  • Smarty 15.9%
  • Makefile 15.8%
  • Dockerfile 2.8%