...

/

Implementing a Webhook for Token Authentication

Implementing a Webhook for Token Authentication

Learn how to implement a webhook token authentication service.

Implement a webhook token authentication service

A webhook token authentication service is a web server because the kube-apiserver invokes it through HTTPS POST requests.

Now, let’s implement such a service step by step.

Step 1: Write a simple HTTP server

Let’s write a simple HTTP server that responds with the mock authenticated user mock, when requested for the /authenticate resource over port 443.

package main

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net/http"

	authenticationapi "k8s.io/api/authentication/v1beta1"
)

func authN(tr *authenticationapi.TokenReview) {
	// Now we create a mock as an example
	// Please replace this with your logic
	tr.Status.Authenticated = true
	tr.Status.User = authenticationapi.UserInfo{
		Username: "mock",
		UID:      "mock",
		Groups:   []string{"group-mock"},
		Extra:    nil,
	}
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	log.Printf("Receiving %s", r.Method)

	if r.Method != "POST" {
		http.Error(w, "Only Accept POST requests", http.StatusMethodNotAllowed)
		return
	}

	// Read body of POST request
	payload, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}
	log.Printf("Receiving Token: %s\n", string(payload))

	// Unmarshal JSON from POST request to TokenReview object
	tr := &authenticationapi.TokenReview{}
	err = json.Unmarshal(payload, tr)
	if err != nil {
		http.Error(w, err.Error(), http.StatusBadRequest)
		return
	}

	authN(tr)

	// Marshal the TokenReview to JSON and send it back
	result, err := json.Marshal(*tr)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.Write(result)
	w.Header().Set("Content-Type", "application/json")
}

func main() {
	// Set up a /authenticate resource handler
	http.HandleFunc("/authenticate", helloHandler)

	// Listen to port 443 and wait
	log.Println("Listening on port 443 for requests...")
	log.Fatal(http.ListenAndServe(":443", nil))
}
The webhook HTTP server

In a real-world scenario, we only need to replace the mock codes in the function authN with our actual implementations to query our user-management system. This function should set a valid UserInfo if the provided token is legitimate. Moreover, Status.Authenticated should be set as well—true for legitimate users and false for invalid users. For the error message, it can be set to the field Status.Error.

The rest of the code is a simple HTTP ...

Access this course and 1400+ top-rated courses and projects.