Skip to content

Commit

Permalink
Fix yaml for httpRoute and backendTLSPolicy. Fix CA generation.
Browse files Browse the repository at this point in the history
Fix certificate unit test.
  • Loading branch information
candita committed Nov 4, 2024
1 parent cade4a1 commit e58e8bc
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 110 deletions.
63 changes: 0 additions & 63 deletions conformance/base/manifests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -730,66 +730,3 @@ data:
foo.bar.com:53 {
whoami
}
---
apiVersion: v1
kind: Service
metadata:
name: backendtlspolicy-test
namespace: gateway-conformance-infra
spec:
selector:
app: backendtlspolicy-test
ports:
- protocol: TCP
port: 443
targetPort: 8443
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: backendtlspolicy-test
namespace: gateway-conformance-infra
labels:
app: backendtlspolicy-test
spec:
replicas: 1
selector:
matchLabels:
app: backendtlspolicy-test
template:
metadata:
labels:
app: backendtlspolicy-test
spec:
containers:
- name: backendtlspolicy-test
image: gcr.io/k8s-staging-gateway-api/echo-basic:v20241007-v1.2.0-6-g9f820af9
volumeMounts:
- name: secret-volume
mountPath: /etc/secret-volume
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: CA_CERT
value: /etc/secret-volume/crt
- name: CA_CERT_KEY
value: /etc/secret-volume/key
resources:
requests:
cpu: 10m
volumes:
- name: secret-volume
secret:
# This secret is generated dynamically by the test suite.
secretName: backend-tls-checks-certificate
items:
- key: tls.crt
path: crt
- key: tls.key
path: key
84 changes: 82 additions & 2 deletions conformance/tests/backendtlspolicy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ spec:
validation:
caCertificateRefs:
- group: ""
kind: Secret
kind: ConfigMap
# This secret is generated dynamically by the test suite.
name: "backend-tls-checks-certificate"
hostname: "abc.example.com"
Expand All @@ -52,7 +52,87 @@ spec:
hostnames:
- abc.example.com
rules:
- matches:
- backendRefs:
- group: ""
kind: Service
name: backendtlspolicy-test
port: 443
matches:
- path:
type: Exact
value: /backendTLS
---
apiVersion: v1
kind: Service
metadata:
name: backendtlspolicy-test
namespace: gateway-conformance-infra
spec:
selector:
app: backendtlspolicy-test
ports:
- protocol: TCP
port: 443
targetPort: 8443
---
# Deployment must not be applied until after the secret is generated.
apiVersion: apps/v1
kind: Deployment
metadata:
name: backendtlspolicy-test
namespace: gateway-conformance-infra
labels:
app: backendtlspolicy-test
spec:
replicas: 1
selector:
matchLabels:
app: backendtlspolicy-test
template:
metadata:
labels:
app: backendtlspolicy-test
spec:
containers:
- name: backendtlspolicy-test
image: echo-basic:2.2
volumeMounts:
- name: ca-volume
mountPath: /etc/ca-volume
- name: secret-volume
mountPath: /etc/secret-volume
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: CA_CERT
value: /etc/ca-volume/crt
- name: TLS_SERVER_CERT
value: /etc/secret-volume/crt
- name: TLS_SERVER_PRIVKEY
value: /etc/secret-volume/key
resources:
requests:
cpu: 10m
volumes:
- name: ca-volume
configMap:
# This configMap is generated dynamically by the test suite.
name: backend-tls-checks-certificate
items:
- key: ca.crt
path: crt
- name: secret-volume
secret:
# This secret is generated dynamically by the test suite.
secretName: tls-checks-certificate
items:
- key: tls.crt
path: crt
- key: tls.key
path: key
62 changes: 31 additions & 31 deletions conformance/utils/kubernetes/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,34 +120,41 @@ func generateRSACert(hosts []string, keyOut, certOut io.Writer) error {
return nil
}

// MustCreateCASignedCertSecret will create a secret using a CA Certificate, and public and private key for that certificate.
func MustCreateCASignedCertSecret(t *testing.T, namespace, secretName string, hosts []string) *corev1.Secret {
// MustCreateCASignedCertConfigMap will create a ConfigMap containing a CA Certificate, given a TLS Secret
// for that CA certificate.
func MustCreateCASignedCertConfigMap(t *testing.T, namespace, configMapName string, hosts []string) *corev1.ConfigMap {
require.NotEmpty(t, hosts, "require a non-empty hosts for Subject Alternate Name values")

var serverKey, serverCert bytes.Buffer

require.NoError(t, generateCACert(hosts, &serverKey, &serverCert), "failed to generate CA certificate")
caBytes, err := generateCACert(hosts)
if err != nil {
t.Errorf("failed to generate CA certificate: %v", err)
return nil
}

data := map[string][]byte{
corev1.TLSCertKey: serverCert.Bytes(),
corev1.TLSPrivateKeyKey: serverKey.Bytes(),
var certData bytes.Buffer
if err := pem.Encode(&certData, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}); err != nil {
t.Errorf("failed creating cert: %v", err)
return nil
}

newSecret := &corev1.Secret{
// Store the certificate in a ConfigMap.
caConfigMap := &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Name: secretName,
Name: configMapName,
},
Data: map[string]string{
"ca.crt": certData.String(),
},
Type: corev1.SecretTypeTLS,
Data: data,
}

return newSecret
return caConfigMap
}

// generateCACert generates a CA Certificate signed certificate valid for a year.
func generateCACert(hosts []string, keyOut, certOut io.Writer) error {
// Create the CA certificate.
// generateCACert generates a ConfigMap containing a CA Certificate signed certificate valid for a year.
func generateCACert(hosts []string) ([]byte, error) {
var caBytes []byte

// Create the CA certificate template.
ca := &x509.Certificate{
SerialNumber: big.NewInt(2024),
Subject: pkix.Name{
Expand All @@ -162,7 +169,7 @@ func generateCACert(hosts []string, keyOut, certOut io.Writer) error {
NotAfter: time.Now().AddDate(1, 0, 0),
IsCA: true, // Indicates this is a CA Certificate.
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment,
BasicConstraintsValid: true,
}

Expand All @@ -175,26 +182,19 @@ func generateCACert(hosts []string, keyOut, certOut io.Writer) error {
}
}

// Generate the private key.
// Generate the private key to sign certificates.
caPrivKey, err := rsa.GenerateKey(rand.Reader, rsaBits)
if err != nil {
return err
return caBytes, fmt.Errorf("error generating key for CA: %v", err)
}

// Generate the certificate using the CA certificate.
caBytes, err := x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
// Create the self-signed certificate using the CA certificate.
caBytes, err = x509.CreateCertificate(rand.Reader, ca, ca, &caPrivKey.PublicKey, caPrivKey)
if err != nil {
return err
}

if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}); err != nil {
return fmt.Errorf("failed creating cert: %w", err)
return caBytes, fmt.Errorf("error creating CA: %v", err)
}

if err := pem.Encode(keyOut, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caPrivKey)}); err != nil {
return fmt.Errorf("failed creating key: %w", err)
}
return nil
return caBytes, nil
}

// validateHost ensures that the host name length is no more than 253 characters.
Expand Down
18 changes: 7 additions & 11 deletions conformance/utils/kubernetes/certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,16 @@ func Test_generateCACert(t *testing.T) {
serverKey.Reset()
// Test the function generateCACert. We can only test normative function
// and hostnames, everything else is hardcoded.
err := generateCACert(tc.hosts, &serverKey, &serverCert)
caBytes, err := generateCACert(tc.hosts)
require.NoError(t, err, "unexpected error generating RSA certificate")

var certData bytes.Buffer
if err := pem.Encode(&certData, &pem.Block{Type: "CERTIFICATE", Bytes: caBytes}); err != nil {
require.NoError(t, err, "failed to create certificater")
}

// Test that the CA certificate is decodable, parseable, and has the configured hostname/s.
block, _ := pem.Decode(serverCert.Bytes())
block, _ := pem.Decode(certData.Bytes())
if block == nil {
require.FailNow(t, "failed to decode PEM block containing cert")
} else if block.Type == "CERTIFICATE" {
Expand All @@ -86,15 +91,6 @@ func Test_generateCACert(t *testing.T) {
}
}
}

// Test that the server key is decodable and parseable.
block, _ = pem.Decode(serverKey.Bytes())
if block == nil {
require.FailNow(t, "failed to decode PEM block containing public key")
} else if block.Type == "RSA PRIVATE KEY" {
_, err := x509.ParsePKCS1PrivateKey(block.Bytes)
require.NoError(t, err, "failed to parse key")
}
})
}
}
3 changes: 2 additions & 1 deletion conformance/utils/roundtripper/roundtripper.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,9 @@ func (d *DefaultRoundTripper) defaultRoundTrip(request Request, transport http.R
return nil, nil, err
}
tlog.Logf(request.T, "Error sending request:\n%s\n\n", formatDump(dump, "< "))
} else {
tlog.Logf(request.T, "Error sending request: %v (no response)\n", err)
}
tlog.Log(request.T, "Error sending request: no response\n")
}
return nil, nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions conformance/utils/suite/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,8 @@ func (suite *ConformanceTestSuite) Setup(t *testing.T, tests []ConformanceTest)
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
secret = kubernetes.MustCreateSelfSignedCertSecret(t, "gateway-conformance-app-backend", "tls-passthrough-checks-certificate", []string{"abc.example.com"})
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{secret}, suite.Cleanup)
caSecret := kubernetes.MustCreateCASignedCertSecret(t, "gateway-conformance-infra", "backend-tls-checks-certificate", []string{"abc.example.com"})
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caSecret}, suite.Cleanup)
caConfigMap := kubernetes.MustCreateCASignedCertConfigMap(t, "gateway-conformance-infra", "backend-tls-checks-certificate", []string{"abc.example.com"})
suite.Applier.MustApplyObjectsWithCleanup(t, suite.Client, suite.TimeoutConfig, []client.Object{caConfigMap}, suite.Cleanup)

tlog.Logf(t, "Test Setup: Ensuring Gateways and Pods from base manifests are ready")
namespaces := []string{
Expand Down

0 comments on commit e58e8bc

Please sign in to comment.