kubeless icon indicating copy to clipboard operation
kubeless copied to clipboard

Serve function over tls directly

Open kferrone opened this issue 3 years ago • 1 comments

Is this a BUG REPORT or FEATURE REQUEST?: FEATURE REQUEST

What happened: Mutating and validating webhooks just complain the service for a function is not using https.

What you expected to happen: I would like to use serverless functions to handle k8s MutatingWebhook. Mutating and validating webhooks require the service itself to serve over SSL. The function resource should have an option to point to tls secret and have it installed into the runtimes server.

How to reproduce it (as minimally and precisely as possible):

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: test-hook
  annotations:
    cert-manager.io/inject-ca-from: default/test-hook-cert
webhooks:
- name: com.kubeless.mutatingwebhook
  sideEffects: None
  admissionReviewVersions:
  - v1
  - v1beta1
  matchPolicy: Equivalent
  failurePolicy: Fail
  objectSelector:
    matchLabels:
      test-label: "true"
  clientConfig:
    caBundle: ""
    service:
      name: myfx
      namespace: kubeless
      path: "/"
      port: 443
  rules:
  - scope: "*"
    operations:
    - CREATE
    - UPDATE
    apiGroups:
    - ""
    - networking.k8s.io
    apiVersions:
    - v1
    resources: 
    - services
    - ingress

kferrone avatar Jun 04 '21 17:06 kferrone

So I have a working example! It took me quite a while but I have successfully made a Mutating webhook with a kubeless function.

Heres all what I had to do:

  1. update the kubeless.js file by changing the following line:
const server = app.listen(funcPort);

to this code

const https = require('https');
const fs = require('fs')
const server = https.createServer({
    key: fs.readFileSync(process.env.SSL_KEY, 'utf-8'),
    cert: fs.readFileSync(process.env.SSL_CERT, 'utf-8')
}, app);
server.listen(funcPort);
  1. then Dockerfile
FROM kubeless/nodejs:14
ADD kubeless.js /kubeless_rt/
ENV SSL_KEY=/ssl/tls.key SSL_CERT=/ssl/tls.crt
  1. Add a new runtime in kubeless-config called nodejs-ssl14 using new image on dockerhub
  2. Make function, webhook, and cert
apiVersion: kubeless.io/v1beta1
kind: Function
metadata:
  name: mutate
  namespace: kubeless
spec:
  handler: handler.mutate
  runtime: nodejs-ssl14
  function: |
      module.exports = {
        mutate: function(event, context) {
          console.log(event.data);
          const patch = [{
            op: "add",
            path: "/metadata/annotations/kubeless-did-it",
            value: 'true'
          }];
          event.data.response = {
            uid: event.data.request.uid,
            allowed: true,
            patchType: "JSONPatch",
            patch: Buffer.from(JSON.stringify(patch)).toString("base64")
          };
          return event.data;
        }
      }
  deployment:
    spec:
      template:
        spec:
          nodeSelector:
            beta.kubernetes.io/arch: amd64
          containers:
          - name: mutate
            volumeMounts:
            - name: certs
              mountPath: /ssl
            livenessProbe:
              httpGet:
                path: /healthz
                port: 8080
                scheme: HTTPS
          volumes:
          - name: certs
            secret:
              secretName: mutate-cert
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
  name: mutate
  annotations:
    cert-manager.io/inject-ca-from: kubeless/mutate
webhooks:
- name: com.example.mutate
  sideEffects: None
  admissionReviewVersions:
  - v1
  - v1beta1
  matchPolicy: Equivalent
  failurePolicy: Fail
  objectSelector:
    matchLabels:
      mutate: "true"
  clientConfig:
    caBundle: ""
    service:
      name: mutate
      namespace: kubeless
      path: "/"
      port: 8080
  rules:
  - scope: "*"
    operations:
    - CREATE
    - UPDATE
    apiGroups:
    - ''
    - networking.k8s.io
    apiVersions:
    - v1
    resources: 
    - ingresses
    - services
  ---
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
  name: mutate
  namespace: kubeless
spec:
  dnsNames:
    - mutate
    - mutate.kubeless
    - mutate.kubeless.svc
    - mutate.kubeless.svc.cluster.local
  issuerRef:
    kind: ClusterIssuer
    name: local # selfsigned issuer
  secretName: mutate-cert

Still would be nice for kubeless to just have ssl like this baked right in to the default runtimes or even the Function CRD could handle it.

kferrone avatar Jun 05 '21 05:06 kferrone