Skip to content

Commit

Permalink
Generated by kubebuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
zoetrope committed Mar 19, 2021
1 parent 84f1de8 commit 3ecea4e
Show file tree
Hide file tree
Showing 34 changed files with 1,462 additions and 35 deletions.
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file
# Ignore all files which are not go type
!**/*.go
!**/*.mod
!**/*.sum
21 changes: 4 additions & 17 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
# Test binary, build with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

# Editors
*~
.*.swp
.#*
\#*#
/bin
/testbin/*
/vendor
/.vscode

# ignore go.sum
/go.sum
/.idea
27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Build the manager binary
FROM golang:1.15 as builder

WORKDIR /workspace
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# cache deps before building and copying source so that we don't need to re-download as much
# and so that source changes don't invalidate our downloaded layer
RUN go mod download

# Copy the go source
COPY main.go main.go
COPY api/ api/
COPY controllers/ controllers/

# Build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go

# Use distroless as minimal base image to package the manager binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
FROM gcr.io/distroless/static:nonroot
WORKDIR /
COPY --from=builder /workspace/manager .
USER 65532:65532

ENTRYPOINT ["/manager"]
111 changes: 93 additions & 18 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,32 +1,107 @@
CONTROLLER_RUNTIME_VERSION := $(shell awk '/sigs\.k8s\.io\/controller-runtime/ {print substr($$2, 2)}' go.mod)
CONTROLLER_TOOLS_VERSION = 0.5.0
KUSTOMIZE_VERSION = 3.8.7

# Set the shell used to bash for better error handling.
SHELL = /bin/bash
.SHELLFLAGS = -e -o pipefail -c

# For Go
GO111MODULE = on
export GO111MODULE
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif

.PHONY: all
all: test
all: build

.PHONY: test
test: test-tools
##@ General

# The help target prints out all targets with their descriptions organized
# beneath their categories. The categories are represented by '##@' and the
# target descriptions by '##'. The awk commands is responsible for reading the
# entire set of makefiles included in this invocation, looking for lines of the
# file as xyz: ## something, and then pretty-format the target and help. Then,
# if there's a line with ##@ something, that gets pretty-printed as a category.
# More info on the usage of ANSI control characters for terminal formatting:
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
# More info on the awk command:
# http://linuxcommand.org/lc3_adv_awk.php

help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

##@ Development

.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=pod-security-admission webhook paths="./..."

.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."

.PHONY: check-generate
check-generate:
$(MAKE) manifests
$(MAKE) generate
git diff --exit-code --name-only

.PHONY: simple-test
simple-test: staticcheck nilerr
test -z "$$(gofmt -s -l . | tee /dev/stderr)"
staticcheck ./...
test -z "$$(nilerr ./... 2>&1 | tee /dev/stderr)"
go install ./...
go test -race -v ./...
$(STATICCHECK) ./...
test -z "$$($(NILERR) $$(go list ./...) 2>&1 | tee /dev/stderr)"
go vet ./...

.PHONY: test-tools
test-tools: staticcheck nilerr
ENVTEST_ASSETS_DIR=$(shell pwd)/testbin
test: manifests generate ## Run tests.
mkdir -p ${ENVTEST_ASSETS_DIR}
test -f ${ENVTEST_ASSETS_DIR}/setup-envtest.sh || curl -sSLo ${ENVTEST_ASSETS_DIR}/setup-envtest.sh https://raw.githubusercontent.com/kubernetes-sigs/controller-runtime/v0.7.0/hack/setup-envtest.sh
source ${ENVTEST_ASSETS_DIR}/setup-envtest.sh; fetch_envtest_tools $(ENVTEST_ASSETS_DIR); setup_envtest_env $(ENVTEST_ASSETS_DIR); go test ./... -coverprofile cover.out

##@ Build

.PHONY: build
build: ## Build binary.
CGO_ENABLED=0 go build -o bin/pod-security-admission -ldflags="-w -s" main.go

CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
.PHONY: controller-gen
controller-gen: ## Download controller-gen locally if necessary.
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v$(CONTROLLER_TOOLS_VERSION))

KUSTOMIZE = $(shell pwd)/bin/kustomize
.PHONY: kustomize
kustomize: ## Download kustomize locally if necessary.
$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v$(KUSTOMIZE_VERSION))

STATICCHECK = $(shell pwd)/bin/staticcheck
.PHONY: staticcheck
staticcheck:
if ! which staticcheck >/dev/null; then \
cd /tmp; env GOFLAGS= GO111MODULE=on go get honnef.co/go/tools/cmd/staticcheck; \
fi
$(call go-install-tool,$(STATICCHECK),honnef.co/go/tools/cmd/staticcheck@latest)

NILERR = $(shell pwd)/bin/nilerr
.PHONY: nilerr
nilerr:
if ! which nilerr >/dev/null; then \
cd /tmp; env GOFLAGS= GO111MODULE=on go get github.com/gostaticanalysis/nilerr/cmd/nilerr; \
fi
$(call go-install-tool,$(NILERR),github.com/gostaticanalysis/nilerr/cmd/nilerr@latest)

.PHONY: clean
clean:
rm -rf bin testbin
rm -f config/crd/bases/*

# go-install-tool will 'go install' any package $2 and install it to $1.
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
define go-install-tool
@[ -f $(1) ] || { \
set -e ;\
TMP_DIR=$$(mktemp -d) ;\
cd $$TMP_DIR ;\
go mod init tmp ;\
echo "Downloading $(2)" ;\
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
rm -rf $$TMP_DIR ;\
}
endef
5 changes: 5 additions & 0 deletions PROJECT
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
domain: cybozu.com
layout: go.kubebuilder.io/v3
projectName: tmp
repo: github.com/cybozu-go/pod-security-admission
version: "3"
83 changes: 83 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package cmd

import (
"flag"
"fmt"
"github.com/cybozu-go/pod-security-admission/hooks"
"io/ioutil"
"net"
"os"
"strconv"

"github.com/spf13/cobra"
"k8s.io/klog"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/yaml"
)

var config struct {
metricsAddr string
probeAddr string
webhookAddr string
certDir string
configPath string
zapOpts zap.Options
}

var rootCmd = &cobra.Command{
Use: "pod-security-admission",
Short: "admission webhooks to ensure pod security standards",
Long: `Admission webhooks to ensure pod security standards.`,
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true
h, p, err := net.SplitHostPort(config.webhookAddr)
if err != nil {
return fmt.Errorf("invalid webhook address: %s, %v", config.webhookAddr, err)
}
numPort, err := strconv.Atoi(p)
if err != nil {
return fmt.Errorf("invalid webhook address: %s, %v", config.webhookAddr, err)
}
conf, err := parseConfig(config.configPath)
if err != nil {
return err
}
return run(h, numPort, conf)
},
}

func parseConfig(configPath string) (*hooks.Config, error) {
data, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, err
}
var conf hooks.Config
err = yaml.Unmarshal(data, &conf)
if err != nil {
return nil, err
}
return &conf, nil
}

// Execute executes the command.
func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func init() {
fs := rootCmd.Flags()
fs.StringVar(&config.metricsAddr, "metrics-addr", ":8080", "Listen address for metrics")
fs.StringVar(&config.probeAddr, "health-probe-addr", ":8081", "Listen address for health probes")
fs.StringVar(&config.webhookAddr, "webhook-addr", ":9443", "Listen address for the webhook endpoint")
fs.StringVar(&config.certDir, "cert-dir", "", "certificate directory")
fs.StringVar(&config.configPath, "config-path", "/etc/pod-security-admission/config.yaml", "Configuration for webhooks")

goflags := flag.NewFlagSet("klog", flag.ExitOnError)
klog.InitFlags(goflags)
config.zapOpts.BindFlags(goflags)

fs.AddGoFlagSet(goflags)
}
66 changes: 66 additions & 0 deletions cmd/run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package cmd

import (
"github.com/cybozu-go/pod-security-admission/hooks"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

var (
scheme = runtime.NewScheme()
setupLog = ctrl.Log.WithName("setup")
)

func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))

// +kubebuilder:scaffold:scheme
}

func run(addr string, port int, conf *hooks.Config) error {
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&config.zapOpts)))

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: config.metricsAddr,
HealthProbeBindAddress: config.probeAddr,
LeaderElection: false,
Host: addr,
Port: port,
CertDir: config.certDir,
})
if err != nil {
setupLog.Error(err, "unable to start manager")
return err
}

// register webhook handlers
// admission.NewDecoder never returns non-nil error
dec, _ := admission.NewDecoder(scheme)
wh := mgr.GetWebhookServer()
wh.Register("/mutate-pod", hooks.NewPodMutator(mgr.GetClient(), dec))
wh.Register("/validate-pod", hooks.NewPodValidator(mgr.GetClient(), dec))

// +kubebuilder:scaffold:builder

if err := mgr.AddHealthzCheck("health", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up health check")
return err
}
if err := mgr.AddReadyzCheck("check", healthz.Ping); err != nil {
setupLog.Error(err, "unable to set up ready check")
return err
}

setupLog.Info("starting manager")
if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
return err
}
return nil
}
25 changes: 25 additions & 0 deletions config/certmanager/certificate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# The following manifests contain a self-signed issuer CR and a certificate CR.
# More document can be found at https://docs.cert-manager.io
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: selfsigned-issuer
namespace: system
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
namespace: system
spec:
# $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
dnsNames:
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
issuerRef:
kind: Issuer
name: selfsigned-issuer
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
5 changes: 5 additions & 0 deletions config/certmanager/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resources:
- certificate.yaml

configurations:
- kustomizeconfig.yaml
16 changes: 16 additions & 0 deletions config/certmanager/kustomizeconfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This configuration is for teaching kustomize how to update name ref and var substitution
nameReference:
- kind: Issuer
group: cert-manager.io
fieldSpecs:
- kind: Certificate
group: cert-manager.io
path: spec/issuerRef/name

varReference:
- kind: Certificate
group: cert-manager.io
path: spec/commonName
- kind: Certificate
group: cert-manager.io
path: spec/dnsNames
Loading

0 comments on commit 3ecea4e

Please sign in to comment.