Skip to content

Commit

Permalink
Feat/metrics (#5)
Browse files Browse the repository at this point in the history
* build post image

* add dockerfile postjob

* build image only on tags

* build image only on tags

* set cosign 1.8.0 in workflow

* WIP: init chart

* sign only ghcr

* sign with new key and cosign 2.0

* add healthz func

* go 1.20

* add missing atomic

* healthz return always OK

* fix atomic

* service healthz on 8081

* extra go rotine for mserver

* final chart release

* add prometheus

* act ob metrics uri

* reorder requests

* new handle func

* duplicate metric register

* fix depends

* servicemonitor and dashboard for app

* cleanup & doc

* build helm chart

* push to chart repo

* update doc
  • Loading branch information
eumel8 authored Mar 21, 2023
1 parent 14c7f9e commit 63cfdc2
Show file tree
Hide file tree
Showing 175 changed files with 31,386 additions and 9 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,11 @@ jobs:
POSTIMAGE: cosignpostjob
COSIGN_KEY: ${{secrets.COSIGN_KEY}}
COSIGN_PASSWORD: ${{secrets.COSIGN_PASSWORD}}
- name: Helm lint & package & push
run: |
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
helm version
HELM_EXPERIMENTAL_OCI=1 helm registry login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
helm lint chart
helm package chart
HELM_EXPERIMENTAL_OCI=1 helm push $(ls *.tgz| head -1) oci://ghcr.io/${{ github.actor }}/charts
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@ Kubernetes Validation Admission Controller to verify Cosign Image signatures.

Watch POD creating in deployments, looking for the first container image and a present RSA publik key to verify.

# Installation
# Installation with Helm

```bash
helm -n cosignwebhook upgrade -i cosignwebhook oci://ghcr.io/eumel8/charts/cosignwebhook --versi
on 2.0.0 --create-namespace
```

this installation has some advantages:

* auto generate TLS key pair
* setup ServiceMonitor and GrafanaDashboard

# Installation with manifest

As Cluster Admin create a namespace and install the Admission Controller:

Expand Down
6 changes: 5 additions & 1 deletion chart/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ apiVersion: v2
name: cosignwebhook
description: A Helm chart for Cosign Webhook Admission Controller
type: application
version: 0.1.0
version: 2.0.0
appVersion: "2.0.0"
maintainers:
- name: eumel8
email: [email protected]
url: https://www.telekom.com
155 changes: 155 additions & 0 deletions chart/templates/configmap-dashboard.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
{{ if .Values.grafanaDashboard.enabled }}
---
apiVersion: v1
data:
cosign-webhook.json: |-
{
"annotations": {
"list": [
{
"builtIn": 1,
"datasource": "-- Grafana --",
"enable": true,
"hide": true,
"iconColor": "rgba(0, 211, 255, 1)",
"name": "Annotations & Alerts",
"type": "dashboard"
}
]
},
"editable": true,
"gnetId": null,
"graphTooltip": 0,
"id": 39,
"links": [],
"panels": [
{
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
"datasource": null,
"description": "Monitor Cosign Webhook Activities",
"fieldConfig": {
"defaults": {},
"overrides": []
},
"fill": 1,
"fillGradient": 0,
"gridPos": {
"h": 9,
"w": 12,
"x": 0,
"y": 0
},
"hiddenSeries": false,
"id": 2,
"legend": {
"avg": false,
"current": false,
"max": false,
"min": false,
"show": true,
"total": false,
"values": false
},
"lines": true,
"linewidth": 1,
"nullPointMode": "null",
"options": {
"alertThreshold": true
},
"percentage": false,
"pluginVersion": "7.5.11",
"pointradius": 2,
"points": false,
"renderer": "flot",
"seriesOverrides": [],
"spaceLength": 10,
"stack": false,
"steppedLine": false,
"targets": [
{
"exemplar": true,
"expr": "rate(cosign_processed_ops_total[5m])",
"interval": "",
"legendFormat": "Cosign Process Operations Total",
"refId": "A"
},
{
"exemplar": true,
"expr": "rate(cosign_processed_verified_total[5m])",
"hide": false,
"interval": "",
"legendFormat": "Cosign Verfified Operations Total",
"refId": "B"
}
],
"thresholds": [],
"timeFrom": null,
"timeRegions": [],
"timeShift": null,
"title": "Cosign Webhook",
"tooltip": {
"shared": true,
"sort": 0,
"value_type": "individual"
},
"type": "graph",
"xaxis": {
"buckets": null,
"mode": "time",
"name": null,
"show": true,
"values": []
},
"yaxes": [
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
},
{
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": null,
"show": true
}
],
"yaxis": {
"align": false,
"alignLevel": null
}
}
],
"schemaVersion": 27,
"style": "dark",
"tags": [],
"templating": {
"list": []
},
"time": {
"from": "now-5m",
"to": "now"
},
"timepicker": {},
"timezone": "",
"title": "Cosign Webhook Operations",
"uid": "7jU1pnfVk",
"version": 1
}
kind: ConfigMap
metadata:
name: {{ include "cosignwebhook.fullname" . }}
{{ if .Values.grafanaDashboard.namespace }}
namespace: {{ .Values.grafanaDashboard.namespace }}
{{ end }}
labels:
grafana_dashboard: "1"
{{- include "cosignwebhook.labels" . | nindent 4 }}
{{ end }}
5 changes: 4 additions & 1 deletion chart/templates/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ spec:
type: {{ .Values.service.type }}
ports:
- name: webhook
port: {{ .Values.service.port }}
port: {{ .Values.service.webhookPort }}
targetPort: {{ .Values.service.targetPort }}
- name: metrics
port: {{ .Values.service.monitorPort }}
targetPort: {{ .Values.service.metricPort }}
selector:
{{- include "cosignwebhook.selectorLabels" . | nindent 4 }}
17 changes: 17 additions & 0 deletions chart/templates/servicemonitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{{ if .Values.serviceMonitor.enabled }}
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "cosignwebhook.fullname" . }}
labels:
{{- include "cosignwebhook.labels" . | nindent 4 }}
spec:
endpoints:
- port: metrics
interval: 10s
path: /metrics
selector:
matchLabels:
{{- include "cosignwebhook.selectorLabels" . | nindent 6 }}
{{ end }}
21 changes: 20 additions & 1 deletion chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ admission:

podAnnotations: {}

# minimal permissions for pod
podSecurityContext:
fsGroup: 1000
supplementalGroups:
- 1000

# minimal permissions for container
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
Expand All @@ -41,14 +43,26 @@ securityContext:
runAsUser: 1000
runAsGroup: 1000


# service for Webhook endpoint and Monitoring
service:
type: ClusterIP
port: 443
monitorPort: 80
webhookPort: 443
# targetPort and metricPort are static in the cosignwebhook app
# configurable options for later
targetPort: 8080
metricPort: 8081

serviceMonitor:
enabled: false

# install a Grafana Dashboard (optional on a specific namespace)
grafanaDashboard:
enabled: false
# namespace: cattle-dashboards

# resources for InitContainer
initresources:
limits:
cpu: 100m
Expand All @@ -57,6 +71,7 @@ initresources:
cpu: 10m
memory: 64Mi

# resources for Container
resources:
limits:
memory: 250Mi
Expand All @@ -78,6 +93,9 @@ tolerations: []

affinity: {}

# verify all images before usage
# sccosign: verify the cosign cli image itself
# scwebhook: verify the cosign webhook image
cosign:
image:
repository: ghcr.io/sigstore/cosign/cosign
Expand All @@ -96,6 +114,7 @@ cosign:
ZvVnR15G9EILCH8+elXkYy+4U70mR++XIL0iD8NhZ3kxfpFjxyHlnG5Snw==
-----END PUBLIC KEY-----
# postjob generates a new TLS keypair after application installation
postjob:
image:
repository: ghcr.io/eumel8/cosignwebhook/cosignpostjob
Expand Down
18 changes: 15 additions & 3 deletions cosignwebhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/sigstore/sigstore/pkg/cryptoutils"
"github.com/sigstore/sigstore/pkg/signature"

)

const (
Expand Down Expand Up @@ -53,9 +54,10 @@ func (cs *CosignServerHandler) serve(w http.ResponseWriter, r *http.Request) {
body = data
}
}
if len(body) == 0 {
glog.Error("empty body")
http.Error(w, "empty body", http.StatusBadRequest)

// Url path of metrics
if r.URL.Path == "/metrics" {
w.WriteHeader(http.StatusOK)
return
}

Expand All @@ -66,6 +68,14 @@ func (cs *CosignServerHandler) serve(w http.ResponseWriter, r *http.Request) {
return
}

if len(body) == 0 {
glog.Error("empty body")
http.Error(w, "empty body", http.StatusBadRequest)
return
}

// count each request for prometheus metric
opsProcessed.Inc()
arRequest := v1.AdmissionReview{}
if err := json.Unmarshal(body, &arRequest); err != nil {
glog.Error("incorrect body")
Expand Down Expand Up @@ -206,6 +216,8 @@ func (cs *CosignServerHandler) serve(w http.ResponseWriter, r *http.Request) {
http.Error(w, fmt.Sprintf("could not write response: %v", err), http.StatusInternalServerError)
}
} else {
// count successful verifies for prometheus metric
verifiedProcessed.Inc()
glog.Info("Image successful verified: ", pod.Namespace, "/", pod.Name)
resp, err := json.Marshal(admissionResponse(200, true, "Success", "Cosign image verified", &arRequest))
if err != nil {
Expand Down
8 changes: 7 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/golang/glog v1.0.0
github.com/google/go-containerregistry v0.12.1
github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20230104193340-e797859b62b6
github.com/prometheus/client_golang v1.14.0
github.com/sigstore/cosign v1.13.1
github.com/sigstore/cosign/v2 v2.0.0-rc.0
github.com/sigstore/sigstore v1.5.0
Expand Down Expand Up @@ -41,7 +42,9 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.17.6 // indirect
github.com/aws/smithy-go v1.13.5 // indirect
github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20221004211355-a250ad2ca1e3 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver v3.5.1+incompatible // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/chrismellard/docker-credential-acr-env v0.0.0-20221002210726-e883f69e0206 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.12.1 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20210823021906-dc406ceaf94b // indirect
Expand Down Expand Up @@ -90,6 +93,7 @@ require (
github.com/letsencrypt/boulder v0.0.0-20221109233200-85aa52084eaf // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
Expand All @@ -102,7 +106,9 @@ require (
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/sassoftware/relic v0.0.0-20210427151427-dfb082b79b74 // indirect
github.com/secure-systems-lab/go-securesystemslib v0.4.0 // indirect
Expand Down
Loading

0 comments on commit 63cfdc2

Please sign in to comment.