-
Notifications
You must be signed in to change notification settings - Fork 743
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
Changes from all commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
1422432
feat: Validation webhook for event bus
whynowy 4e2c0d4
feat: webhook
whynowy 7933dd3
manifests
whynowy afcdba4
test case and manifests change
whynowy e08c72c
Merge remote-tracking branch 'upstream/master' into validation
whynowy da8ce6f
more validation
whynowy 885623d
Merge branch 'master' into validation
whynowy 7a0a72e
interface refac
whynowy 4612e32
Merge remote-tracking branch 'upstream/master' into validation
whynowy 02599fa
fix manifests
whynowy b32a203
fix test cases
whynowy 89f9f67
doc update
whynowy 80f2c0a
minor
whynowy 74a2974
minor
whynowy 4b3b323
more validation
whynowy 07a9f8d
Merge branch 'master' into validation
whynowy f542b66
more test cases
whynowy 1048ff8
doc revise
whynowy f94a238
minor
whynowy 188eb8d
fix test case
whynowy 86592ca
minor
whynowy 867ef91
minor
whynowy 35bd4cd
port
whynowy 1baee50
fix typo and refine rbac
whynowy f282831
Merge branch 'master' into validation
whynowy bb5b1a2
Stop doing cross resources validating
whynowy c9125fd
remove unused delete validation
whynowy 4f88fca
Merge branch 'master' into validation
whynowy 3cb9cc4
Merge branch 'master' into validation
whynowy 7e542d4
Merge remote-tracking branch 'upstream/master' into validation
whynowy 1013737
Merge branch 'master' into validation
whynowy 85f388b
update test case
whynowy 31057d5
lint
whynowy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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") | ||
} | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package eventbus | ||
|
||
import ( | ||
"github.com/pkg/errors" | ||
|
||
"github.com/argoproj/argo-events/pkg/apis/eventbus/v1alpha1" | ||
) | ||
|
||
// ValidateEventBus accepts an EventBus and performs validation against it | ||
func ValidateEventBus(eb *v1alpha1.EventBus) error { | ||
if eb.Spec.NATS != nil { | ||
if eb.Spec.NATS.Native != nil && eb.Spec.NATS.Exotic != nil { | ||
return errors.New("\"spec.nats.native\" and \"spec.nats.exotic\" can not be defined together") | ||
} | ||
if eb.Spec.NATS.Exotic != nil { | ||
e := eb.Spec.NATS.Exotic | ||
if e.ClusterID == nil { | ||
return errors.New("\"spec.nats.exotic.clusterID\" is missing") | ||
} | ||
if e.URL == "" { | ||
return errors.New("\"spec.nats.exotic.url\" is missing") | ||
} | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package eventbus | ||
|
||
import ( | ||
"strings" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
|
||
"github.com/argoproj/argo-events/common" | ||
"github.com/argoproj/argo-events/pkg/apis/eventbus/v1alpha1" | ||
) | ||
|
||
var ( | ||
testEventBus = &v1alpha1.EventBus{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Namespace: "test-ns", | ||
Name: common.DefaultEventBusName, | ||
}, | ||
Spec: v1alpha1.EventBusSpec{ | ||
NATS: &v1alpha1.NATSBus{ | ||
Native: &v1alpha1.NativeStrategy{ | ||
Auth: &v1alpha1.AuthStrategyToken, | ||
}, | ||
}, | ||
}, | ||
} | ||
) | ||
|
||
func TestValidate(t *testing.T) { | ||
t.Run("test good eventbus", func(t *testing.T) { | ||
err := ValidateEventBus(testEventBus) | ||
assert.NoError(t, err) | ||
}) | ||
|
||
t.Run("test native exotic conflicting eventbus", func(t *testing.T) { | ||
eb := testEventBus.DeepCopy() | ||
eb.Spec.NATS.Exotic = &v1alpha1.NATSConfig{} | ||
err := ValidateEventBus(eb) | ||
assert.Error(t, err) | ||
assert.True(t, strings.Contains(err.Error(), "can not be defined together")) | ||
}) | ||
|
||
t.Run("test exotic eventbus no clusterID", func(t *testing.T) { | ||
eb := testEventBus.DeepCopy() | ||
eb.Spec.NATS.Native = nil | ||
eb.Spec.NATS.Exotic = &v1alpha1.NATSConfig{} | ||
err := ValidateEventBus(eb) | ||
assert.Error(t, err) | ||
assert.True(t, strings.Contains(err.Error(), "\"spec.nats.exotic.clusterID\" is missing")) | ||
}) | ||
|
||
t.Run("test exotic eventbus empty URL", func(t *testing.T) { | ||
eb := testEventBus.DeepCopy() | ||
eb.Spec.NATS.Native = nil | ||
cID := "test-cluster-id" | ||
eb.Spec.NATS.Exotic = &v1alpha1.NATSConfig{ | ||
ClusterID: &cID, | ||
} | ||
err := ValidateEventBus(eb) | ||
assert.Error(t, err) | ||
assert.True(t, strings.Contains(err.Error(), "\"spec.nats.exotic.url\" is missing")) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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")