├── .gitignore ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── cmd └── kubesec │ └── main.go ├── deploy ├── gen-certs.sh ├── webhook-certs.yaml ├── webhook-registration.yaml ├── webhook-registration.yaml.tpl └── webhook.yaml ├── go.mod ├── go.sum ├── helm └── kubesec-webhook │ ├── .helmignore │ ├── Chart.yaml │ ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── tests │ │ └── test-connection.yaml │ └── webhook-certs-secrets.yaml │ └── values.yaml ├── pkg └── webhook │ ├── default_values.go │ ├── testdata │ ├── configmap.yaml │ ├── daemonset-hardened.yaml │ ├── daemonset-insecure.yaml │ ├── deployment-hardened.yaml │ ├── deployment-insecure.yaml │ ├── pod-hardened.yaml │ ├── pod-insecure.yaml │ ├── statefulset-hardened.yaml │ └── statefulset-insecure.yaml │ ├── webhook.go │ └── webhook_test.go └── test ├── daemonset.yaml ├── deployment.yaml ├── pod.yaml └── statefulset.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Temporary folder for creating certs 15 | deploy/certs -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.21-alpine AS builder 2 | COPY . /build 3 | WORKDIR /build 4 | RUN apk add --no-cache build-base && \ 5 | go test -race -v ./... && \ 6 | GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -tags netgo -a -v -o /build/kubesec-webhook /build/cmd/kubesec 7 | 8 | FROM alpine:3.18.4 9 | 10 | ENV USER=webhook 11 | ENV GROUP=webhook 12 | ENV HOMEDIR="/app" 13 | ENV UID=60000 14 | ENV GID=60000 15 | ENV SHELL='/sbin/nologin' 16 | 17 | #Usage: adduser [OPTIONS] USER [GROUP] 18 | # 19 | #Create new user, or add USER to GROUP 20 | # 21 | # -h DIR Home directory 22 | # -g GECOS GECOS field 23 | # -s SHELL Login shell 24 | # -G GRP Group 25 | # -S Create a system user 26 | # -D Don't assign a password 27 | # -H Don't create home directory 28 | # -u UID User id 29 | # -k SKEL Skeleton directory (/etc/skel) 30 | 31 | RUN addgroup -g "${GID}" "${GROUP}" && \ 32 | adduser \ 33 | -G ${GROUP} \ 34 | -D \ 35 | -g '' \ 36 | -h ${HOMEDIR} \ 37 | -s "${SHELL}" \ 38 | -u "${UID}" \ 39 | "${USER}" 40 | 41 | COPY --from=builder /build/kubesec-webhook /app/kubesec 42 | USER "${USER}" 43 | WORKDIR "${HOMEDIR}" 44 | 45 | ENTRYPOINT [ "/app/kubesec" ] 46 | 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Stefan Prodan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | NAME:=kubesec-webhook 2 | DOCKER_REPOSITORY:=controlplaneio 3 | DOCKER_IMAGE_NAME:=$(DOCKER_REPOSITORY)/$(NAME) 4 | GITREPO:=github.com/controlplaneio/kubesec-webhook 5 | GITCOMMIT:=$(shell git describe --dirty --always) 6 | VERSION:=0.1-dev 7 | 8 | .PHONY: build 9 | build: 10 | docker build -t $(DOCKER_IMAGE_NAME):$(VERSION) -f Dockerfile . 11 | 12 | .PHONY: push 13 | push: 14 | docker push $(DOCKER_IMAGE_NAME):$(VERSION) 15 | 16 | .PHONY: test 17 | test: 18 | cd pkg/webhook ; go test -v -race ./... 19 | 20 | .PHONY: certs 21 | certs: 22 | cd deploy && ./gen-certs.sh 23 | 24 | .PHONY: deploy 25 | deploy: 26 | kubectl create namespace kubesec --dry-run=client -oyaml | kubectl apply -f - 27 | kubectl apply -f ./deploy/ 28 | 29 | .PHONY: delete 30 | delete: 31 | kubectl delete namespace kubesec 32 | kubectl delete -f ./deploy/webhook-registration.yaml 33 | 34 | travis_push: 35 | @docker tag $(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_IMAGE_NAME):$(TRAVIS_BRANCH)-$(GITCOMMIT) 36 | @docker push $(DOCKER_IMAGE_NAME):$(TRAVIS_BRANCH)-$(GITCOMMIT) 37 | 38 | travis_release: 39 | @docker tag $(DOCKER_IMAGE_NAME):$(VERSION) $(DOCKER_IMAGE_NAME):$(TRAVIS_TAG) 40 | @docker push $(DOCKER_IMAGE_NAME):$(TRAVIS_TAG) 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kubesec-webhook 2 | 3 | [![Build Status](https://travis-ci.org/controlplaneio/kubesec-webhook.svg?branch=master)](https://travis-ci.org/controlplaneio/kubesec-webhook) 4 | 5 | Kubesec.io admission controller for Kubernetes Pods, Deployments, 6 | DaemonSets and StatefulSets. 7 | 8 | For the kubectl scan plugin see [kubectl-kubesec](https://github.com/controlplaneio/kubectl-kubesec) 9 | 10 | ## Install 11 | 12 | Generate webhook configuration files with a new TLS certificate and CA Bundle: 13 | 14 | ```bash 15 | make certs 16 | ``` 17 | 18 | Deploy the admission controller and webhooks in the kubesec namespace (requires Kubernetes 1.20 or newer): 19 | 20 | ```bash 21 | make deploy 22 | ``` 23 | 24 | Enable Kubesec validation by adding this label: 25 | 26 | ```bash 27 | kubectl label namespaces default kubesec-validation=enabled 28 | ``` 29 | 30 | ## Usage 31 | 32 | Try to apply a privileged Deployment: 33 | 34 | ```bash 35 | kubectl apply -f ./test/deployment.yaml 36 | 37 | Error from server (InternalError): error when creating "./test/deployment.yaml": 38 | Internal error occurred: admission webhook "deployment.admission.kubesec.io" denied the request: 39 | deployment-test score is -30, deployment minimum accepted score is 0 40 | Scan Result: 41 | { 42 | "error": "", 43 | "score": -30, 44 | "scoring": { 45 | "critical": [ 46 | { 47 | "selector": "containers[] .securityContext .privileged == true", 48 | "reason": "Privileged containers can allow almost completely unrestricted host access", 49 | "weight": 0 50 | } 51 | ], 52 | "advise": [ 53 | { 54 | "selector": "containers[] .securityContext .runAsNonRoot == true", 55 | "reason": "Force the running image to run as a non-root user to ensure least privilege" 56 | }, 57 | { 58 | "selector": "containers[] .securityContext .capabilities .drop", 59 | "reason": "Reducing kernel capabilities available to a container limits its attack surface", 60 | "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" 61 | }, 62 | { 63 | "selector": "containers[] .securityContext .readOnlyRootFilesystem == true", 64 | "reason": "An immutable root filesystem can prevent malicious binaries being added to 65 | PATH and increase attack cost" 66 | }, 67 | { 68 | "selector": "containers[] .securityContext .runAsUser \u003e 10000", 69 | "reason": "Run as a high-UID user to avoid conflicts with the host's user table" 70 | }, 71 | { 72 | "selector": "containers[] .securityContext .capabilities .drop | index(\"ALL\")", 73 | "reason": "Drop all capabilities and add only those required to reduce syscall attack surface" 74 | } 75 | ] 76 | } 77 | } 78 | ``` 79 | 80 | Try to apply a privileged DaemonSet: 81 | 82 | ```bash 83 | kubectl apply -f ./test/daemonset.yaml 84 | 85 | Error from server (InternalError): error when creating "./test/daemonset.yaml": 86 | Internal error occurred: admission webhook "daemonset.admission.kubesec.io" denied the request: 87 | daemonset-test score is -30, daemonset minimum accepted score is 0 88 | Scan Result: 89 | { 90 | "error": "", 91 | "score": -30, 92 | "scoring": { 93 | "critical": [ 94 | { 95 | "selector": "containers[] .securityContext .privileged == true", 96 | "reason": "Privileged containers can allow almost completely unrestricted host access", 97 | "weight": 0 98 | } 99 | ], 100 | "advise": [ 101 | { 102 | "selector": "containers[] .securityContext .runAsNonRoot == true", 103 | "reason": "Force the running image to run as a non-root user to ensure least privilege" 104 | }, 105 | { 106 | "selector": "containers[] .securityContext .capabilities .drop", 107 | "reason": "Reducing kernel capabilities available to a container limits its attack surface", 108 | "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" 109 | }, 110 | { 111 | "selector": "containers[] .securityContext .readOnlyRootFilesystem == true", 112 | "reason": "An immutable root filesystem can prevent malicious binaries being added to PATH and increase attack cost" 113 | }, 114 | { 115 | "selector": "containers[] .securityContext .runAsUser \u003e 10000", 116 | "reason": "Run as a high-UID user to avoid conflicts with the host's user table" 117 | }, 118 | { 119 | "selector": "containers[] .securityContext .capabilities .drop | index(\"ALL\")", 120 | "reason": "Drop all capabilities and add only those required to reduce syscall attack surface" 121 | } 122 | ] 123 | } 124 | } 125 | ``` 126 | 127 | Try to apply a privileged StatefulSet: 128 | 129 | ```bash 130 | kubectl apply -f ./test/statefulset.yaml 131 | 132 | Error from server (InternalError): error when creating "./test/statefulset.yaml": 133 | Internal error occurred: admission webhook "statefulset.admission.kubesec.io" denied the request: 134 | statefulset-test score is -30, statefulset minimum accepted score is 0 135 | Scan Result: 136 | { 137 | "error": "", 138 | "score": -30, 139 | "scoring": { 140 | "critical": [ 141 | { 142 | "selector": "containers[] .securityContext .privileged == true", 143 | "reason": "Privileged containers can allow almost completely unrestricted host access", 144 | "weight": 0 145 | } 146 | ], 147 | "advise": [ 148 | { 149 | "selector": ".spec .volumeClaimTemplates[] .spec .accessModes | index(\"ReadWriteOnce\")", 150 | "reason": "" 151 | }, 152 | { 153 | "selector": "containers[] .securityContext .runAsNonRoot == true", 154 | "reason": "Force the running image to run as a non-root user to ensure least privilege" 155 | }, 156 | { 157 | "selector": "containers[] .securityContext .capabilities .drop", 158 | "reason": "Reducing kernel capabilities available to a container limits its attack surface", 159 | "href": "https://kubernetes.io/docs/tasks/configure-pod-container/security-context/" 160 | }, 161 | { 162 | "selector": "containers[] .securityContext .readOnlyRootFilesystem == true", 163 | "reason": "An immutable root filesystem can prevent malicious binaries being added to 164 | PATH and increase attack cost" 165 | }, 166 | { 167 | "selector": "containers[] .securityContext .runAsUser \u003e 10000", 168 | "reason": "Run as a high-UID user to avoid conflicts with the host's user table" 169 | } 170 | ] 171 | } 172 | } 173 | ``` 174 | 175 | ## Configuration 176 | 177 | You can set the minimum Kubesec.io score in `./deploy/webhook/yaml`: 178 | 179 | ```yaml 180 | apiVersion: apps/v1beta1 181 | kind: Deployment 182 | metadata: 183 | name: kubesec-webhook 184 | labels: 185 | app: kubesec-webhook 186 | spec: 187 | replicas: 1 188 | template: 189 | metadata: 190 | labels: 191 | app: kubesec-webhook 192 | annotations: 193 | prometheus.io/scrape: "true" 194 | prometheus.io/port: "8081" 195 | spec: 196 | containers: 197 | - name: kubesec-webhook 198 | image: controlplaneio/kubesec:0.1-dev 199 | imagePullPolicy: Always 200 | command: 201 | - ./kubesec 202 | args: 203 | - -tls-cert-file=/etc/webhook/certs/cert.pem 204 | - -tls-key-file=/etc/webhook/certs/key.pem 205 | - -min-score=0 206 | ports: 207 | - containerPort: 8080 208 | - containerPort: 8081 209 | volumeMounts: 210 | - name: webhook-certs 211 | mountPath: /etc/webhook/certs 212 | readOnly: true 213 | volumes: 214 | - name: webhook-certs 215 | secret: 216 | secretName: kubesec-webhook-certs 217 | ``` 218 | 219 | ## Monitoring 220 | 221 | The admission controller exposes Prometheus RED metrics for each webhook a 222 | Grafana dashboard is available [here](https://grafana.com/dashboards/7088). 223 | 224 | ### Credits 225 | 226 | Kudos to [Xabier](https://github.com/slok) for the awesome [kubewebhook library](https://github.com/slok/kubewebhook). 227 | -------------------------------------------------------------------------------- /cmd/kubesec/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "net/http" 7 | "os" 8 | "os/signal" 9 | "syscall" 10 | "time" 11 | 12 | "github.com/prometheus/client_golang/prometheus" 13 | "github.com/prometheus/client_golang/prometheus/promhttp" 14 | "github.com/sirupsen/logrus" 15 | kwhhttp "github.com/slok/kubewebhook/v2/pkg/http" 16 | "github.com/slok/kubewebhook/v2/pkg/log" 17 | kwhlogrus "github.com/slok/kubewebhook/v2/pkg/log/logrus" 18 | kwhprometheus "github.com/slok/kubewebhook/v2/pkg/metrics/prometheus" 19 | kwhwebhook "github.com/slok/kubewebhook/v2/pkg/webhook" 20 | 21 | "github.com/controlplaneio/kubesec-webhook/pkg/webhook" 22 | ) 23 | 24 | // Defaults. 25 | const ( 26 | lAddressDef = ":8080" 27 | lMetricsAddress = ":8081" 28 | debugDef = false 29 | gracePeriod = 10 * time.Second 30 | JSONLogging = false 31 | ) 32 | 33 | // Flags are the flags of the program. 34 | type Flags struct { 35 | ListenAddress string 36 | MetricsListenAddress string 37 | JSONLogging bool 38 | Debug bool 39 | CertFile string 40 | KeyFile string 41 | MinScore int 42 | } 43 | 44 | // NewFlags returns the flags of the commandline. 45 | func NewFlags() *Flags { 46 | flags := &Flags{} 47 | fl := flag.NewFlagSet(os.Args[0], flag.ExitOnError) 48 | fl.StringVar(&flags.ListenAddress, "listen-address", lAddressDef, "webhook server listen address") 49 | fl.StringVar(&flags.MetricsListenAddress, "metrics-listen-address", lMetricsAddress, "metrics server listen address") 50 | fl.BoolVar(&flags.Debug, "debug", debugDef, "enable debug mode") 51 | fl.BoolVar(&flags.JSONLogging, "enable-json-logging", JSONLogging, "enable JSON logging") 52 | fl.StringVar(&flags.CertFile, "tls-cert-file", "certs/cert.pem", "TLS certificate file") 53 | fl.StringVar(&flags.KeyFile, "tls-key-file", "certs/key.pem", "TLS key file") 54 | fl.IntVar(&flags.MinScore, "min-score", 0, "Kubesec.io minimum score to validate against") 55 | 56 | if err := fl.Parse(os.Args[1:]); err != nil { 57 | fmt.Fprintf(os.Stderr, "%s", err) 58 | os.Exit(1) 59 | } 60 | 61 | return flags 62 | } 63 | 64 | type Main struct { 65 | flags *Flags 66 | logger log.Logger 67 | stopC chan struct{} 68 | } 69 | 70 | // Run will run the main program. 71 | func (m *Main) Run() error { 72 | // Logging 73 | logrusLogEntry := logrus.NewEntry(logrus.New()) 74 | logrusLogEntry.WithField("app", "kubesec-webhook") 75 | if m.flags.Debug { 76 | logrusLogEntry.Logger.SetLevel(logrus.DebugLevel) 77 | } 78 | if m.flags.JSONLogging { 79 | logrusLogEntry.Logger.SetFormatter(&logrus.JSONFormatter{}) 80 | } 81 | m.logger = kwhlogrus.NewLogrus(logrusLogEntry) 82 | 83 | // Register metrics 84 | promReg := prometheus.NewRegistry() 85 | metricsRec, err := kwhprometheus.NewRecorder(kwhprometheus.RecorderConfig{Registry: promReg}) 86 | if err != nil { 87 | return fmt.Errorf("could not create Prometheus metrics recorder: %w", err) 88 | } 89 | 90 | // Webhook 91 | wh, err := webhook.New(m.flags.MinScore, m.logger) 92 | if err != nil { 93 | return err 94 | } 95 | 96 | handler, err := kwhhttp.HandlerFor(kwhhttp.HandlerConfig{ 97 | Webhook: kwhwebhook.NewMeasuredWebhook(metricsRec, wh), 98 | Logger: m.logger}) 99 | if err != nil { 100 | return fmt.Errorf("error creating pod webhook handler: %w", err) 101 | } 102 | 103 | errC := make(chan error) 104 | 105 | // Serve webhooks 106 | go func() { 107 | m.logger.Infof("webhooks listening on %s...", m.flags.ListenAddress) 108 | mux := http.NewServeMux() 109 | mux.Handle("/", handler) 110 | errC <- http.ListenAndServeTLS( 111 | m.flags.ListenAddress, 112 | m.flags.CertFile, 113 | m.flags.KeyFile, 114 | mux, 115 | ) 116 | }() 117 | 118 | // Serve metrics. 119 | metricsHandler := promhttp.HandlerFor(promReg, promhttp.HandlerOpts{}) 120 | go func() { 121 | m.logger.Infof("metrics listening on %s...", m.flags.MetricsListenAddress) 122 | errC <- http.ListenAndServe(m.flags.MetricsListenAddress, metricsHandler) 123 | }() 124 | 125 | // Run everything 126 | defer m.stop() 127 | 128 | sigC := m.createSignalChan() 129 | select { 130 | case err := <-errC: 131 | if err != nil { 132 | m.logger.Errorf("error received: %s", err) 133 | return err 134 | } 135 | m.logger.Infof("app finished successfuly") 136 | case s := <-sigC: 137 | m.logger.Infof("signal %s received", s) 138 | return nil 139 | } 140 | 141 | return nil 142 | } 143 | 144 | func (m *Main) stop() { 145 | m.logger.Infof("stopping everything, waiting %s...", gracePeriod) 146 | 147 | close(m.stopC) 148 | 149 | // Stop everything and let them time to stop. 150 | time.Sleep(gracePeriod) 151 | } 152 | 153 | func (m *Main) createSignalChan() chan os.Signal { 154 | c := make(chan os.Signal, 1) 155 | signal.Notify(c, syscall.SIGTERM, syscall.SIGINT) 156 | return c 157 | } 158 | 159 | func main() { 160 | m := Main{ 161 | flags: NewFlags(), 162 | stopC: make(chan struct{}), 163 | } 164 | 165 | err := m.Run() 166 | if err != nil { 167 | fmt.Fprintf(os.Stderr, "%s", err) 168 | os.Exit(1) 169 | } 170 | os.Exit(0) 171 | } 172 | -------------------------------------------------------------------------------- /deploy/gen-certs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Defaults 4 | NAMESPACE=${1:-"kubesec"} 5 | NAME=${2:-"kubesec-webhook"} 6 | OS="$(uname)" 7 | 8 | # Generate cert 9 | 10 | subj="/CN=${NAME}.${NAMESPACE}.svc" 11 | addext="subjectAltName=DNS:${NAME}.${NAMESPACE}.svc" 12 | 13 | mkdir -p ./certs 14 | 15 | echo "$addext" >> ./certs/kubesec.cnf 16 | echo extendedKeyUsage = serverAuth >> ./certs/kubesec.cnf 17 | 18 | docker run --rm -v "${PWD}/certs/":/certs/ --user "$(id -u):$(id -g)" alpine/openssl genrsa -out /certs/webhookCA.key 2048 19 | docker run --rm -v "${PWD}/certs/":/certs/ --user "$(id -u):$(id -g)" alpine/openssl req -new -key /certs/webhookCA.key \ 20 | -subj "$subj" \ 21 | -addext "$addext" \ 22 | -out /certs/webhookCA.csr 23 | 24 | docker run --rm -v "${PWD}/certs/":/certs/ --user "$(id -u):$(id -g)" alpine/openssl x509 -req \ 25 | -extfile /certs/kubesec.cnf \ 26 | -days 365 \ 27 | -in /certs/webhookCA.csr \ 28 | -signkey /certs/webhookCA.key \ 29 | -out /certs/webhook.crt 30 | 31 | # Generate cert secret 32 | kubectl -n kubesec create secret generic \ 33 | "${NAME}"-certs \ 34 | --from-file=key.pem=./certs/webhookCA.key \ 35 | --from-file=cert.pem=./certs/webhook.crt \ 36 | --dry-run=client -o yaml > ./webhook-certs.yaml 37 | 38 | # Encode CABundle 39 | if [[ "$OS" == "Darwin" ]]; then 40 | CA_BUNDLE=$(cat ./certs/webhook.crt | base64) 41 | elif [[ "$OS" == "Linux" ]]; then 42 | CA_BUNDLE=$(cat ./certs/webhook.crt | base64 -w0) 43 | else 44 | echo "Unsupported OS ${OS}" 45 | exit 1 46 | fi 47 | 48 | # Generate Kubernetes webhook registration 49 | sed "s/CA_BUNDLE/${CA_BUNDLE}/" ./webhook-registration.yaml.tpl > ./webhook-registration.yaml 50 | 51 | # Clean 52 | rm -rf ./certs/ 53 | -------------------------------------------------------------------------------- /deploy/webhook-certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | data: 3 | cert.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHVENDQWdHZ0F3SUJBZ0lVVGhDN3pzRW9jRTRTOSt6emZsT2dtc1Fkd1hvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0pqRWtNQ0lHQTFVRUF3d2JhM1ZpWlhObFl5MTNaV0pvYjI5ckxtdDFZbVZ6WldNdWMzWmpNQjRYRFRJeQpNVEl3TmpFek1qTXhOVm9YRFRJek1USXdOakV6TWpNeE5Wb3dKakVrTUNJR0ExVUVBd3diYTNWaVpYTmxZeTEzClpXSm9iMjlyTG10MVltVnpaV011YzNaak1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXZsVmxSa3Bla09PKzVYSW5hTEpBU1I3VVl5UjlOSzd5U2djblgwcnYzdFdSMnh0Mmljb1dQeFNqc0NEZgpZRkVGOGtuS2RYS0J2TXhUdE16VDNiUlJoc3Bkb2trNGtXQVZRWEp5ZUhPWGNIbTFGcVFyRVhNOGdXNDFQWTlvCkJQMW84bVo5MWx3dUJCSFVRUU94Y1BDL0JuYm51SXNaSmlvNXpCRmNvdDUwODBqVkkxSkVrYzFrQXJHYlZVRmcKTVcvZzI0N1hVU2svdzUrd2pvMmdSdW9WMkVKamYrZDlkRG1iL25TdmlNVVp5SFp0eTRnc09kWmdGbmxDdGxGVgpCQXQ1YXFzSUVoTWdaYXhSdEVQTWRnNjJONDhxcDc3MHY2S0RUa2N2VmlBRUViMmgvU1JBQ3o0T0JtQjlDRVB5ClQ2VnVrekVydWtsRitjTE1oVllOVWV4NWx3SURBUUFCb3o4d1BUQW1CZ05WSFJFRUh6QWRnaHRyZFdKbGMyVmoKTFhkbFltaHZiMnN1YTNWaVpYTmxZeTV6ZG1Nd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3RXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUV6MHgyQUxhVWFRZlY1QjFRVVpWWnVrL2tkcXo4QnVPWjQ4cTBiTlN1MVRWcnpkCkltMzBJSHRoR05pOGZYb2s5bFNzalNBWm9nbUl0L2I3T3ZxQ2R4Z0s0eHlDVVFSVjZvVzRwNW1UbUpYRmFqSG0KRVFPeXpaSFp5c011cHF0Vzh5clhMN0xKaW90ZjUvQml1TEtvcnVzWUphZmZYankxNnJnakpnSGd5UVJ0YXBPQQpXR1BsblJuWXd4RXpJUTVzczd4ZURmdmhaVVVFN1JiUUhuWkRkNjVTNnNsM2Zlbk8yL0xZSlc5NXpyd2gzWWNHCnhlc1hJcXF4dWRQY3JYMmV5NWNXUHprUDM1VlE5c2NwMmFsUnF6TTN0NE5kTC9iL250QjFVUFRIQjBZYTVhWksKM3E4VitJcHR4VzJJN0lONVZFeDBwUWxTdFlKMjE5OHFRSERYZ00wPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 4 | key.pem: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdmxWbFJrcGVrT08rNVhJbmFMSkFTUjdVWXlSOU5LN3lTZ2NuWDBydjN0V1IyeHQyCmljb1dQeFNqc0NEZllGRUY4a25LZFhLQnZNeFR0TXpUM2JSUmhzcGRva2s0a1dBVlFYSnllSE9YY0htMUZxUXIKRVhNOGdXNDFQWTlvQlAxbzhtWjkxbHd1QkJIVVFRT3hjUEMvQm5ibnVJc1pKaW81ekJGY290NTA4MGpWSTFKRQprYzFrQXJHYlZVRmdNVy9nMjQ3WFVTay93NSt3am8yZ1J1b1YyRUpqZitkOWREbWIvblN2aU1VWnlIWnR5NGdzCk9kWmdGbmxDdGxGVkJBdDVhcXNJRWhNZ1pheFJ0RVBNZGc2Mk40OHFwNzcwdjZLRFRrY3ZWaUFFRWIyaC9TUkEKQ3o0T0JtQjlDRVB5VDZWdWt6RXJ1a2xGK2NMTWhWWU5VZXg1bHdJREFRQUJBb0lCQUZuVHo3STIweDZxZmFPbwpGblZRK3dvSFpORk5uVkhKNTB1TXlNWXVoYnF6TE4wdHZ1b1UyQjc1VEsrSk5DTXUyaEdaUmRYY0x1Szl4QnVtCk42K0F0S0ZheklvVTZIK2p5eVJTTVRncnhhTXRyWXQ3KzErRzlWMVllQVFQdEZYMml4c3J4K1B0S1VKK2I2QW4KY0EwUGNmaEpFZCtFdGwvT3VleFhuVks0anBWcVQrRk55UFYyVVRFUnV6cWhVY0dCc0p0bnVkZkpWMFdRZXRGVAordUxCWTFtM3VuY2hHWlo1cnlML0NWYVQxc1NiMk9LM2VMUTRaWmZ3UFFHc3pFMytaU2hJWnRlcE94QzBVbE5yCnNNOXFGODBtN2hWNU5hT0FHZXkxZlRDd0VOTFhIaENKMFpnbGd2ajN3RWxCeUtsTFVSenJjOW9mRFY5SUl3SGIKTFQrWXlGRUNnWUVBM2FNMGh3alhmV0xnS1BRSVBVSGE2QTJvZ0E2cjRTQ25lYTJpUjMrZjVWZlBFOTg2SXBTKwp4Qk9QVzdqS3ZiaVl1WGRua0dSa010b0VmTHZyOW1HRWYwUTFTdGtDSjEvbjVxSG42NmJ5M3VLb1ZkZlpKYmtUCld6cWpFWHVRRGpzZ01HUnA0aDJ0cVdQNFZ5aEphSktBRTc1bUszT0dNZHpXMEdaRXY0MjFuOHNDZ1lFQTI5ZTgKbGUyK2ltQnRXR05GY3ZjYUQ2ZlhLdUpCSDJsSVhRQyt2L2VLZjd2M3lZbUJmN0VGS3ZHL1hnL3VWS1J0dlp4SAorazZrUk9lblp4Z1lOc1I1QTFUeUlTT3R0ajhINmppcDRGcFpjWGUxS1JsbXIyTFFaaEFhZmRpWlFEanBCUUlvCmcwb2ZRZFcvOURTL3BDNjBBbk00ejRlazhGYU1jOER0SUE1S2UrVUNnWUJiRnpPRWVCN1FtcTJVUjArSGxhUloKa1J0Nm5nMElOcnArS04yMFV3Q3RhcHhpQjNIR09xbjR2aTFDUGoyZElkd3JCYWNiMGhiWVM0QmluMzJJUW1ZSgpSRWcrM2RlanhTZnpRd0dsZVhVQ0k5ZVppRi9ud0J2emQ3TURnV3dnWFM2S2xRcHJjMVVuZEQzaDNGM25TNmExCjlwL1pKZDYyYVpRa0RKUWV3aWd1WndLQmdDNVF1aU5nRGdkN0h5NUM0OHUvc1ZiaEJseTdnL3JKSkh5cmZvUlUKODNITHVQMVZvZG0wQXFHMGdwdWZnWmVGZUxVOHFwRmFaaE02TnJOcWlSZG90eEh6b0h0STEvMFFOR3VzK21VUQp3ODA2NmdpNW1EK1U4dEM5emNiN2pmWFF4NDdOa0psd1VUdCtlODFJRzZQTVR4SkJFaFB1d05uOWNlT2xIby9sClV0M2RBb0dCQU10SHduTWwxdUZWbW4yME03NmlDTytsNVhSZjNjam5QV1B3ZlJyTXprWVlqTXNUaTFNMmFOZUoKd05IbTVOWG5hTm5BSWhjaThKc3RjRXdrVzNZa1FNdmpTeStaRW9obSs1dVVGTkladWtDVDhoWWoyWVRXaWZWbQpEZ2NkMEhRcW1NUEUvQTFORkxHd3dRakxUUjcvNTFhUU13YlZaUHY2cWlBZUxDMnVCTmVxCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== 5 | kind: Secret 6 | metadata: 7 | creationTimestamp: null 8 | name: kubesec-webhook-certs 9 | namespace: kubesec 10 | -------------------------------------------------------------------------------- /deploy/webhook-registration.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: ValidatingWebhookConfiguration 4 | metadata: 5 | name: kubesec-webhook 6 | labels: 7 | app: kubesec-webhook 8 | kind: validator 9 | webhooks: 10 | - name: pod.admission.kubesc.io 11 | clientConfig: 12 | service: 13 | name: kubesec-webhook 14 | namespace: kubesec 15 | path: "/" 16 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHVENDQWdHZ0F3SUJBZ0lVVGhDN3pzRW9jRTRTOSt6emZsT2dtc1Fkd1hvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0pqRWtNQ0lHQTFVRUF3d2JhM1ZpWlhObFl5MTNaV0pvYjI5ckxtdDFZbVZ6WldNdWMzWmpNQjRYRFRJeQpNVEl3TmpFek1qTXhOVm9YRFRJek1USXdOakV6TWpNeE5Wb3dKakVrTUNJR0ExVUVBd3diYTNWaVpYTmxZeTEzClpXSm9iMjlyTG10MVltVnpaV011YzNaak1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXZsVmxSa3Bla09PKzVYSW5hTEpBU1I3VVl5UjlOSzd5U2djblgwcnYzdFdSMnh0Mmljb1dQeFNqc0NEZgpZRkVGOGtuS2RYS0J2TXhUdE16VDNiUlJoc3Bkb2trNGtXQVZRWEp5ZUhPWGNIbTFGcVFyRVhNOGdXNDFQWTlvCkJQMW84bVo5MWx3dUJCSFVRUU94Y1BDL0JuYm51SXNaSmlvNXpCRmNvdDUwODBqVkkxSkVrYzFrQXJHYlZVRmcKTVcvZzI0N1hVU2svdzUrd2pvMmdSdW9WMkVKamYrZDlkRG1iL25TdmlNVVp5SFp0eTRnc09kWmdGbmxDdGxGVgpCQXQ1YXFzSUVoTWdaYXhSdEVQTWRnNjJONDhxcDc3MHY2S0RUa2N2VmlBRUViMmgvU1JBQ3o0T0JtQjlDRVB5ClQ2VnVrekVydWtsRitjTE1oVllOVWV4NWx3SURBUUFCb3o4d1BUQW1CZ05WSFJFRUh6QWRnaHRyZFdKbGMyVmoKTFhkbFltaHZiMnN1YTNWaVpYTmxZeTV6ZG1Nd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3RXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUV6MHgyQUxhVWFRZlY1QjFRVVpWWnVrL2tkcXo4QnVPWjQ4cTBiTlN1MVRWcnpkCkltMzBJSHRoR05pOGZYb2s5bFNzalNBWm9nbUl0L2I3T3ZxQ2R4Z0s0eHlDVVFSVjZvVzRwNW1UbUpYRmFqSG0KRVFPeXpaSFp5c011cHF0Vzh5clhMN0xKaW90ZjUvQml1TEtvcnVzWUphZmZYankxNnJnakpnSGd5UVJ0YXBPQQpXR1BsblJuWXd4RXpJUTVzczd4ZURmdmhaVVVFN1JiUUhuWkRkNjVTNnNsM2Zlbk8yL0xZSlc5NXpyd2gzWWNHCnhlc1hJcXF4dWRQY3JYMmV5NWNXUHprUDM1VlE5c2NwMmFsUnF6TTN0NE5kTC9iL250QjFVUFRIQjBZYTVhWksKM3E4VitJcHR4VzJJN0lONVZFeDBwUWxTdFlKMjE5OHFRSERYZ00wPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 17 | rules: 18 | - operations: 19 | - CREATE 20 | - UPDATE 21 | apiGroups: 22 | - "" 23 | apiVersions: 24 | - "v1" 25 | resources: 26 | - pods 27 | failurePolicy: Fail 28 | namespaceSelector: 29 | matchLabels: 30 | kubesec-validation: enabled 31 | sideEffects: None 32 | timeoutSeconds: 15 33 | admissionReviewVersions: ["v1"] 34 | - name: deployment.admission.kubesc.io 35 | clientConfig: 36 | service: 37 | name: kubesec-webhook 38 | namespace: kubesec 39 | path: "/" 40 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHVENDQWdHZ0F3SUJBZ0lVVGhDN3pzRW9jRTRTOSt6emZsT2dtc1Fkd1hvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0pqRWtNQ0lHQTFVRUF3d2JhM1ZpWlhObFl5MTNaV0pvYjI5ckxtdDFZbVZ6WldNdWMzWmpNQjRYRFRJeQpNVEl3TmpFek1qTXhOVm9YRFRJek1USXdOakV6TWpNeE5Wb3dKakVrTUNJR0ExVUVBd3diYTNWaVpYTmxZeTEzClpXSm9iMjlyTG10MVltVnpaV011YzNaak1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXZsVmxSa3Bla09PKzVYSW5hTEpBU1I3VVl5UjlOSzd5U2djblgwcnYzdFdSMnh0Mmljb1dQeFNqc0NEZgpZRkVGOGtuS2RYS0J2TXhUdE16VDNiUlJoc3Bkb2trNGtXQVZRWEp5ZUhPWGNIbTFGcVFyRVhNOGdXNDFQWTlvCkJQMW84bVo5MWx3dUJCSFVRUU94Y1BDL0JuYm51SXNaSmlvNXpCRmNvdDUwODBqVkkxSkVrYzFrQXJHYlZVRmcKTVcvZzI0N1hVU2svdzUrd2pvMmdSdW9WMkVKamYrZDlkRG1iL25TdmlNVVp5SFp0eTRnc09kWmdGbmxDdGxGVgpCQXQ1YXFzSUVoTWdaYXhSdEVQTWRnNjJONDhxcDc3MHY2S0RUa2N2VmlBRUViMmgvU1JBQ3o0T0JtQjlDRVB5ClQ2VnVrekVydWtsRitjTE1oVllOVWV4NWx3SURBUUFCb3o4d1BUQW1CZ05WSFJFRUh6QWRnaHRyZFdKbGMyVmoKTFhkbFltaHZiMnN1YTNWaVpYTmxZeTV6ZG1Nd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3RXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUV6MHgyQUxhVWFRZlY1QjFRVVpWWnVrL2tkcXo4QnVPWjQ4cTBiTlN1MVRWcnpkCkltMzBJSHRoR05pOGZYb2s5bFNzalNBWm9nbUl0L2I3T3ZxQ2R4Z0s0eHlDVVFSVjZvVzRwNW1UbUpYRmFqSG0KRVFPeXpaSFp5c011cHF0Vzh5clhMN0xKaW90ZjUvQml1TEtvcnVzWUphZmZYankxNnJnakpnSGd5UVJ0YXBPQQpXR1BsblJuWXd4RXpJUTVzczd4ZURmdmhaVVVFN1JiUUhuWkRkNjVTNnNsM2Zlbk8yL0xZSlc5NXpyd2gzWWNHCnhlc1hJcXF4dWRQY3JYMmV5NWNXUHprUDM1VlE5c2NwMmFsUnF6TTN0NE5kTC9iL250QjFVUFRIQjBZYTVhWksKM3E4VitJcHR4VzJJN0lONVZFeDBwUWxTdFlKMjE5OHFRSERYZ00wPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 41 | rules: 42 | - operations: 43 | - CREATE 44 | - UPDATE 45 | apiGroups: 46 | - apps 47 | apiVersions: 48 | - "*" 49 | resources: 50 | - deployments 51 | failurePolicy: Fail 52 | namespaceSelector: 53 | matchLabels: 54 | kubesec-validation: enabled 55 | sideEffects: None 56 | timeoutSeconds: 15 57 | admissionReviewVersions: ["v1"] 58 | - name: daemonset.admission.kubesc.io 59 | clientConfig: 60 | service: 61 | name: kubesec-webhook 62 | namespace: kubesec 63 | path: "/" 64 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHVENDQWdHZ0F3SUJBZ0lVVGhDN3pzRW9jRTRTOSt6emZsT2dtc1Fkd1hvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0pqRWtNQ0lHQTFVRUF3d2JhM1ZpWlhObFl5MTNaV0pvYjI5ckxtdDFZbVZ6WldNdWMzWmpNQjRYRFRJeQpNVEl3TmpFek1qTXhOVm9YRFRJek1USXdOakV6TWpNeE5Wb3dKakVrTUNJR0ExVUVBd3diYTNWaVpYTmxZeTEzClpXSm9iMjlyTG10MVltVnpaV011YzNaak1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXZsVmxSa3Bla09PKzVYSW5hTEpBU1I3VVl5UjlOSzd5U2djblgwcnYzdFdSMnh0Mmljb1dQeFNqc0NEZgpZRkVGOGtuS2RYS0J2TXhUdE16VDNiUlJoc3Bkb2trNGtXQVZRWEp5ZUhPWGNIbTFGcVFyRVhNOGdXNDFQWTlvCkJQMW84bVo5MWx3dUJCSFVRUU94Y1BDL0JuYm51SXNaSmlvNXpCRmNvdDUwODBqVkkxSkVrYzFrQXJHYlZVRmcKTVcvZzI0N1hVU2svdzUrd2pvMmdSdW9WMkVKamYrZDlkRG1iL25TdmlNVVp5SFp0eTRnc09kWmdGbmxDdGxGVgpCQXQ1YXFzSUVoTWdaYXhSdEVQTWRnNjJONDhxcDc3MHY2S0RUa2N2VmlBRUViMmgvU1JBQ3o0T0JtQjlDRVB5ClQ2VnVrekVydWtsRitjTE1oVllOVWV4NWx3SURBUUFCb3o4d1BUQW1CZ05WSFJFRUh6QWRnaHRyZFdKbGMyVmoKTFhkbFltaHZiMnN1YTNWaVpYTmxZeTV6ZG1Nd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3RXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUV6MHgyQUxhVWFRZlY1QjFRVVpWWnVrL2tkcXo4QnVPWjQ4cTBiTlN1MVRWcnpkCkltMzBJSHRoR05pOGZYb2s5bFNzalNBWm9nbUl0L2I3T3ZxQ2R4Z0s0eHlDVVFSVjZvVzRwNW1UbUpYRmFqSG0KRVFPeXpaSFp5c011cHF0Vzh5clhMN0xKaW90ZjUvQml1TEtvcnVzWUphZmZYankxNnJnakpnSGd5UVJ0YXBPQQpXR1BsblJuWXd4RXpJUTVzczd4ZURmdmhaVVVFN1JiUUhuWkRkNjVTNnNsM2Zlbk8yL0xZSlc5NXpyd2gzWWNHCnhlc1hJcXF4dWRQY3JYMmV5NWNXUHprUDM1VlE5c2NwMmFsUnF6TTN0NE5kTC9iL250QjFVUFRIQjBZYTVhWksKM3E4VitJcHR4VzJJN0lONVZFeDBwUWxTdFlKMjE5OHFRSERYZ00wPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 65 | rules: 66 | - operations: 67 | - CREATE 68 | - UPDATE 69 | apiGroups: 70 | - apps 71 | apiVersions: 72 | - "*" 73 | resources: 74 | - daemonsets 75 | failurePolicy: Fail 76 | namespaceSelector: 77 | matchLabels: 78 | kubesec-validation: enabled 79 | sideEffects: None 80 | timeoutSeconds: 15 81 | admissionReviewVersions: ["v1"] 82 | - name: statefulset.admission.kubesc.io 83 | clientConfig: 84 | service: 85 | name: kubesec-webhook 86 | namespace: kubesec 87 | path: "/" 88 | caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURHVENDQWdHZ0F3SUJBZ0lVVGhDN3pzRW9jRTRTOSt6emZsT2dtc1Fkd1hvd0RRWUpLb1pJaHZjTkFRRUwKQlFBd0pqRWtNQ0lHQTFVRUF3d2JhM1ZpWlhObFl5MTNaV0pvYjI5ckxtdDFZbVZ6WldNdWMzWmpNQjRYRFRJeQpNVEl3TmpFek1qTXhOVm9YRFRJek1USXdOakV6TWpNeE5Wb3dKakVrTUNJR0ExVUVBd3diYTNWaVpYTmxZeTEzClpXSm9iMjlyTG10MVltVnpaV011YzNaak1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0MKQVFFQXZsVmxSa3Bla09PKzVYSW5hTEpBU1I3VVl5UjlOSzd5U2djblgwcnYzdFdSMnh0Mmljb1dQeFNqc0NEZgpZRkVGOGtuS2RYS0J2TXhUdE16VDNiUlJoc3Bkb2trNGtXQVZRWEp5ZUhPWGNIbTFGcVFyRVhNOGdXNDFQWTlvCkJQMW84bVo5MWx3dUJCSFVRUU94Y1BDL0JuYm51SXNaSmlvNXpCRmNvdDUwODBqVkkxSkVrYzFrQXJHYlZVRmcKTVcvZzI0N1hVU2svdzUrd2pvMmdSdW9WMkVKamYrZDlkRG1iL25TdmlNVVp5SFp0eTRnc09kWmdGbmxDdGxGVgpCQXQ1YXFzSUVoTWdaYXhSdEVQTWRnNjJONDhxcDc3MHY2S0RUa2N2VmlBRUViMmgvU1JBQ3o0T0JtQjlDRVB5ClQ2VnVrekVydWtsRitjTE1oVllOVWV4NWx3SURBUUFCb3o4d1BUQW1CZ05WSFJFRUh6QWRnaHRyZFdKbGMyVmoKTFhkbFltaHZiMnN1YTNWaVpYTmxZeTV6ZG1Nd0V3WURWUjBsQkF3d0NnWUlLd1lCQlFVSEF3RXdEUVlKS29aSQpodmNOQVFFTEJRQURnZ0VCQUV6MHgyQUxhVWFRZlY1QjFRVVpWWnVrL2tkcXo4QnVPWjQ4cTBiTlN1MVRWcnpkCkltMzBJSHRoR05pOGZYb2s5bFNzalNBWm9nbUl0L2I3T3ZxQ2R4Z0s0eHlDVVFSVjZvVzRwNW1UbUpYRmFqSG0KRVFPeXpaSFp5c011cHF0Vzh5clhMN0xKaW90ZjUvQml1TEtvcnVzWUphZmZYankxNnJnakpnSGd5UVJ0YXBPQQpXR1BsblJuWXd4RXpJUTVzczd4ZURmdmhaVVVFN1JiUUhuWkRkNjVTNnNsM2Zlbk8yL0xZSlc5NXpyd2gzWWNHCnhlc1hJcXF4dWRQY3JYMmV5NWNXUHprUDM1VlE5c2NwMmFsUnF6TTN0NE5kTC9iL250QjFVUFRIQjBZYTVhWksKM3E4VitJcHR4VzJJN0lONVZFeDBwUWxTdFlKMjE5OHFRSERYZ00wPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== 89 | rules: 90 | - operations: 91 | - CREATE 92 | - UPDATE 93 | apiGroups: 94 | - apps 95 | apiVersions: 96 | - "*" 97 | resources: 98 | - statefulsets 99 | failurePolicy: Fail 100 | namespaceSelector: 101 | matchLabels: 102 | kubesec-validation: enabled 103 | sideEffects: None 104 | timeoutSeconds: 15 105 | admissionReviewVersions: ["v1"] 106 | -------------------------------------------------------------------------------- /deploy/webhook-registration.yaml.tpl: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: admissionregistration.k8s.io/v1 3 | kind: ValidatingWebhookConfiguration 4 | metadata: 5 | name: kubesec-webhook 6 | labels: 7 | app: kubesec-webhook 8 | kind: validator 9 | webhooks: 10 | - name: pod.admission.kubesc.io 11 | clientConfig: 12 | service: 13 | name: kubesec-webhook 14 | namespace: kubesec 15 | path: "/" 16 | caBundle: CA_BUNDLE 17 | rules: 18 | - operations: 19 | - CREATE 20 | - UPDATE 21 | apiGroups: 22 | - "" 23 | apiVersions: 24 | - "v1" 25 | resources: 26 | - pods 27 | failurePolicy: Fail 28 | namespaceSelector: 29 | matchLabels: 30 | kubesec-validation: enabled 31 | sideEffects: None 32 | timeoutSeconds: 15 33 | admissionReviewVersions: ["v1"] 34 | - name: deployment.admission.kubesc.io 35 | clientConfig: 36 | service: 37 | name: kubesec-webhook 38 | namespace: kubesec 39 | path: "/" 40 | caBundle: CA_BUNDLE 41 | rules: 42 | - operations: 43 | - CREATE 44 | - UPDATE 45 | apiGroups: 46 | - apps 47 | apiVersions: 48 | - "*" 49 | resources: 50 | - deployments 51 | failurePolicy: Fail 52 | namespaceSelector: 53 | matchLabels: 54 | kubesec-validation: enabled 55 | sideEffects: None 56 | timeoutSeconds: 15 57 | admissionReviewVersions: ["v1"] 58 | - name: daemonset.admission.kubesc.io 59 | clientConfig: 60 | service: 61 | name: kubesec-webhook 62 | namespace: kubesec 63 | path: "/" 64 | caBundle: CA_BUNDLE 65 | rules: 66 | - operations: 67 | - CREATE 68 | - UPDATE 69 | apiGroups: 70 | - apps 71 | apiVersions: 72 | - "*" 73 | resources: 74 | - daemonsets 75 | failurePolicy: Fail 76 | namespaceSelector: 77 | matchLabels: 78 | kubesec-validation: enabled 79 | sideEffects: None 80 | timeoutSeconds: 15 81 | admissionReviewVersions: ["v1"] 82 | - name: statefulset.admission.kubesc.io 83 | clientConfig: 84 | service: 85 | name: kubesec-webhook 86 | namespace: kubesec 87 | path: "/" 88 | caBundle: CA_BUNDLE 89 | rules: 90 | - operations: 91 | - CREATE 92 | - UPDATE 93 | apiGroups: 94 | - apps 95 | apiVersions: 96 | - "*" 97 | resources: 98 | - statefulsets 99 | failurePolicy: Fail 100 | namespaceSelector: 101 | matchLabels: 102 | kubesec-validation: enabled 103 | sideEffects: None 104 | timeoutSeconds: 15 105 | admissionReviewVersions: ["v1"] 106 | -------------------------------------------------------------------------------- /deploy/webhook.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: kubesec-webhook 6 | labels: 7 | app: kubesec-webhook 8 | namespace: kubesec 9 | spec: 10 | selector: 11 | matchLabels: 12 | app: kubesec-webhook 13 | replicas: 1 14 | template: 15 | metadata: 16 | labels: 17 | app: kubesec-webhook 18 | annotations: 19 | prometheus.io/scrape: "true" 20 | prometheus.io/port: "8081" 21 | spec: 22 | containers: 23 | - name: kubesec-webhook 24 | image: stefanprodan/kubesec-webhook:0.1-dev 25 | imagePullPolicy: Always 26 | securityContext: 27 | readOnlyRootFilesystem: true 28 | runAsNonRoot: true 29 | runAsUser: 10001 30 | capabilities: 31 | drop: 32 | - all 33 | add: 34 | - NET_BIND_SERVICE 35 | command: 36 | - ./kubesec 37 | args: 38 | - -tls-cert-file=/etc/webhook/certs/cert.pem 39 | - -tls-key-file=/etc/webhook/certs/key.pem 40 | - -min-score=0 41 | ports: 42 | - containerPort: 8080 43 | - containerPort: 8081 44 | readinessProbe: 45 | httpGet: 46 | path: /metrics 47 | port: 8081 48 | livenessProbe: 49 | httpGet: 50 | path: /metrics 51 | port: 8081 52 | resources: 53 | limits: 54 | memory: "256Mi" 55 | cpu: "1000m" 56 | requests: 57 | memory: "32Mi" 58 | cpu: "10m" 59 | volumeMounts: 60 | - name: webhook-certs 61 | mountPath: /etc/webhook/certs 62 | readOnly: true 63 | volumes: 64 | - name: webhook-certs 65 | secret: 66 | secretName: kubesec-webhook-certs 67 | --- 68 | apiVersion: v1 69 | kind: Service 70 | metadata: 71 | name: kubesec-webhook 72 | labels: 73 | app: kubesec-webhook 74 | namespace: kubesec 75 | spec: 76 | ports: 77 | - port: 443 78 | targetPort: 8080 79 | selector: 80 | app: kubesec-webhook 81 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/controlplaneio/kubesec-webhook 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/controlplaneio/kubectl-kubesec/v2 v2.0.0-20230918075906-028307149cf6 7 | github.com/prometheus/client_golang v1.17.0 8 | github.com/sirupsen/logrus v1.9.3 9 | github.com/slok/kubewebhook/v2 v2.5.0 10 | k8s.io/api v0.28.4 11 | k8s.io/apimachinery v0.28.4 12 | k8s.io/client-go v0.28.4 13 | ) 14 | 15 | require ( 16 | github.com/beorn7/perks v1.0.1 // indirect 17 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 18 | github.com/go-logr/logr v1.3.0 // indirect 19 | github.com/gogo/protobuf v1.3.2 // indirect 20 | github.com/golang/protobuf v1.5.3 // indirect 21 | github.com/google/gofuzz v1.2.0 // indirect 22 | github.com/json-iterator/go v1.1.12 // indirect 23 | github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect 24 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect 25 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 26 | github.com/modern-go/reflect2 v1.0.2 // indirect 27 | github.com/prometheus/client_model v0.5.0 // indirect 28 | github.com/prometheus/common v0.45.0 // indirect 29 | github.com/prometheus/procfs v0.12.0 // indirect 30 | github.com/stretchr/testify v1.8.4 // indirect 31 | golang.org/x/net v0.18.0 // indirect 32 | golang.org/x/sys v0.14.0 // indirect 33 | golang.org/x/text v0.14.0 // indirect 34 | google.golang.org/protobuf v1.31.0 // indirect 35 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 36 | gopkg.in/inf.v0 v0.9.1 // indirect 37 | gopkg.in/yaml.v2 v2.4.0 // indirect 38 | k8s.io/klog/v2 v2.110.1 // indirect 39 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect 40 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 41 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect 42 | sigs.k8s.io/yaml v1.4.0 // indirect 43 | ) 44 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 14 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 15 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 16 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 17 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 18 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 19 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 20 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 21 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 22 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 23 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 24 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 25 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 26 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 27 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 28 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 29 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 30 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 31 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 32 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 33 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 34 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 35 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 36 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 37 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 38 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 39 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 40 | github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= 41 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 42 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 43 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 44 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 45 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 46 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 47 | github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= 48 | github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 49 | github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= 50 | github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 51 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 52 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 53 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 54 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 55 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 56 | github.com/controlplaneio/kubectl-kubesec/v2 v2.0.0-20221123145816-65846073e41e h1:TdU8e1nu1J0p9tNdAeuIUpPmEncvh/VH1c0QnSNGcGU= 57 | github.com/controlplaneio/kubectl-kubesec/v2 v2.0.0-20221123145816-65846073e41e/go.mod h1:2JbNM43BaOtl/EXQpFy+iyWhpSBCSOkMR9uCgrbJC8c= 58 | github.com/controlplaneio/kubectl-kubesec/v2 v2.0.0-20230918075906-028307149cf6 h1:xwSyLr8UTV7rB1/VojDOadkQQWmWzYHj7ofvBk3k8eA= 59 | github.com/controlplaneio/kubectl-kubesec/v2 v2.0.0-20230918075906-028307149cf6/go.mod h1:Mafe4sPM7PREb9DV3TF+tpuLkn//4vY9vL7zZmYv/hc= 60 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 61 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 62 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 63 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 64 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 65 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 66 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 67 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 68 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 69 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 70 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 71 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 72 | github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= 73 | github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= 74 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 75 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 76 | github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= 77 | github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= 78 | github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 79 | github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= 80 | github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 81 | github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= 82 | github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 83 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 84 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 85 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 86 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 87 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 88 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 89 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 90 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 91 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 92 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 93 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 94 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 95 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 96 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 97 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 98 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 99 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 100 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 101 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 102 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 103 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 104 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 105 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 106 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 107 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 108 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 109 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 110 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 111 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 112 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 113 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 114 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 115 | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= 116 | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 117 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 118 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 119 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 120 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 121 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 122 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 123 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 124 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 125 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 126 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 127 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 128 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= 129 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 130 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 131 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 132 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 133 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 134 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 135 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 136 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 137 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 138 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 139 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 140 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 141 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 142 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 143 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 144 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 145 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 146 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 147 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 148 | github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= 149 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 150 | github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 151 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 152 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 153 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 154 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 155 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 156 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 157 | github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 158 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 159 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 160 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 161 | github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 162 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 163 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 164 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 165 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 166 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 167 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 168 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 169 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 170 | github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= 171 | github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= 172 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= 173 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 174 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 175 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 176 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 177 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 178 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 179 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 180 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 181 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 182 | github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 183 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 184 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 185 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 186 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 187 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 188 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 189 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 190 | github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= 191 | github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= 192 | github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= 193 | github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= 194 | github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= 195 | github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= 196 | github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= 197 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 198 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 199 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 200 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 201 | github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= 202 | github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= 203 | github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= 204 | github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= 205 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 206 | github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= 207 | github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= 208 | github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= 209 | github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= 210 | github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= 211 | github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= 212 | github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 213 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 214 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 215 | github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= 216 | github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 217 | github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= 218 | github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= 219 | github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= 220 | github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= 221 | github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 222 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 223 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 224 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 225 | github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= 226 | github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= 227 | github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 228 | github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= 229 | github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 230 | github.com/slok/kubewebhook/v2 v2.5.0 h1:CwMxLbTEcha3+SxSXc4pc9iIbREdhgLurAs+/uRzxIw= 231 | github.com/slok/kubewebhook/v2 v2.5.0/go.mod h1:TcQS+Ae0TDiiwm9glxum6AFvtumR33qdAenUeiQ/TWs= 232 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 233 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 234 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 235 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 236 | github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= 237 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 238 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 239 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 240 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 241 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 242 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 243 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 244 | github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= 245 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 246 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 247 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 248 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 249 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 250 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 251 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 252 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 253 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 254 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 255 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 256 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 257 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 258 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 259 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 260 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 261 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 262 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 263 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 264 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 265 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 266 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 267 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 268 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 269 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 270 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 271 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 272 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 273 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 274 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 275 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 276 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 277 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 278 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 279 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 280 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 281 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 282 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 283 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 284 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 285 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 286 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 287 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 288 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 289 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 290 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 291 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 292 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 293 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 294 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 295 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 296 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 297 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 298 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 299 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 300 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 301 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 302 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 303 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 304 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 305 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 306 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 307 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 308 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 309 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 310 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 311 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 312 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 313 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 314 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 315 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 316 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 317 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 318 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 319 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 320 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 321 | golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 322 | golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 323 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 324 | golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= 325 | golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 326 | golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= 327 | golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= 328 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 329 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 330 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 331 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 332 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 333 | golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 334 | golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= 335 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 336 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 337 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 338 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 339 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 340 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 341 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 342 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 343 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 344 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 345 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 346 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 347 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 348 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 349 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 350 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 351 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 352 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 353 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 354 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 355 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 356 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 357 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 358 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 359 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 360 | golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 361 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 362 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 363 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 364 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 365 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 366 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 367 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 368 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 369 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 370 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 371 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 372 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 373 | golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 374 | golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 375 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 376 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 377 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 378 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 379 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 380 | golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 381 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 382 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 383 | golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 384 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 385 | golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= 386 | golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 387 | golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= 388 | golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 389 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 390 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 391 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 392 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 393 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 394 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 395 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 396 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 397 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 398 | golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= 399 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 400 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 401 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 402 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 403 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 404 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 405 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 406 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 407 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 408 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 409 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 410 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 411 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 412 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 413 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 414 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 415 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 416 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 417 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 418 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 419 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 420 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 421 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 422 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 423 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 424 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 425 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 426 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 427 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 428 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 429 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 430 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 431 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 432 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 433 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 434 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 435 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 436 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 437 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 438 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 439 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 440 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 441 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 442 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 443 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 444 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 445 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 446 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 447 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 448 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 449 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 450 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 451 | gomodules.xyz/jsonpatch/v3 v3.0.1 h1:Te7hKxV52TKCbNYq3t84tzKav3xhThdvSsSp/W89IyI= 452 | gomodules.xyz/orderedmap v0.1.0 h1:fM/+TGh/O1KkqGR5xjTKg6bU8OKBkg7p0Y+x/J9m8Os= 453 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 454 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 455 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 456 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 457 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 458 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 459 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 460 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 461 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 462 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 463 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 464 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 465 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 466 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 467 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 468 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 469 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 470 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 471 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 472 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 473 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 474 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 475 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 476 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 477 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 478 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 479 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 480 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 481 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 482 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 483 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 484 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 485 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 486 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 487 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 488 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 489 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 490 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 491 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 492 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 493 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 494 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 495 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 496 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 497 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 498 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 499 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 500 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 501 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 502 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 503 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 504 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 505 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 506 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 507 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 508 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 509 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 510 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 511 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 512 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 513 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 514 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 515 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 516 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 517 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 518 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 519 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 520 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 521 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 522 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 523 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 524 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 525 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 526 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 527 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 528 | google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= 529 | google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 530 | google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= 531 | google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 532 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 533 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 534 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 535 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 536 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 537 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 538 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 539 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 540 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 541 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 542 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 543 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 544 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 545 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 546 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 547 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 548 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 549 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 550 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 551 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 552 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 553 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 554 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 555 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 556 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 557 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 558 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 559 | k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= 560 | k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= 561 | k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= 562 | k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= 563 | k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= 564 | k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= 565 | k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= 566 | k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= 567 | k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8= 568 | k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= 569 | k8s.io/client-go v0.28.4 h1:Np5ocjlZcTrkyRJ3+T3PkXDpe4UpatQxj85+xjaD2wY= 570 | k8s.io/client-go v0.28.4/go.mod h1:0VDZFpgoZfelyP5Wqu0/r/TRYcLYuJ2U1KEeoaPa1N4= 571 | k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= 572 | k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= 573 | k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= 574 | k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= 575 | k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 h1:GfD9OzL11kvZN5iArC6oTS7RTj7oJOIfnislxYlqTj8= 576 | k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 577 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= 578 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 579 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 580 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 581 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 582 | sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= 583 | sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= 584 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= 585 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= 586 | sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= 587 | sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= 588 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= 589 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= 590 | sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= 591 | sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= 592 | sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= 593 | sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= 594 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: "1.0" 3 | description: A Helm chart for Kubernetes 4 | name: kubesec-webhook 5 | version: 0.1.0 6 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | 1. Get the application URL by running these commands: 2 | {{- if .Values.ingress.enabled }} 3 | {{- range $host := .Values.ingress.hosts }} 4 | {{- range .paths }} 5 | http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }} 6 | {{- end }} 7 | {{- end }} 8 | {{- else if contains "NodePort" .Values.service.type }} 9 | export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "kubesec-webhook.fullname" . }}) 10 | export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") 11 | echo http://$NODE_IP:$NODE_PORT 12 | {{- else if contains "LoadBalancer" .Values.service.type }} 13 | NOTE: It may take a few minutes for the LoadBalancer IP to be available. 14 | You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "kubesec-webhook.fullname" . }}' 15 | export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "kubesec-webhook.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}') 16 | echo http://$SERVICE_IP:{{ .Values.service.port }} 17 | {{- else if contains "ClusterIP" .Values.service.type }} 18 | export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "kubesec-webhook.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 19 | echo "Visit http://127.0.0.1:8080 to use your application" 20 | kubectl port-forward $POD_NAME 8080:80 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* vim: set filetype=mustache: */}} 2 | {{/* 3 | Expand the name of the chart. 4 | */}} 5 | {{- define "kubesec-webhook.name" -}} 6 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 7 | {{- end -}} 8 | 9 | {{/* 10 | Create a default fully qualified app name. 11 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 12 | If release name contains chart name it will be used as a full name. 13 | */}} 14 | {{- define "kubesec-webhook.fullname" -}} 15 | {{- if .Values.fullnameOverride -}} 16 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} 17 | {{- else -}} 18 | {{- $name := default .Chart.Name .Values.nameOverride -}} 19 | {{- if contains $name .Release.Name -}} 20 | {{- .Release.Name | trunc 63 | trimSuffix "-" -}} 21 | {{- else -}} 22 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} 23 | {{- end -}} 24 | {{- end -}} 25 | {{- end -}} 26 | 27 | {{/* 28 | Create chart name and version as used by the chart label. 29 | */}} 30 | {{- define "kubesec-webhook.chart" -}} 31 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 32 | {{- end -}} 33 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "kubesec-webhook.fullname" . }} 5 | labels: 6 | app: {{ include "kubesec-webhook.name" . }} 7 | app.kubernetes.io/name: {{ include "kubesec-webhook.name" . }} 8 | helm.sh/chart: {{ include "kubesec-webhook.chart" . }} 9 | app.kubernetes.io/instance: {{ .Release.Name }} 10 | app.kubernetes.io/managed-by: {{ .Release.Service }} 11 | spec: 12 | replicas: {{ .Values.replicaCount }} 13 | selector: 14 | matchLabels: 15 | app.kubernetes.io/name: {{ include "kubesec-webhook.name" . }} 16 | app.kubernetes.io/instance: {{ .Release.Name }} 17 | template: 18 | metadata: 19 | labels: 20 | app: {{ include "kubesec-webhook.name" . }} 21 | app.kubernetes.io/name: {{ include "kubesec-webhook.name" . }} 22 | app.kubernetes.io/instance: {{ .Release.Name }} 23 | spec: 24 | containers: 25 | - name: {{ .Chart.Name }} 26 | image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 27 | imagePullPolicy: {{ .Values.image.pullPolicy }} 28 | command: 29 | - ./kubesec 30 | args: 31 | - -tls-cert-file=/etc/webhook/certs/cert.pem 32 | - -tls-key-file=/etc/webhook/certs/key.pem 33 | - -min-score=0 34 | - -debug 35 | securityContext: 36 | readOnlyRootFilesystem: true 37 | runAsNonRoot: true 38 | runAsUser: 10001 39 | capabilities: 40 | drop: 41 | - all 42 | add: 43 | - NET_BIND_SERVICE 44 | ports: 45 | - name: http 46 | containerPort: 80 47 | containerPort: 8080 48 | containerPort: 8081 49 | protocol: TCP 50 | livenessProbe: 51 | httpGet: 52 | path: /metrics 53 | port: 8081 54 | readinessProbe: 55 | httpGet: 56 | path: /metrics 57 | port: 8081 58 | resources: 59 | {{- toYaml .Values.resources | nindent 12 }} 60 | {{- with .Values.nodeSelector }} 61 | nodeSelector: 62 | {{- toYaml . | nindent 8 }} 63 | {{- end }} 64 | {{- with .Values.affinity }} 65 | affinity: 66 | {{- toYaml . | nindent 8 }} 67 | {{- end }} 68 | {{- with .Values.tolerations }} 69 | tolerations: 70 | {{- toYaml . | nindent 8 }} 71 | {{- end }} 72 | volumeMounts: 73 | - name: webhook-certs 74 | mountPath: /etc/webhook/certs 75 | readOnly: true 76 | volumes: 77 | - name: webhook-certs 78 | secret: 79 | secretName: {{ include "kubesec-webhook.fullname" . }} 80 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "kubesec-webhook.fullname" . -}} 3 | apiVersion: extensions/v1beta1 4 | kind: Ingress 5 | metadata: 6 | name: {{ $fullName }} 7 | labels: 8 | app.kubernetes.io/name: {{ include "kubesec-webhook.name" . }} 9 | helm.sh/chart: {{ include "kubesec-webhook.chart" . }} 10 | app.kubernetes.io/instance: {{ .Release.Name }} 11 | app.kubernetes.io/managed-by: {{ .Release.Service }} 12 | {{- with .Values.ingress.annotations }} 13 | annotations: 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | spec: 17 | {{- if .Values.ingress.tls }} 18 | tls: 19 | {{- range .Values.ingress.tls }} 20 | - hosts: 21 | {{- range .hosts }} 22 | - {{ . | quote }} 23 | {{- end }} 24 | secretName: {{ .secretName }} 25 | {{- end }} 26 | {{- end }} 27 | rules: 28 | {{- range .Values.ingress.hosts }} 29 | - host: {{ .host | quote }} 30 | http: 31 | paths: 32 | {{- range .paths }} 33 | - path: {{ . }} 34 | backend: 35 | serviceName: {{ $fullName }} 36 | servicePort: http 37 | {{- end }} 38 | {{- end }} 39 | {{- end }} 40 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "kubesec-webhook.name" . }} 5 | labels: 6 | app.kubernetes.io/name: {{ include "kubesec-webhook.name" . }} 7 | helm.sh/chart: {{ include "kubesec-webhook.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | spec: 11 | type: {{ .Values.service.type }} 12 | ports: 13 | - port: {{ .Values.service.port }} 14 | targetPort: {{ .Values.server.port }} 15 | protocol: TCP 16 | name: https 17 | selector: 18 | app.kubernetes.io/name: {{ include "kubesec-webhook.name" . }} 19 | app.kubernetes.io/instance: {{ .Release.Name }} 20 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "kubesec-webhook.fullname" . }}-test-connection" 5 | labels: 6 | app.kubernetes.io/name: {{ include "kubesec-webhook.name" . }} 7 | helm.sh/chart: {{ include "kubesec-webhook.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | annotations: 11 | "helm.sh/hook": test-success 12 | spec: 13 | containers: 14 | - name: wget 15 | image: busybox 16 | command: ['wget'] 17 | args: ['{{ include "kubesec-webhook.fullname" . }}:{{ .Values.service.port }}'] 18 | restartPolicy: Never 19 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/templates/webhook-certs-secrets.yaml: -------------------------------------------------------------------------------- 1 | # This file was generated using openssl by the gen-certs.sh script 2 | {{ $ca := genCA "kubesec-webhook-ca" 365 }} 3 | {{ $cn := printf "kubesec-webhook.%s.svc.cluster.local" .Release.Namespace }} 4 | {{ $server := genSignedCert $cn nil nil 365 $ca }} 5 | apiVersion: v1 6 | kind: Secret 7 | metadata: 8 | name: {{ include "kubesec-webhook.fullname" . }} 9 | type: Opaque 10 | data: 11 | {{- if .Values.server.certData }} 12 | cert.pem: {{ .Values.server.certData }} 13 | {{- else }} 14 | cert.pem: {{ b64enc $server.Cert }} 15 | {{ end }} 16 | {{- if .Values.server.caKeyData }} 17 | key.pem: {{ .Values.server.caKeyData }} 18 | {{- else }} 19 | key.pem: {{ b64enc $server.Key }} 20 | {{ end }} 21 | -------------------------------------------------------------------------------- /helm/kubesec-webhook/values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for kubesec-webhook. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 1 6 | 7 | image: 8 | repository: praveendhac/kubesec-webhook 9 | tag: 0.1-dev 10 | pullPolicy: IfNotPresent 11 | 12 | nameOverride: "" 13 | fullnameOverride: "" 14 | 15 | service: 16 | type: ClusterIP 17 | port: 443 18 | 19 | ingress: 20 | enabled: false 21 | annotations: {} 22 | # kubernetes.io/ingress.class: nginx 23 | # kubernetes.io/tls-acme: "true" 24 | hosts: 25 | - host: chart-example.local 26 | paths: [] 27 | 28 | tls: [] 29 | # - secretName: chart-example-tls 30 | # hosts: 31 | # - chart-example.local 32 | 33 | resources: {} 34 | # We usually recommend not to specify default resources and to leave this as a conscious 35 | # choice for the user. This also increases chances charts run on environments with little 36 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 37 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 38 | # limits: 39 | # cpu: 100m 40 | # memory: 128Mi 41 | # requests: 42 | # cpu: 100m 43 | # memory: 128Mi 44 | 45 | nodeSelector: {} 46 | 47 | tolerations: [] 48 | 49 | affinity: {} 50 | 51 | # The "server" settings control how the webhooks get registered and the ssl certificate security 52 | server: 53 | port: 8443 54 | # Feel free to change the companyDomain to that of your organisation - used in the registration of a webook 55 | companyDomain: kubesec.io 56 | # NOTE: certificates are added as base64 encodings of their data (default cert assumes deployment to 'kubesec' or chart namespace) 57 | -------------------------------------------------------------------------------- /pkg/webhook/default_values.go: -------------------------------------------------------------------------------- 1 | package webhook 2 | 3 | // Default URL and timeout values associated with the upstream Kubesec v2 service 4 | const ( 5 | kubesecScanURL = `https://v2.kubesec.io` 6 | timeOut = 15 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/configmap.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: config 6 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/daemonset-hardened.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: DaemonSet 4 | metadata: 5 | name: fluentd-elasticsearch 6 | namespace: kube-system 7 | labels: 8 | k8s-app: fluentd-logging 9 | spec: 10 | selector: 11 | matchLabels: 12 | name: fluentd-elasticsearch 13 | template: 14 | metadata: 15 | labels: 16 | name: fluentd-elasticsearch 17 | spec: 18 | containers: 19 | - name: fluentd-elasticsearch 20 | image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 21 | securityContext: 22 | readOnlyRootFilesystem: true 23 | runAsUser: 100 24 | runAsNonRoot: true 25 | privileged: false 26 | allowPrivilegeEscalation: false 27 | capabilities: 28 | drop: 29 | - "ALL" 30 | resources: 31 | limits: 32 | memory: 200Mi 33 | requests: 34 | cpu: 100m 35 | memory: 200Mi 36 | volumeMounts: 37 | - name: varlog 38 | mountPath: /var/log 39 | terminationGracePeriodSeconds: 30 40 | volumes: 41 | - name: varlog 42 | hostPath: 43 | path: /var/log 44 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/daemonset-insecure.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: DaemonSet 4 | metadata: 5 | name: fluentd-elasticsearch 6 | namespace: kube-system 7 | labels: 8 | k8s-app: fluentd-logging 9 | spec: 10 | selector: 11 | matchLabels: 12 | name: fluentd-elasticsearch 13 | template: 14 | metadata: 15 | labels: 16 | name: fluentd-elasticsearch 17 | spec: 18 | containers: 19 | - name: fluentd-elasticsearch 20 | image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 21 | securityContext: 22 | readOnlyRootFilesystem: false 23 | runAsNonRoot: false 24 | privileged: true 25 | allowPrivilegeEscalation: true 26 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/deployment-hardened.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: hardened-deployment 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: foo 10 | replicas: 1 11 | template: 12 | metadata: 13 | labels: 14 | app: foo 15 | spec: 16 | containers: 17 | - name: main-container 18 | image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 19 | securityContext: 20 | readOnlyRootFilesystem: true 21 | runAsUser: 100 22 | runAsNonRoot: true 23 | privileged: false 24 | allowPrivilegeEscalation: false 25 | capabilities: 26 | drop: 27 | - "ALL" 28 | resources: 29 | limits: 30 | memory: 200Mi 31 | requests: 32 | cpu: 100m 33 | memory: 200Mi 34 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/deployment-insecure.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: deployment-test 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: nginx 10 | replicas: 1 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | spec: 16 | containers: 17 | - name: main-container 18 | image: quay.io/fluentd_elasticsearch/fluentd:v2.5.2 19 | securityContext: 20 | readOnlyRootFilesystem: false 21 | runAsUser: 100 22 | runAsNonRoot: false 23 | privileged: true 24 | allowPrivilegeEscalation: true 25 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/pod-hardened.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: secure-pod-spec 6 | namespace: foo 7 | spec: 8 | containers: 9 | - name: main 10 | image: busybox 11 | serviceAccount: test 12 | command: [ "sh", "-c", "sleep 1h" ] 13 | securityContext: 14 | readOnlyRootFilesystem: true 15 | runAsUser: 100 16 | runAsNonRoot: true 17 | privileged: false 18 | allowPrivilegeEscalation: false 19 | capabilities: 20 | drop: 21 | - "all" 22 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/pod-insecure.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: Pod 4 | metadata: 5 | name: test 6 | namespace: foo 7 | spec: 8 | containers: 9 | - name: main 10 | image: busybox 11 | serviceAccount: foo 12 | command: [ "sh", "-c", "sleep 1h" ] 13 | securityContext: 14 | readOnlyRootFilesystem: false 15 | privileged: true 16 | runAsNonRoot: false 17 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/statefulset-hardened.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: StatefulSet 4 | metadata: 5 | name: hardened-statefulset 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: hardened-statefulset 10 | serviceName: "statefulset-test-sa" 11 | replicas: 2 12 | template: 13 | metadata: 14 | labels: 15 | app: hardened-statefulset 16 | spec: 17 | containers: 18 | - name: main-container 19 | image: nginx 20 | securityContext: 21 | readOnlyRootFilesystem: true 22 | runAsUser: 100 23 | runAsNonRoot: true 24 | privileged: false 25 | allowPrivilegeEscalation: false 26 | capabilities: 27 | drop: 28 | - "ALL" 29 | resources: 30 | limits: 31 | memory: 200Mi 32 | requests: 33 | cpu: 100m 34 | memory: 200Mi 35 | -------------------------------------------------------------------------------- /pkg/webhook/testdata/statefulset-insecure.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: StatefulSet 4 | metadata: 5 | name: web 6 | spec: 7 | selector: 8 | matchLabels: 9 | app: insecure-statefulset 10 | serviceName: "statefulset-test-sa" 11 | replicas: 2 12 | template: 13 | metadata: 14 | labels: 15 | app: insecure-statefulset 16 | spec: 17 | containers: 18 | - name: main-container 19 | image: nginx 20 | securityContext: 21 | readOnlyRootFilesystem: false 22 | runAsUser: 0 23 | runAsNonRoot: false 24 | privileged: true 25 | allowPrivilegeEscalation: true 26 | -------------------------------------------------------------------------------- /pkg/webhook/webhook.go: -------------------------------------------------------------------------------- 1 | package webhook 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "encoding/json" 7 | "fmt" 8 | 9 | kubesecv2 "github.com/controlplaneio/kubectl-kubesec/v2/pkg/kubesec" 10 | "github.com/slok/kubewebhook/v2/pkg/log" 11 | "github.com/slok/kubewebhook/v2/pkg/model" 12 | "github.com/slok/kubewebhook/v2/pkg/webhook" 13 | "github.com/slok/kubewebhook/v2/pkg/webhook/validating" 14 | appsv1 "k8s.io/api/apps/v1" 15 | v1 "k8s.io/api/core/v1" 16 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 17 | "k8s.io/apimachinery/pkg/runtime" 18 | kjson "k8s.io/apimachinery/pkg/runtime/serializer/json" 19 | "k8s.io/client-go/kubernetes/scheme" 20 | ) 21 | 22 | // kubesecValidator validates a definition against the Kubesec.io score. 23 | type validator struct { 24 | minScore int 25 | logger log.Logger 26 | } 27 | 28 | var _ validating.Validator = &validator{} 29 | 30 | // New returns a new validating webhook. 31 | func New(minScore int, logger log.Logger) (webhook.Webhook, error) { 32 | val := &validator{ 33 | minScore: minScore, 34 | logger: logger, 35 | } 36 | 37 | cfg := validating.WebhookConfig{ 38 | ID: "kubesec", 39 | Validator: val, 40 | Logger: logger, 41 | } 42 | 43 | return validating.NewWebhook(cfg) 44 | } 45 | 46 | // Validate implements the validator interface to validate a resource. 47 | func (v *validator) Validate(_ context.Context, _ *model.AdmissionReview, obj metav1.Object) (*validating.ValidatorResult, error) { 48 | // Make sure the input object is a supported resource 49 | var kObj runtime.Object 50 | switch o := obj.(type) { 51 | case *appsv1.DaemonSet: 52 | kObj = o 53 | case *appsv1.Deployment: 54 | kObj = o 55 | case *v1.Pod: 56 | kObj = o 57 | case *appsv1.StatefulSet: 58 | kObj = o 59 | default: 60 | return &validating.ValidatorResult{ 61 | Valid: true, 62 | Warnings: []string{"resource kind not supported, validation skipped"}, 63 | }, nil 64 | } 65 | 66 | // Logging 67 | logFields := map[string]interface{}{ 68 | "kind": kObj.GetObjectKind().GroupVersionKind().Kind, 69 | "namespace": obj.GetNamespace(), 70 | "name": obj.GetName(), 71 | } 72 | logger := v.logger.WithValues(logFields) 73 | 74 | // Serialize the runtime object to yaml 75 | serializer := kjson.NewYAMLSerializer(kjson.DefaultMetaFactory, scheme.Scheme, scheme.Scheme) 76 | buf := bytes.NewBuffer([]byte{}) 77 | err := serializer.Encode(kObj, buf) 78 | if err != nil { 79 | return &validating.ValidatorResult{}, fmt.Errorf("serialization failed: %w", err) 80 | } 81 | 82 | // Scan using kubesec.io 83 | logger.WithValues(log.Kv{"status": "running"}).Infof("scan resource") 84 | results, err := scan(*buf) 85 | if err != nil { 86 | logger.WithValues(log.Kv{"status": "failed", "error": err}).Infof("scan finished with error") 87 | return &validating.ValidatorResult{}, err 88 | } 89 | result := results[0] 90 | 91 | jq, err := json.MarshalIndent(results, "", " ") 92 | if err != nil { 93 | return &validating.ValidatorResult{}, fmt.Errorf("kubesec.io pretty printing issue %v", err) 94 | } 95 | 96 | logger.WithValues(log.Kv{"status": "success", "result": string(jq)}).Infof("scan finished successfuly") 97 | 98 | if result.Score < v.minScore { 99 | return &validating.ValidatorResult{ 100 | Valid: false, 101 | Message: fmt.Sprintf("%s score is %d, minimum accepted score is %d\nScan Result:\n%s", obj.GetName(), result.Score, v.minScore, jq), 102 | }, nil 103 | } 104 | 105 | return &validating.ValidatorResult{Valid: true}, nil 106 | } 107 | 108 | // scan is a small wrapper for scanning a manifest definition against kubesec.io 109 | func scan(definition bytes.Buffer) ([]kubesecv2.KubesecResult, error) { 110 | results, err := kubesecv2.NewClient(kubesecScanURL, timeOut). 111 | ScanDefinition(definition) 112 | if err != nil { 113 | return results, fmt.Errorf("kubesec.io scan failed: %w", err) 114 | } 115 | 116 | if len(results) != 1 { 117 | return results, fmt.Errorf("scan failed as result is empty") 118 | } 119 | 120 | if results[0].Error != "" { 121 | return results, fmt.Errorf("kubesec.io scan failed: %s", results[0].Error) 122 | } 123 | 124 | return results, nil 125 | } 126 | -------------------------------------------------------------------------------- /pkg/webhook/webhook_test.go: -------------------------------------------------------------------------------- 1 | package webhook 2 | 3 | import ( 4 | "context" 5 | "io/ioutil" 6 | "os" 7 | "path/filepath" 8 | "testing" 9 | 10 | "github.com/sirupsen/logrus" 11 | "github.com/sirupsen/logrus/hooks/test" 12 | "github.com/slok/kubewebhook/v2/pkg/log" 13 | kwhlogrus "github.com/slok/kubewebhook/v2/pkg/log/logrus" 14 | appsv1 "k8s.io/api/apps/v1" 15 | v1 "k8s.io/api/core/v1" 16 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 17 | "k8s.io/client-go/kubernetes/scheme" 18 | ) 19 | 20 | type testCase struct { 21 | name string // name of the test 22 | valid bool // should the resource to be allowed 23 | minScore int // minimum score used for initialisation 24 | specFilepath string // path to manifest file 25 | expectedWarnings int // we expected warning for non supported resources 26 | } 27 | 28 | // TestValidate - tests the validation of hardened and insecure YAML manifests 29 | // The hardened manifest should be allowed by the webhook and the insecure should be blocked 30 | func TestValidate(t *testing.T) { 31 | tests := []testCase{ 32 | { 33 | name: "Hardened DaemonSet Spec", 34 | valid: true, 35 | minScore: 0, 36 | specFilepath: "./testdata/daemonset-hardened.yaml", 37 | }, 38 | { 39 | name: "Insecure DaemonSet Spec", 40 | valid: false, 41 | minScore: 0, 42 | specFilepath: "./testdata/daemonset-insecure.yaml", 43 | }, 44 | { 45 | name: "Hardened Deployment Spec", 46 | valid: true, 47 | minScore: 0, 48 | specFilepath: "./testdata/deployment-hardened.yaml", 49 | }, 50 | { 51 | name: "Insecure Deployment Spec", 52 | valid: false, 53 | minScore: 0, 54 | specFilepath: "./testdata/deployment-insecure.yaml", 55 | }, 56 | { 57 | name: "Hardened Pod Spec.", 58 | valid: true, 59 | minScore: 0, 60 | specFilepath: "./testdata/pod-hardened.yaml", 61 | }, 62 | { 63 | name: "Insecure Pod Spec", 64 | valid: false, 65 | minScore: 0, 66 | specFilepath: "./testdata/pod-insecure.yaml", 67 | }, 68 | { 69 | name: "Hardened Statefulset Spec", 70 | valid: true, 71 | minScore: 0, 72 | specFilepath: "./testdata/statefulset-hardened.yaml", 73 | }, 74 | { 75 | name: "Insecure Statefulset Spec", 76 | valid: false, 77 | minScore: 0, 78 | specFilepath: "./testdata/statefulset-insecure.yaml", 79 | }, 80 | { 81 | name: "Unsupported resource", 82 | // we don't validate this kind of resource so we consider it valid 83 | valid: true, 84 | minScore: 0, 85 | expectedWarnings: 1, 86 | specFilepath: "./testdata/configmap.yaml", 87 | }, 88 | } 89 | for _, tt := range tests { 90 | tt := tt 91 | t.Run(tt.name, func(t *testing.T) { 92 | t.Parallel() 93 | 94 | manifest, err := ioutil.ReadFile(filepath.Clean(tt.specFilepath)) 95 | if err != nil { 96 | t.Fatalf("error opening fixture file: %v", err) 97 | } 98 | 99 | decode := scheme.Codecs.UniversalDeserializer().Decode 100 | obj, _, err := decode(manifest, nil, nil) 101 | 102 | if err != nil { 103 | t.Fatalf("Unable to decode YAML object: %s", err.Error()) 104 | } 105 | 106 | switch o := obj.(type) { 107 | case *appsv1.DaemonSet: 108 | testValidator(t, o, tt) 109 | case *appsv1.Deployment: 110 | testValidator(t, o, tt) 111 | case *v1.Pod: 112 | testValidator(t, o, tt) 113 | case *appsv1.StatefulSet: 114 | testValidator(t, o, tt) 115 | case *v1.ConfigMap: 116 | testValidator(t, o, tt) 117 | default: 118 | t.Fatalf("resource kind not supported for testing") 119 | } 120 | }) 121 | } 122 | } 123 | 124 | func testValidator(t *testing.T, obj metav1.Object, tt testCase) { 125 | var logger log.Logger 126 | if _, ok := os.LookupEnv("TEST_ENABLE_LOGGING"); ok { 127 | logrusLogEntry := logrus.NewEntry(logrus.New()) 128 | logger = kwhlogrus.NewLogrus(logrusLogEntry) 129 | } else { 130 | loggerN, _ := test.NewNullLogger() 131 | logrusLogEntry := logrus.NewEntry(loggerN) 132 | logger = kwhlogrus.NewLogrus(logrusLogEntry) 133 | } 134 | 135 | v := validator{ 136 | minScore: tt.minScore, 137 | logger: logger, 138 | } 139 | 140 | resp, err := v.Validate(context.Background(), nil, obj) 141 | if err != nil { 142 | t.Fatalf("Unexpected error: %s", err.Error()) 143 | } 144 | 145 | if len(resp.Warnings) != tt.expectedWarnings { 146 | t.Errorf("Unexpected number of warnings, got=%d, want=%d", len(resp.Warnings), tt.expectedWarnings) 147 | } 148 | 149 | if resp.Valid != tt.valid { 150 | t.Fatalf("Invalid resource correctness, got=%v, want=%v", resp.Valid, tt.valid) 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /test/daemonset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: DaemonSet 3 | metadata: 4 | name: daemonset-test 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: daemonset-test 9 | template: 10 | metadata: 11 | labels: 12 | app: daemonset-test 13 | spec: 14 | containers: 15 | - name: nginx 16 | image: nginx 17 | securityContext: 18 | privileged: true 19 | -------------------------------------------------------------------------------- /test/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: deployment-test 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: nginx 9 | replicas: 1 10 | template: 11 | metadata: 12 | labels: 13 | app: nginx 14 | spec: 15 | containers: 16 | - name: nginx 17 | image: nginx 18 | securityContext: 19 | privileged: true 20 | -------------------------------------------------------------------------------- /test/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: pod-test 5 | spec: 6 | containers: 7 | - name: nginx 8 | image: nginx 9 | securityContext: 10 | privileged: true 11 | -------------------------------------------------------------------------------- /test/statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: statefulset-test 5 | spec: 6 | selector: 7 | matchLabels: 8 | app: statefulset-test 9 | serviceName: "statefulset-test" 10 | replicas: 2 11 | template: 12 | metadata: 13 | labels: 14 | app: statefulset-test 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx 19 | securityContext: 20 | privileged: true 21 | --------------------------------------------------------------------------------