Skip to content

Instantly share code, notes, and snippets.

@ajanikow
Last active August 21, 2019 17:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ajanikow/6944d84324dbfbb49086703514f2a35b to your computer and use it in GitHub Desktop.
Save ajanikow/6944d84324dbfbb49086703514f2a35b to your computer and use it in GitHub Desktop.
Simple Admission Webhook Application
// Copyright 2019
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"fmt"
"io/ioutil"
"net/http"
"strings"
admission "k8s.io/api/admission/v1beta1"
core "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/json"
)
func validation(w http.ResponseWriter, r *http.Request) {
if r.Body == nil {
return
}
defer r.Body.Close()
data, err := ioutil.ReadAll(r.Body)
if err != nil {
panic(err)
}
var admissionReview admission.AdmissionReview
err = json.Unmarshal(data, &admissionReview)
if err != nil {
panic(err)
}
if admissionReview.Request.Kind.Kind != "Pod" {
return
}
obj, err := admissionReview.Request.Object.MarshalJSON()
if err != nil {
panic(err)
}
var pod core.Pod
err = json.Unmarshal(obj, &pod)
if err != nil {
panic(err)
}
validationError := arePodImagesValid(&pod)
if validationError != nil {
admissionReview.Response = &admission.AdmissionResponse{
Allowed: false,
Result: &v1.Status{
Message: validationError.Error(),
},
}
} else {
admissionReview.Response = &admission.AdmissionResponse{
Allowed: true,
}
}
admissionReview.Response.UID = admissionReview.Request.UID
response, err := json.Marshal(admissionReview)
if err != nil {
panic(err)
}
_, err = w.Write(response)
if err != nil {
panic(err)
}
}
func arePodImagesValid(pod *core.Pod) error {
for _, container := range pod.Spec.InitContainers {
if len(strings.Split(container.Image, ":")) != 2 || strings.Split(container.Image, ":")[1] == "latest" {
return fmt.Errorf("initContainer %s has invalid image %s", container.Name, container.Image)
}
}
for _, container := range pod.Spec.Containers {
if len(strings.Split(container.Image, ":")) != 2 || strings.Split(container.Image, ":")[1] == "latest" {
return fmt.Errorf("container %s has invalid image %s", container.Name, container.Image)
}
}
return nil
}
func main() {
http.HandleFunc("/validation", validation)
if err := http.ListenAndServeTLS(":443", "./tls.crt", "./tls.key", nil); err != nil {
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment