Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Introducing a Validating Admission Controller #1021

Merged
merged 33 commits into from
Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1422432
feat: Validation webhook for event bus
whynowy Dec 11, 2020
4e2c0d4
feat: webhook
whynowy Dec 18, 2020
7933dd3
manifests
whynowy Jan 15, 2021
afcdba4
test case and manifests change
whynowy Jan 19, 2021
e08c72c
Merge remote-tracking branch 'upstream/master' into validation
whynowy Jan 19, 2021
da8ce6f
more validation
whynowy Jan 20, 2021
885623d
Merge branch 'master' into validation
whynowy Jan 22, 2021
7a0a72e
interface refac
whynowy Jan 23, 2021
4612e32
Merge remote-tracking branch 'upstream/master' into validation
whynowy Jan 25, 2021
02599fa
fix manifests
whynowy Jan 25, 2021
b32a203
fix test cases
whynowy Jan 25, 2021
89f9f67
doc update
whynowy Jan 25, 2021
80f2c0a
minor
whynowy Jan 25, 2021
74a2974
minor
whynowy Jan 25, 2021
4b3b323
more validation
whynowy Jan 25, 2021
07a9f8d
Merge branch 'master' into validation
whynowy Jan 25, 2021
f542b66
more test cases
whynowy Jan 25, 2021
1048ff8
doc revise
whynowy Jan 26, 2021
f94a238
minor
whynowy Jan 26, 2021
188eb8d
fix test case
whynowy Jan 26, 2021
86592ca
minor
whynowy Jan 26, 2021
867ef91
minor
whynowy Jan 26, 2021
35bd4cd
port
whynowy Jan 26, 2021
1baee50
fix typo and refine rbac
whynowy Jan 26, 2021
f282831
Merge branch 'master' into validation
whynowy Jan 27, 2021
bb5b1a2
Stop doing cross resources validating
whynowy Jan 27, 2021
c9125fd
remove unused delete validation
whynowy Jan 28, 2021
4f88fca
Merge branch 'master' into validation
whynowy Jan 28, 2021
3cb9cc4
Merge branch 'master' into validation
whynowy Jan 28, 2021
7e542d4
Merge remote-tracking branch 'upstream/master' into validation
whynowy Jan 28, 2021
1013737
Merge branch 'master' into validation
whynowy Jan 29, 2021
85f388b
update test case
whynowy Jan 29, 2021
31057d5
lint
whynowy Jan 29, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,13 @@ RUN argo version || true
COPY dist/sensor /bin/sensor

ENTRYPOINT [ "/bin/sensor" ]

####################################################################################################
# events-webhook
####################################################################################################
FROM scratch as events-webhook
COPY --from=base /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=base /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY dist/events-webhook /bin/events-webhook
ENTRYPOINT [ "/bin/events-webhook" ]

28 changes: 26 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ endif

# Build the project images
.DELETE_ON_ERROR:
all: sensor sensor-controller eventbus-controller eventsource-controller eventsource
all: sensor sensor-controller eventbus-controller eventsource-controller eventsource events-webhook

all-images: sensor-image sensor-controller-image eventbus-controller-image eventsource-controller-image eventsource-image
all-images: sensor-image sensor-controller-image eventbus-controller-image eventsource-controller-image eventsource-image events-webhook-image

all-controller-images: sensor-controller-image eventbus-controller-image eventsource-controller-image

Expand Down Expand Up @@ -145,6 +145,26 @@ eventbus-controller-image: dist/eventbus-controller-linux-amd64
DOCKER_BUILDKIT=1 docker build -t $(IMAGE_PREFIX)eventbus-controller:$(IMAGE_TAG) --target eventbus-controller -f $(DOCKERFILE) .
@if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)eventbus-controller:$(IMAGE_TAG) ; fi

# Webhook
.PHONY: events-webhook
events-webhook: dist/events-webhook-linux-amd64

dist/events-webhook: GOARGS = GOOS= GOARCH=
dist/events-webhook-linux-amd64: GOARGS = GOOS=linux GOARCH=amd64
dist/events-webhook-linux-arm64: GOARGS = GOOS=linux GOARCH=arm64
dist/events-webhook-linux-ppc64le: GOARGS = GOOS=linux GOARCH=ppc64le
dist/events-webhook-linux-s390x: GOARGS = GOOS=linux GOARCH=s390x

dist/events-webhook:
go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/events-webhook ./webhook/cmd/main.go

dist/events-webhook-%:
CGO_ENABLED=0 $(GOARGS) go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/events-webhook ./webhook/cmd/main.go

events-webhook-image: dist/events-webhook-linux-amd64
DOCKER_BUILDKIT=1 docker build -t $(IMAGE_PREFIX)events-webhook:$(IMAGE_TAG) --target events-webhook -f $(DOCKERFILE) .
@if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)events-webhook:$(IMAGE_TAG) ; fi

test:
go test $(shell go list ./... | grep -v /vendor/ | grep -v /test/e2e/) -race -short -v

Expand All @@ -162,6 +182,7 @@ crds:
.PHONY: manifests
manifests: crds
kustomize build manifests/cluster-install > manifests/install.yaml
kustomize build manifests/cluster-install-no-extention > manifests/install-no-extension.yaml
kustomize build manifests/namespace-install > manifests/namespace-install.yaml

.PHONY: swagger
Expand Down Expand Up @@ -219,3 +240,6 @@ quay-release: eventbus-controller-image sensor-controller-image sensor-image eve

docker tag $(IMAGE_PREFIX)eventsource:$(IMAGE_TAG) quay.io/$(IMAGE_PREFIX)eventsource:$(IMAGE_TAG)
docker push quay.io/$(IMAGE_PREFIX)eventsource:$(IMAGE_TAG)

docker tag $(IMAGE_PREFIX)events-webhook:$(IMAGE_TAG) quay.io/$(IMAGE_PREFIX)events-webhook:$(IMAGE_TAG)
docker push quay.io/$(IMAGE_PREFIX)events-webhook:$(IMAGE_TAG)
117 changes: 117 additions & 0 deletions common/tls/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package tls

import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"time"

"github.com/pkg/errors"
)

func certTemplate(org string, hosts []string, notAfter time.Time) (*x509.Certificate, error) {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
if err != nil {
return nil, errors.Wrap(err, "failed to generate serial number")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: I much prefer fmt.Errorf("%w")

}
return &x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{org},
},
SignatureAlgorithm: x509.SHA256WithRSA,
NotBefore: time.Now(),
NotAfter: notAfter,
BasicConstraintsValid: true,
DNSNames: hosts,
}, nil
}

func createCACertTemplate(org string, hosts []string, notAfter time.Time) (*x509.Certificate, error) {
rootCert, err := certTemplate(org, hosts, notAfter)
if err != nil {
return nil, err
}
rootCert.IsCA = true
rootCert.KeyUsage = x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature
rootCert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
return rootCert, nil
}

func createServerCertTemplate(org string, hosts []string, notAfter time.Time) (*x509.Certificate, error) {
serverCert, err := certTemplate(org, hosts, notAfter)
if err != nil {
return nil, err
}
serverCert.KeyUsage = x509.KeyUsageDigitalSignature
serverCert.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}
return serverCert, err
}

// Sign the cert
func createCert(template, parent *x509.Certificate, pub, parentPriv interface{}) (
cert *x509.Certificate, certPEM []byte, err error) {
certDER, err := x509.CreateCertificate(rand.Reader, template, parent, pub, parentPriv)
if err != nil {
return
}
cert, err = x509.ParseCertificate(certDER)
if err != nil {
return
}
b := pem.Block{Type: "CERTIFICATE", Bytes: certDER}
certPEM = pem.EncodeToMemory(&b)
return
}

func createCA(org string, hosts []string, notAfter time.Time) (*rsa.PrivateKey, *x509.Certificate, []byte, error) {
rootKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "failed to generate random key")
}

rootCertTmpl, err := createCACertTemplate(org, hosts, notAfter)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "failed to generate CA cert")
}

rootCert, rootCertPEM, err := createCert(rootCertTmpl, rootCertTmpl, &rootKey.PublicKey, rootKey)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "failed to sign CA cert")
}
return rootKey, rootCert, rootCertPEM, nil
}

// CreateCerts creates and returns a CA certificate and certificate and
// key for the server
func CreateCerts(org string, hosts []string, notAfter time.Time) (serverKey, serverCert, caCert []byte, err error) {
// Create a CA certificate and private key
caKey, caCertificate, caCertificatePEM, err := createCA(org, hosts, notAfter)
if err != nil {
return nil, nil, nil, err
}

// Create the private key
servKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "failed to generate random key")
}
servCertTemplate, err := createServerCertTemplate(org, hosts, notAfter)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "failed to create server cert template")
}

// create a certificate wrapping the public key, sign it with the CA private key
_, servCertPEM, err := createCert(servCertTemplate, caCertificate, &servKey.PublicKey, caKey)
if err != nil {
return nil, nil, nil, errors.Wrap(err, "failed to sign server cert")
}
servKeyPEM := pem.EncodeToMemory(&pem.Block{
Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(servKey),
})
return servKeyPEM, servCertPEM, caCertificatePEM, nil
}
48 changes: 48 additions & 0 deletions common/tls/tls_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package tls

import (
"crypto/x509"
"encoding/pem"
"testing"
"time"

"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)

func TestCreateCerts(t *testing.T) {
t.Run("test create certs", func(t *testing.T) {
sKey, serverCertPEM, caCertBytes, err := CreateCerts("test-org", []string{"test-host"}, time.Now().AddDate(1, 0, 0))
assert.NoError(t, err)
p, _ := pem.Decode(sKey)
assert.Equal(t, "RSA PRIVATE KEY", p.Type)
key, err := x509.ParsePKCS1PrivateKey(p.Bytes)
assert.NoError(t, err)
err = key.Validate()
assert.NoError(t, err)
sCert, err := validCertificate(serverCertPEM, t)
assert.NoError(t, err)
caParsedCert, err := validCertificate(caCertBytes, t)
assert.NoError(t, err)
assert.Equal(t, "test-host", caParsedCert.DNSNames[0])
err = sCert.CheckSignatureFrom(caParsedCert)
assert.NoError(t, err)
})
}

func validCertificate(cert []byte, t *testing.T) (*x509.Certificate, error) {
t.Helper()
const certificate = "CERTIFICATE"
caCert, _ := pem.Decode(cert)
if caCert.Type != certificate {
return nil, errors.Errorf("CERT type mismatch, got %s, want: %s", caCert.Type, certificate)
}
parsedCert, err := x509.ParseCertificate(caCert.Bytes)
if err != nil {
return nil, errors.Wrap(err, "failed to parse cert")
}
if parsedCert.SignatureAlgorithm != x509.SHA256WithRSA {
return nil, errors.Errorf("signature not match. Got: %s, want: %s", parsedCert.SignatureAlgorithm, x509.SHA256WithRSA)
}
return parsedCert, nil
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ require (
github.com/fatih/color v1.9.0 // indirect
github.com/fsnotify/fsnotify v1.4.9
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/go-openapi/inflect v0.19.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what licence?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MIT.

github.com/go-openapi/spec v0.19.8
github.com/go-redis/redis v6.15.8+incompatible
github.com/go-resty/resty/v2 v2.3.0
Expand Down
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd h1:aY7OQNf2XqY/JQ6qREWamhI/81os/agb2BAGpcx5yWI=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
Expand Down
9 changes: 9 additions & 0 deletions manifests/cluster-install-no-extention/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../base
- rbac

namespace: argo-events

4 changes: 2 additions & 2 deletions manifests/cluster-install/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../base
- rbac
- ../cluster-install-no-extention
- ../extentions

namespace: argo-events

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: argo-events-webhook-sa
24 changes: 24 additions & 0 deletions manifests/extentions/events-webhook/events-webhook-deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: events-webhook
spec:
replicas: 1
selector:
matchLabels:
app: events-webhook
template:
metadata:
labels:
app: events-webhook
spec:
containers:
- name: webhook
image: argoproj/events-webhook:latest
imagePullPolicy: Always
env:
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
serviceAccountName: argo-events-webhook-sa
10 changes: 10 additions & 0 deletions manifests/extentions/events-webhook/events-webhook-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: events-webhook
spec:
ports:
- port: 443
targetPort: 443
selector:
app: events-webhook
8 changes: 8 additions & 0 deletions manifests/extentions/events-webhook/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- argo-events-webhook-sa.yaml
- rbac
- events-webhook-deployment.yaml
- events-webhook-service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argo-events-webhook-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argo-events-webhook
subjects:
- kind: ServiceAccount
name: argo-events-webhook-sa
namespace: argo-events
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argo-events-webhook
rules:
- apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- get
- list
- create
- update
- delete
- patch
- watch
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- apiGroups:
- admissionregistration.k8s.io
resources:
- validatingwebhookconfigurations
verbs:
- get
- list
- create
- update
- delete
- patch
- watch
6 changes: 6 additions & 0 deletions manifests/extentions/events-webhook/rbac/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- argo-events-webhook-cluster-role.yaml
- argo-events-webhook-cluster-role-binding.yaml
14 changes: 14 additions & 0 deletions manifests/extentions/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#
# Update the versions in this file.
#

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- events-webhook

images:
- name: argoproj/events-webhook
newTag: latest

Loading