From 9dc412423a35ab19d0e5c0dfe0d8f0311c9bb73b Mon Sep 17 00:00:00 2001 From: Seth Jennings Date: Mon, 18 Apr 2022 09:51:15 -0500 Subject: [PATCH] contrib: admission-tracer for API call tracing --- .gitignore | 2 +- contrib/admission-tracer/Dockerfile | 3 + contrib/admission-tracer/Makefile | 28 +++++++ contrib/admission-tracer/main.go | 78 +++++++++++++++++++ .../manifests/deployment.yaml | 39 ++++++++++ .../admission-tracer/manifests/service.yaml | 18 +++++ .../validatingwebhookconfiguration.yaml | 30 +++++++ 7 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 contrib/admission-tracer/Dockerfile create mode 100644 contrib/admission-tracer/Makefile create mode 100644 contrib/admission-tracer/main.go create mode 100644 contrib/admission-tracer/manifests/deployment.yaml create mode 100644 contrib/admission-tracer/manifests/service.yaml create mode 100644 contrib/admission-tracer/manifests/validatingwebhookconfiguration.yaml diff --git a/.gitignore b/.gitignore index 1d0594b1f5..802e18397b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,4 @@ tools/bin # ignore util binaries /contrib/cleanzones/cleanzones - +/contrib/admission-tracer/admission-tracer diff --git a/contrib/admission-tracer/Dockerfile b/contrib/admission-tracer/Dockerfile new file mode 100644 index 0000000000..02a18b0ada --- /dev/null +++ b/contrib/admission-tracer/Dockerfile @@ -0,0 +1,3 @@ +FROM quay.io/openshift/origin-base:4.11 +COPY admission-tracer /usr/bin/ +ENTRYPOINT /usr/bin/admission-tracer diff --git a/contrib/admission-tracer/Makefile b/contrib/admission-tracer/Makefile new file mode 100644 index 0000000000..d0b8f09f80 --- /dev/null +++ b/contrib/admission-tracer/Makefile @@ -0,0 +1,28 @@ + +IMG=quay.io/sjenning/admission-tracer:latest +RUNTIME ?= podman +GO_GCFLAGS ?= -gcflags=all='-N -l' +GO=GO111MODULE=on GOFLAGS=-mod=vendor go +GO_BUILD_RECIPE=CGO_ENABLED=0 $(GO) build $(GO_GCFLAGS) + +all: build image push + +.PHONY: build +build: + $(GO_BUILD_RECIPE) . + +.PHONY: image +image: build + ${RUNTIME} build . -t ${IMG} + +.PHONY: push +push: image + ${RUNTIME} push ${IMG} + +.PHONY: deploy +deploy: + oc apply -f manifests/ + +.PHONY: redeploy +redeploy: + oc patch deployment -n hypershift admission-tracer -p "{\"spec\":{\"template\":{\"metadata\":{\"annotations\":{\"date\":\"$(shell date +%s)\"}}}}}" \ No newline at end of file diff --git a/contrib/admission-tracer/main.go b/contrib/admission-tracer/main.go new file mode 100644 index 0000000000..66df46f952 --- /dev/null +++ b/contrib/admission-tracer/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "bytes" + "context" + "fmt" + "log" + "net/http" + + "github.com/google/go-cmp/cmp" + hyperapi "github.com/openshift/hypershift/api" + hyperv1 "github.com/openshift/hypershift/api/v1alpha1" + + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + admissionv1 "k8s.io/api/admission/v1" +) + +func main() { + ctx := ctrl.SetupSignalHandler() + + restConfig := ctrl.GetConfigOrDie() + restConfig.UserAgent = "admission-differ" + mgr, err := ctrl.NewManager(restConfig, ctrl.Options{ + Scheme: hyperapi.Scheme, + Port: 9443, + CertDir: "/var/run/secrets/serving-cert", + }) + if err != nil { + log.Fatalf("unable to start manager: %s", err.Error()) + } + + hookServer := mgr.GetWebhookServer() + hookServer.Register("/awsendpointservices", &webhook.Admission{Handler: &awsEndpointServiceAdmissionTracer{}}) + + err = mgr.Start(ctx) + if err != nil { + log.Fatalf("Start returned with error: %s", err.Error()) + } +} + +type awsEndpointServiceAdmissionTracer struct { + decoder *admission.Decoder +} + +var _ admission.Handler = &awsEndpointServiceAdmissionTracer{} + +func (v *awsEndpointServiceAdmissionTracer) Handle(_ context.Context, req admission.Request) admission.Response { + new := &hyperv1.AWSEndpointService{} + err := v.decoder.Decode(req, new) + if err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + var output bytes.Buffer + fmt.Fprintf(&output, "%s %s %s\n", new.Name, req.Operation, req.UserInfo.Username) + switch req.Operation { + case admissionv1.Create: + fmt.Fprintf(&output, "+%v", new) + case admissionv1.Update: + old := &hyperv1.AWSEndpointService{} + err = v.decoder.DecodeRaw(req.OldObject, old) + if err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + fmt.Fprint(&output, cmp.Diff(old, new)) + } + fmt.Println(output.String()) + return admission.Allowed("") +} + +var _ admission.DecoderInjector = &awsEndpointServiceAdmissionTracer{} + +func (v *awsEndpointServiceAdmissionTracer) InjectDecoder(d *admission.Decoder) error { + v.decoder = d + return nil +} diff --git a/contrib/admission-tracer/manifests/deployment.yaml b/contrib/admission-tracer/manifests/deployment.yaml new file mode 100644 index 0000000000..deb31902cf --- /dev/null +++ b/contrib/admission-tracer/manifests/deployment.yaml @@ -0,0 +1,39 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: admission-tracer + namespace: hypershift +spec: + replicas: 1 + selector: + matchLabels: + app: admission-tracer + template: + metadata: + labels: + app: admission-tracer + spec: + containers: + - command: + - /usr/bin/admission-tracer + image: quay.io/sjenning/admission-tracer:latest + imagePullPolicy: Always + name: admission-tracer + ports: + - containerPort: 9443 + name: manager + protocol: TCP + resources: + requests: + cpu: 10m + memory: 20Mi + volumeMounts: + - mountPath: /var/run/secrets/serving-cert + name: serving-cert + priorityClassName: hypershift-operator + serviceAccountName: operator + volumes: + - name: serving-cert + secret: + defaultMode: 420 + secretName: admission-tracer-serving-cert diff --git a/contrib/admission-tracer/manifests/service.yaml b/contrib/admission-tracer/manifests/service.yaml new file mode 100644 index 0000000000..0d949de939 --- /dev/null +++ b/contrib/admission-tracer/manifests/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + service.beta.openshift.io/serving-cert-secret-name: admission-tracer-serving-cert + labels: + app: admission-tracer + name: admission-tracer + namespace: hypershift +spec: + ports: + - name: manager + port: 443 + protocol: TCP + targetPort: manager + selector: + app: admission-tracer + type: ClusterIP diff --git a/contrib/admission-tracer/manifests/validatingwebhookconfiguration.yaml b/contrib/admission-tracer/manifests/validatingwebhookconfiguration.yaml new file mode 100644 index 0000000000..6046e484c3 --- /dev/null +++ b/contrib/admission-tracer/manifests/validatingwebhookconfiguration.yaml @@ -0,0 +1,30 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + annotations: + service.beta.openshift.io/inject-cabundle: "true" + name: admissiontracer.hypershift.openshift.io + namespace: hypershift +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: admission-tracer + namespace: hypershift + path: /awsendpointservices + name: awsendpointservices.hypershift.openshift.io + rules: + - apiGroups: + - hypershift.openshift.io + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - awsendpointservices + - awsendpointservices/status + scope: Namespaced + sideEffects: None + timeoutSeconds: 10 \ No newline at end of file