Skip to content

controlplaneio/kubesec-webhook

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kubesec-webhook

Build Status

Kubesec.io admission controller for Kubernetes Pods, Deployments, DaemonSets and StatefulSets.

For the kubectl scan plugin see kubectl-kubesec

Install

Generate webhook configuration files with a new TLS certificate and CA Bundle:

make certs

Deploy the admission controller and webhooks in the kubesec namespace (requires Kubernetes 1.20 or newer):

make deploy

Enable Kubesec validation by adding this label:

kubectl label namespaces default kubesec-validation=enabled

Usage

Try to apply a privileged Deployment:

kubectl apply -f ./test/deployment.yaml

Error from server (InternalError): error when creating "./test/deployment.yaml":
Internal error occurred: admission webhook "deployment.admission.kubesec.io" denied the request:
deployment-test score is -30, deployment minimum accepted score is 0
Scan Result:
{
  "error": "",
  "score": -30,
  "scoring": {
    "critical": [
      {
        "selector": "containers[] .securityContext .privileged == true",
        "reason": "Privileged containers can allow almost completely unrestricted host access",
        "weight": 0
      }
    ],
    "advise": [
      {
        "selector": "containers[] .securityContext .runAsNonRoot == true",
        "reason": "Force the running image to run as a non-root user to ensure least privilege"
      },
      {
        "selector": "containers[] .securityContext .capabilities .drop",
        "reason": "Reducing kernel capabilities available to a container limits its attack surface",
        "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
        "reason": "An immutable root filesystem can prevent malicious binaries being added to
PATH and increase attack cost"
      },
      {
        "selector": "containers[] .securityContext .runAsUser \u003e 10000",
        "reason": "Run as a high-UID user to avoid conflicts with the host's user table"
      },
      {
        "selector": "containers[] .securityContext .capabilities .drop | index(\"ALL\")",
        "reason": "Drop all capabilities and add only those required to reduce syscall attack surface"
      }
    ]
  }
}

Try to apply a privileged DaemonSet:

kubectl apply -f ./test/daemonset.yaml

Error from server (InternalError): error when creating "./test/daemonset.yaml":
Internal error occurred: admission webhook "daemonset.admission.kubesec.io" denied the request:
daemonset-test score is -30, daemonset minimum accepted score is 0
Scan Result:
{
  "error": "",
  "score": -30,
  "scoring": {
    "critical": [
      {
        "selector": "containers[] .securityContext .privileged == true",
        "reason": "Privileged containers can allow almost completely unrestricted host access",
        "weight": 0
      }
    ],
    "advise": [
      {
        "selector": "containers[] .securityContext .runAsNonRoot == true",
        "reason": "Force the running image to run as a non-root user to ensure least privilege"
      },
      {
        "selector": "containers[] .securityContext .capabilities .drop",
        "reason": "Reducing kernel capabilities available to a container limits its attack surface",
        "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
        "reason": "An immutable root filesystem can prevent malicious binaries being added to PATH and increase attack cost"
      },
      {
        "selector": "containers[] .securityContext .runAsUser \u003e 10000",
        "reason": "Run as a high-UID user to avoid conflicts with the host's user table"
      },
      {
        "selector": "containers[] .securityContext .capabilities .drop | index(\"ALL\")",
        "reason": "Drop all capabilities and add only those required to reduce syscall attack surface"
      }
    ]
  }
}

Try to apply a privileged StatefulSet:

kubectl apply -f ./test/statefulset.yaml

Error from server (InternalError): error when creating "./test/statefulset.yaml":
Internal error occurred: admission webhook "statefulset.admission.kubesec.io" denied the request:
statefulset-test score is -30, statefulset minimum accepted score is 0
Scan Result:
{
  "error": "",
  "score": -30,
  "scoring": {
    "critical": [
      {
        "selector": "containers[] .securityContext .privileged == true",
        "reason": "Privileged containers can allow almost completely unrestricted host access",
        "weight": 0
      }
    ],
    "advise": [
      {
        "selector": ".spec .volumeClaimTemplates[] .spec .accessModes | index(\"ReadWriteOnce\")",
        "reason": ""
      },
      {
        "selector": "containers[] .securityContext .runAsNonRoot == true",
        "reason": "Force the running image to run as a non-root user to ensure least privilege"
      },
      {
        "selector": "containers[] .securityContext .capabilities .drop",
        "reason": "Reducing kernel capabilities available to a container limits its attack surface",
        "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/"
      },
      {
        "selector": "containers[] .securityContext .readOnlyRootFilesystem == true",
        "reason": "An immutable root filesystem can prevent malicious binaries being added to
PATH and increase attack cost"
      },
      {
        "selector": "containers[] .securityContext .runAsUser \u003e 10000",
        "reason": "Run as a high-UID user to avoid conflicts with the host's user table"
      }
    ]
  }
}

Configuration

You can set the minimum Kubesec.io score in ./deploy/webhook/yaml:

apiVersion: apps/v1beta1
kind: Deployment
metadata:
  name: kubesec-webhook
  labels:
    app: kubesec-webhook
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: kubesec-webhook
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8081"
    spec:
      containers:
        - name: kubesec-webhook
          image: controlplaneio/kubesec:0.1-dev
          imagePullPolicy: Always
          command:
            - ./kubesec
          args:
            - -tls-cert-file=/etc/webhook/certs/cert.pem
            - -tls-key-file=/etc/webhook/certs/key.pem
            - -min-score=0
          ports:
            - containerPort: 8080
            - containerPort: 8081
          volumeMounts:
            - name: webhook-certs
              mountPath: /etc/webhook/certs
              readOnly: true
      volumes:
        - name: webhook-certs
          secret:
            secretName: kubesec-webhook-certs

Monitoring

The admission controller exposes Prometheus RED metrics for each webhook a Grafana dashboard is available here.

Credits

Kudos to Xabier for the awesome kubewebhook library.

About

Security risk analysis for Kubernetes resources

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 10