Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Simple validation webhook with Python
Ashok Nagaraj
Ashok Nagaraj

Posted on

     

Simple validation webhook with Python

We will implement a simplevalidation webhook to achieve the following:

  • Input conditions:
  • Applicable to all namespaces where label:ngaddons/validation-webhooks isenabled
  • Applicable to object-types:Deployments andPods
  • Not applicable if label:ngaddons/bypass is set on the object

  • Validation logic

  • Fail the object creation unless all of these labels are set:'ngaddons/ownerId', 'ngaddons/webexRoomId', 'ngaddons/appName'

  • Bypass the checks ifngaddons/bypass is set


Webhook code
importloggingimportosfromflaskimportFlask,jsonify,requestapp=Flask('webhook')app.logger.addHandler(logging.StreamHandler())app.logger.setLevel(logging.DEBUG)#Health check@app.route("/healthz",methods=['GET'])defping():returnjsonify({'message':'ok'})REQUIRED_LABELS=['ngaddons/ownerId','ngaddons/webexRoomId','ngaddons/appName']@app.route('/validate',methods=['POST'])defdeployment_webhook():r=request.get_json()req=r.get('request',{})try:ifnotreq:returnsend_response(False,'<no uid>',"Invalid request, no payload.request found")uid=req.get("uid",'')app.logger.debug(f"+ uid:{uid}")ifnotuid:returnsend_response(False,'<no uid>',"Invalid request, no payload.request.uid found")labels=req.get("object",{}).get("metadata",{}).get("labels")if'ngaddons/bypass'inlabels:returnsend_response(True,uid,"Request bypassed as 'ngaddons/bypass' is set")missing=[lforlinREQUIRED_LABELSiflnotinlabels]app.logger.debug(f"+ missing:{missing}")ifmissing:returnsend_response(False,uid,f"Missing labels:{missing}")exceptExceptionase:returnsend_response(False,uid,f"Webhook exception:{e}")#Send OKreturnsend_response(True,uid,"Request has required labels")#Function to respond back to the Admission Controllerdefsend_response(allowed,uid,message):returnjsonify({"apiVersion":"admission.k8s.io/v1","kind":"AdmissionReview","response":{"allowed":allowed,"uid":uid,"status":{"message":message}}})if__name__=="__main__":ca_crt='/etc/ssl/ca.crt'ca_key='/etc/ssl/ca.key'app.run(ssl_context=(ca_crt,ca_key),port=5000,host='0.0.0.0',debug=True)
Enter fullscreen modeExit fullscreen mode
Dockerfile
# Image: ashoka007/check-labels:0.1FROM python:3.8-slimWORKDIR /appCOPY requirements.txt /appRUNpipinstall-r requirements.txtCOPY app.py /appCMD python app.py
Enter fullscreen modeExit fullscreen mode
Webhook manifest
apiVersion:admissionregistration.k8s.io/v1kind:ValidatingWebhookConfigurationmetadata:name:ngaddons-check-labelsnamespace:check-labelswebhooks:-name:ngaddons.check-labels.webhookfailurePolicy:FailsideEffects:NoneadmissionReviewVersions:["v1","v1beta1"]namespaceSelector:matchLabels:ngaddons/validation-webhooks:enabledrules:-apiGroups:["apps",""]resources:-"deployments"-"pods"apiVersions:-"*"operations:-CREATEclientConfig:service:name:${WEBHOOK_SERVICE_NAME}# to be substitutednamespace:${WEBHOOK_NAMESPACE}# to be substitutedpath:/validate/caBundle:${CA_BUNDLE}# to be substituted
Enter fullscreen modeExit fullscreen mode
Create self-signed key-pair and ${CA_BUNDLE}
# Configuration parameters are the key and DNS match is required[ req]default_bits= 2048distinguished_name= req_distinguished_namereq_extensions= req_extprompt= no[ req_distinguished_name]countryName= INstateOrProvinceName= KARlocalityName= BGLorganizationName= ACME INCcommonName= check-labels 0.1[ req_ext]subjectAltName= @alt_names[alt_names]DNS.1=${WEBHOOK_SERVICE_NAME}.${WEBHOOK_NAMESPACE}.svc❯ openssl req-x509-newkey rsa:4096-nodes-out certs/ca.crt-keyout certs/ca.key-days 365-config conf/ext.cnf-extensions req_ext
Enter fullscreen modeExit fullscreen mode
Create a secret with the above
❯ kubectl create secret tls webhook-secret--cert=certs/ca.crt--key=certs/ca.key--namespace=${WEBHOOK_NAMESPACE}
Enter fullscreen modeExit fullscreen mode
Create namespace
❯ kubectl create namespace${WEBHOOK_NAMESPACE}
Enter fullscreen modeExit fullscreen mode
Kubernetes manifest for webhook deployment
apiVersion:apps/v1kind:Deploymentmetadata:name:webhook-depnamespace:${WEBHOOK_NAMESPACE}labels:app:webhookspec:replicas:2selector:matchLabels:app:webhooktemplate:metadata:labels:app:webhookspec:containers:-name:webhook-containerimage:ashoka007/check-labels:0.1volumeMounts:-mountPath:/etc/sslname:webhook-certsreadOnly:truevolumes:-name:webhook-certssecret:secretName:webhook-secret
Enter fullscreen modeExit fullscreen mode
Expose the deployment with service
❯ kubectl expose deployment/webhook-dep--name=${WEBHOOK_SERVICE_NAME}--namespace=${WEBHOOK_NAMESPACE}--port=443--target-port=5000
Enter fullscreen modeExit fullscreen mode

Test
❯ kubectl create namespace demo-ns# normal scenario❯ kubectl run testpod--image=nginx-n demo-nspod/testpod created# start enforcing validation❯ kubectl label namespace demo-ns-l ngaddons/validation-webhooks=enabled# validation fail❯ kubectl run testpod2--image=nginx-n demo-nsError from server: admission webhook"ngaddons.check-labels.webhook" denied the request: Missing labels:['ngaddons/ownerCec','ngaddons/webexRoomId','ngaddons/appName']# validation pass❯ kubectl run testpod3--image=nginx-n demo-ns-l=ngaddons/ownerId=ram-l=ngaddons/webexRoomId=rams-room-id-l=ngaddons/appName=rams-test-apppod/testpod3 created# validation bypass❯ kubectl run testpod4--image=nginx-n demo-ns-l=ngaddons/bypassed=1pod/testpod4 created
Enter fullscreen modeExit fullscreen mode
Delete validation webhook
❯ kubectl delete validatingwebhookconfigurations.admissionregistration.k8s.io check-labels
Enter fullscreen modeExit fullscreen mode

Source code

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
michael_odell_af5d95ecf70 profile image
Michael Odell
  • Joined

Thanks! This helped me today.

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Software developer at Cisco working on Kubernetes and related cloud technologies
  • Location
    Bangalore
  • Education
    Engineering
  • Work
    Cisco
  • Joined

More fromAshok Nagaraj

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp