Skip to content

Commit

Permalink
feat(kuma-cp) Intermediate CA support (#2575)
Browse files Browse the repository at this point in the history
Signed-off-by: Jakub Dyszkiewicz <jakub.dyszkiewicz@gmail.com>
  • Loading branch information
jakubdyszkiewicz authored Aug 17, 2021
1 parent c89ac43 commit dba1a9c
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 180 deletions.
49 changes: 22 additions & 27 deletions pkg/plugins/ca/provided/ca_cert_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,28 @@ func validateCaCert(signingPair util_tls.KeyPair) (verr validators.ValidationErr
verr.AddViolation("cert", fmt.Sprintf("not a valid TLS key pair: %s", err))
return
}
if len(tlsKeyPair.Certificate) != 1 {
verr.AddViolation("cert", "certificate must be a root CA (certificate chains are not allowed)") // Envoy constraint
return
}
cert, err := x509.ParseCertificate(tlsKeyPair.Certificate[0])
if err != nil {
verr.AddViolation("cert", fmt.Sprintf("not a valid x509 certificate: %s", err))
return
}
if cert.Issuer.String() != cert.Subject.String() {
verr.AddViolation("cert", "certificate must be self-signed (intermediate CAs are not allowed)") // Envoy constraint
}
if !cert.IsCA {
verr.AddViolation("cert", "basic constraint 'CA' must be set to 'true' (see X509-SVID: 4.1. Basic Constraints)")
for i, certificate := range tlsKeyPair.Certificate {
path := validators.RootedAt("cert").Index(i)
cert, err := x509.ParseCertificate(certificate)
if err != nil {
verr.AddViolationAt(path, fmt.Sprintf("not a valid x509 certificate: %s", err))
return
}
if !cert.IsCA {
verr.AddViolationAt(path, "basic constraint 'CA' must be set to 'true' (see X509-SVID: 4.1. Basic Constraints)")
}
if cert.KeyUsage&x509.KeyUsageCertSign == 0 {
verr.AddViolationAt(path, "key usage extension 'keyCertSign' must be set (see X509-SVID: 4.3. Key Usage)")
}
if cert.KeyUsage&x509.KeyUsageDigitalSignature != 0 {
verr.AddViolationAt(path, "key usage extension 'digitalSignature' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)")
}
if cert.KeyUsage&x509.KeyUsageKeyAgreement != 0 {
verr.AddViolationAt(path, "key usage extension 'keyAgreement' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)")
}
if cert.KeyUsage&x509.KeyUsageKeyEncipherment != 0 {
verr.AddViolationAt(path, "key usage extension 'keyEncipherment' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)")
}
}
if cert.KeyUsage&x509.KeyUsageCertSign == 0 {
verr.AddViolation("cert", "key usage extension 'keyCertSign' must be set (see X509-SVID: 4.3. Key Usage)")
}
if cert.KeyUsage&x509.KeyUsageDigitalSignature != 0 {
verr.AddViolation("cert", "key usage extension 'digitalSignature' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)")
}
if cert.KeyUsage&x509.KeyUsageKeyAgreement != 0 {
verr.AddViolation("cert", "key usage extension 'keyAgreement' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)")
}
if cert.KeyUsage&x509.KeyUsageKeyEncipherment != 0 {
verr.AddViolation("cert", "key usage extension 'keyEncipherment' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)")
}

return
}
164 changes: 11 additions & 153 deletions pkg/plugins/ca/provided/ca_cert_validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,148 +126,6 @@ LG//nB619RAlzta6BxweiCmFxPyB+oqJl3X9NfWC7988CzfZAqHA+CqO6tJS5i53
WMciH6+W7o9wdsBrfFVx2tGZqc4bZgoZptHFieqz7YBnT0Ozg+NwBU6apAtAc5Ym
DMoTRP2Vo+BEm4uS4GcIFZYqrOsPuuyMuBd0NDE33g==
-----END CERTIFICATE-----
`),
KeyPEM: []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvh4DhQDuE/oXjEJzt1TmgmM6s5DtsIYIEPssxdDiDEjmJzhG
APd0BmAfrz3/fXZ6CqqqfAvTKkTDGjSN0hGtt1thF72weNfmQX9c1gUukEA0gERS
OsSWlzp8Azc5fjXtl5jiQkvaapNoQ8PljLc8SEsgndvdxD1tDVWN6h90bMgtuqyK
M7Fn/1+nwhRExKRTOSlR0iS9eddWPcN3HNGrl3vjCF0oUF/79+nJJqeaXawt0+2P
CMkxY6T6yzFaS/h0Oy3mXLOQ1H5n3cZ2MSEMKQSs9ff8gzeHpWyXpgB1XEKNcUvi
rVKfaJ/WE5v0rieG89B/YnQTduQnrwmPVuwm4wIDAQABAoIBAQCxKKrC7+DqwKvc
ybem6Ph8HBeBaNX1HpC5sjVAiKt8IxpFBc1F7VEy97POywkfUp3a/rorKaG2y6i6
7KoTTOIB8KcDRoIBub4Y3qQV03JWfV3vALtXhAWIGrmhDX8Hux0RnSeJ+8EmewI3
034+qCkGfOuB7nYy/cJ3IHhD6NfG3Q3FrBrGfsI2TGEeGmPJ2Xi8ZyfbluRb/1Bt
NesS6pDbRpZ5/IoauLUtITY3bazpzghm2tJNdrJIP7ohaoMF0WYciPyD5xpNlykt
V8Q2jzNmPYVXuUpi4oPekq4Mg1vd/LPS/JE558Am1LEiXrycelGNrDvJW7hTDLVx
DLRFuMMxAoGBAMkjupL3mxAfNytXM++WxJbdWPuw/vvAeN60ifFu6RUrMs/aXocn
4xSunNF58O2aRfSq/B9LJ+pXtmdITV+Bu0Y1XefKtNUNoqIapAbA8gAWUcFSkDRd
999rh0vWPbx4d3k69iS6xIjVaRcxeuaBbKRWqUcrxDuAydhwTLIRMD1vAoGBAPH4
quLGkr1MdTeZ3qPAWc9mGelp0LhHukjnLB+nMdI73OH7IlX5or11yr6La/+sTmmQ
fI+oITLuCyey7VnWBDhrPmWFGA1BmZIVDqjkJJNwyWQO7N27rQEQoNKm5n6Q+boy
StNKa/ljduYXCjsBndOmF1wSrAwL+u9rQ3x4k9vNAoGAGY5vm1LYofDFar1WvP90
FRMkxj4T99rZwLpBuKp19RmbCCvfzN51jOAuzrLmuNncP50mEbfT54OjinX2Vsc+
C0qmltf7qAJmgqBN7QnA9d/gHWcnKXAzGXEpLKqZB4Rq8b1bHwmYBSbQhoDj87vI
GQ1lzsQx17mia9zA8fMbJQMCgYB0D+2PpuW9rM3QpJp4+wtZAsVNAzddHPKKg2/T
ovOvvoz9S+M1T+8yZyyfZuqfkTtvQSGuGlwKPMnW+ekFHTWbBj3Ani1iNmP+AOGu
OvgcTI4c01fkJ2AdUaeCQxHuBYXzPKpNXLYbwgzG4qhCk0zrtxAfVsl1Yc20R0Pw
kTmCxQKBgQCzd/OOLm7vDEUqYNUNgKlf8I9xM84IwUy+pJP8RaeFDtFj7tVDpY2P
GXHBXcIBDRPnmBxC7cGHCB3KBWJp11smw2qA0ZgmBIShNm1RDHf/1h0yOxSz2+fB
bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
-----END RSA PRIVATE KEY-----
`),
},
}
}),
Entry("chain of CAs", func() testCase {
return testCase{
expectedErr: `
violations:
- field: cert
message: "certificate must be a root CA (certificate chains are not allowed)"
`,
input: util_tls.KeyPair{
CertPEM: []byte(`
-----BEGIN CERTIFICATE-----
MIIDKzCCAhOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAwMQ0wCwYDVQQKEwRLdW1h
MQ0wCwYDVQQLEwRNZXNoMRAwDgYDVQQDEwdkZWZhdWx0MB4XDTIwMDEyOTE2MDgw
NFoXDTMwMDEyNjE2MDgxNFowQDENMAsGA1UEChMES3VtYTEdMAsGA1UECxMETWVz
aDAOBgNVBAsTB2xldmVsLTExEDAOBgNVBAMTB2RlZmF1bHQwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC+HgOFAO4T+heMQnO3VOaCYzqzkO2whggQ+yzF
0OIMSOYnOEYA93QGYB+vPf99dnoKqqp8C9MqRMMaNI3SEa23W2EXvbB41+ZBf1zW
BS6QQDSARFI6xJaXOnwDNzl+Ne2XmOJCS9pqk2hDw+WMtzxISyCd293EPW0NVY3q
H3RsyC26rIozsWf/X6fCFETEpFM5KVHSJL1511Y9w3cc0auXe+MIXShQX/v36ckm
p5pdrC3T7Y8IyTFjpPrLMVpL+HQ7LeZcs5DUfmfdxnYxIQwpBKz19/yDN4elbJem
AHVcQo1xS+KtUp9on9YTm/SuJ4bz0H9idBN25CevCY9W7CbjAgMBAAGjQDA+MA4G
A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBsGA1UdEQQUMBKGEHNwaWZm
ZTovL2RlZmF1bHQwDQYJKoZIhvcNAQELBQADggEBACVXnYWCCrji551pbJsOCGYJ
GEqlvcwNnnYdykas4GrfsbW2rglmaXv0uG8iH2sAH+4/MjGjnlQ6Y6Fj7mDFnidj
ugU964sEDnLuU0CtaIpHl7VZ13I0EzmfY+GsCrcIXIxbAxwWTJhz77XqbHe3baLx
Sh9wHgz/aZuy99rq9OoAvUALEaIfxrvUsVs25jLuv0Xzy57B2Dpqo0odshDA4WSS
MynQnSX7aFg1jqZQL4YjPHryEQQRj8mgjqiWp8M4/PHq5s09zDMB0DCag0QtdC/k
ydtqRoojiRS2fXY8DhFRqqRVBqLvA+7eTEKpzfjUTyEovMqxIM2n4U5MSGKQlbM=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDGzCCAgOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAwMQ0wCwYDVQQKEwRLdW1h
MQ0wCwYDVQQLEwRNZXNoMRAwDgYDVQQDEwdkZWZhdWx0MB4XDTIwMDEyOTE2MDgw
NFoXDTMwMDEyNjE2MDgxNFowMDENMAsGA1UEChMES3VtYTENMAsGA1UECxMETWVz
aDEQMA4GA1UEAxMHZGVmYXVsdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBANhewNnHZI0f+55vsm+iGej9NAYFtCb2FNzFHZlGcu0F07YSAyorPJuM+6V3
BFcY2IkWHL8WOooNmJ0X/yzBd4RSrb3TacGKtaDayRjTo8JOW7Nlh+WvwR18KHjC
QXDjlqkmfExdYIUZjOqJOhu9nO59fqz0SJFvo2WKkkP7CaTLQXt1p3+Hm1Xo5WCX
ZfD7W57YhNBZZLljip/N8pDL7b2Vkhe+txbv/PqVrDRMGoyRBnPNAfS7SPocRbcE
S9th2CesNu+Iwltu4gJBOQbpydBIjJvr1zrx/zxbxM+EbqbGr6gwquGvKTyXHq20
u5CE4tWy3GKSh5LEVItPS066d5UCAwEAAaNAMD4wDgYDVR0PAQH/BAQDAgEGMA8G
A1UdEwEB/wQFMAMBAf8wGwYDVR0RBBQwEoYQc3BpZmZlOi8vZGVmYXVsdDANBgkq
hkiG9w0BAQsFAAOCAQEAMvMqCzbjEveuMlTch9q+/6KcFVUkwQcTcxxs0MPnw5Lw
hY6xo7FvIHNLJDRlShoAyjI6OJZobJ7PFaFnIXWlNcN1F+gA9OZSSWYgJNJl4zee
eS2pHgbxZ6OJqCbDGYWekF3d1vEcI3gaRfxFDVa8eJFBq+B0v2Pho8A2bY5srO0S
LG//nB619RAlzta6BxweiCmFxPyB+oqJl3X9NfWC7988CzfZAqHA+CqO6tJS5i53
WMciH6+W7o9wdsBrfFVx2tGZqc4bZgoZptHFieqz7YBnT0Ozg+NwBU6apAtAc5Ym
DMoTRP2Vo+BEm4uS4GcIFZYqrOsPuuyMuBd0NDE33g==
-----END CERTIFICATE-----
`),
KeyPEM: []byte(`
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAvh4DhQDuE/oXjEJzt1TmgmM6s5DtsIYIEPssxdDiDEjmJzhG
APd0BmAfrz3/fXZ6CqqqfAvTKkTDGjSN0hGtt1thF72weNfmQX9c1gUukEA0gERS
OsSWlzp8Azc5fjXtl5jiQkvaapNoQ8PljLc8SEsgndvdxD1tDVWN6h90bMgtuqyK
M7Fn/1+nwhRExKRTOSlR0iS9eddWPcN3HNGrl3vjCF0oUF/79+nJJqeaXawt0+2P
CMkxY6T6yzFaS/h0Oy3mXLOQ1H5n3cZ2MSEMKQSs9ff8gzeHpWyXpgB1XEKNcUvi
rVKfaJ/WE5v0rieG89B/YnQTduQnrwmPVuwm4wIDAQABAoIBAQCxKKrC7+DqwKvc
ybem6Ph8HBeBaNX1HpC5sjVAiKt8IxpFBc1F7VEy97POywkfUp3a/rorKaG2y6i6
7KoTTOIB8KcDRoIBub4Y3qQV03JWfV3vALtXhAWIGrmhDX8Hux0RnSeJ+8EmewI3
034+qCkGfOuB7nYy/cJ3IHhD6NfG3Q3FrBrGfsI2TGEeGmPJ2Xi8ZyfbluRb/1Bt
NesS6pDbRpZ5/IoauLUtITY3bazpzghm2tJNdrJIP7ohaoMF0WYciPyD5xpNlykt
V8Q2jzNmPYVXuUpi4oPekq4Mg1vd/LPS/JE558Am1LEiXrycelGNrDvJW7hTDLVx
DLRFuMMxAoGBAMkjupL3mxAfNytXM++WxJbdWPuw/vvAeN60ifFu6RUrMs/aXocn
4xSunNF58O2aRfSq/B9LJ+pXtmdITV+Bu0Y1XefKtNUNoqIapAbA8gAWUcFSkDRd
999rh0vWPbx4d3k69iS6xIjVaRcxeuaBbKRWqUcrxDuAydhwTLIRMD1vAoGBAPH4
quLGkr1MdTeZ3qPAWc9mGelp0LhHukjnLB+nMdI73OH7IlX5or11yr6La/+sTmmQ
fI+oITLuCyey7VnWBDhrPmWFGA1BmZIVDqjkJJNwyWQO7N27rQEQoNKm5n6Q+boy
StNKa/ljduYXCjsBndOmF1wSrAwL+u9rQ3x4k9vNAoGAGY5vm1LYofDFar1WvP90
FRMkxj4T99rZwLpBuKp19RmbCCvfzN51jOAuzrLmuNncP50mEbfT54OjinX2Vsc+
C0qmltf7qAJmgqBN7QnA9d/gHWcnKXAzGXEpLKqZB4Rq8b1bHwmYBSbQhoDj87vI
GQ1lzsQx17mia9zA8fMbJQMCgYB0D+2PpuW9rM3QpJp4+wtZAsVNAzddHPKKg2/T
ovOvvoz9S+M1T+8yZyyfZuqfkTtvQSGuGlwKPMnW+ekFHTWbBj3Ani1iNmP+AOGu
OvgcTI4c01fkJ2AdUaeCQxHuBYXzPKpNXLYbwgzG4qhCk0zrtxAfVsl1Yc20R0Pw
kTmCxQKBgQCzd/OOLm7vDEUqYNUNgKlf8I9xM84IwUy+pJP8RaeFDtFj7tVDpY2P
GXHBXcIBDRPnmBxC7cGHCB3KBWJp11smw2qA0ZgmBIShNm1RDHf/1h0yOxSz2+fB
bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
-----END RSA PRIVATE KEY-----
`),
},
}
}),
Entry("not a self-signed certificate", func() testCase {
return testCase{
expectedErr: `
violations:
- field: cert
message: "certificate must be self-signed (intermediate CAs are not allowed)"
`,
input: util_tls.KeyPair{
CertPEM: []byte(`
-----BEGIN CERTIFICATE-----
MIIDKzCCAhOgAwIBAgIBADANBgkqhkiG9w0BAQsFADAwMQ0wCwYDVQQKEwRLdW1h
MQ0wCwYDVQQLEwRNZXNoMRAwDgYDVQQDEwdkZWZhdWx0MB4XDTIwMDEyOTE2MDgw
NFoXDTMwMDEyNjE2MDgxNFowQDENMAsGA1UEChMES3VtYTEdMAsGA1UECxMETWVz
aDAOBgNVBAsTB2xldmVsLTExEDAOBgNVBAMTB2RlZmF1bHQwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC+HgOFAO4T+heMQnO3VOaCYzqzkO2whggQ+yzF
0OIMSOYnOEYA93QGYB+vPf99dnoKqqp8C9MqRMMaNI3SEa23W2EXvbB41+ZBf1zW
BS6QQDSARFI6xJaXOnwDNzl+Ne2XmOJCS9pqk2hDw+WMtzxISyCd293EPW0NVY3q
H3RsyC26rIozsWf/X6fCFETEpFM5KVHSJL1511Y9w3cc0auXe+MIXShQX/v36ckm
p5pdrC3T7Y8IyTFjpPrLMVpL+HQ7LeZcs5DUfmfdxnYxIQwpBKz19/yDN4elbJem
AHVcQo1xS+KtUp9on9YTm/SuJ4bz0H9idBN25CevCY9W7CbjAgMBAAGjQDA+MA4G
A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MBsGA1UdEQQUMBKGEHNwaWZm
ZTovL2RlZmF1bHQwDQYJKoZIhvcNAQELBQADggEBACVXnYWCCrji551pbJsOCGYJ
GEqlvcwNnnYdykas4GrfsbW2rglmaXv0uG8iH2sAH+4/MjGjnlQ6Y6Fj7mDFnidj
ugU964sEDnLuU0CtaIpHl7VZ13I0EzmfY+GsCrcIXIxbAxwWTJhz77XqbHe3baLx
Sh9wHgz/aZuy99rq9OoAvUALEaIfxrvUsVs25jLuv0Xzy57B2Dpqo0odshDA4WSS
MynQnSX7aFg1jqZQL4YjPHryEQQRj8mgjqiWp8M4/PHq5s09zDMB0DCag0QtdC/k
ydtqRoojiRS2fXY8DhFRqqRVBqLvA+7eTEKpzfjUTyEovMqxIM2n4U5MSGKQlbM=
-----END CERTIFICATE-----
`),
KeyPEM: []byte(`
-----BEGIN RSA PRIVATE KEY-----
Expand Down Expand Up @@ -314,9 +172,9 @@ bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
return testCase{
expectedErr: `
violations:
- field: cert
- field: cert[0]
message: "basic constraint 'CA' must be set to 'true' (see X509-SVID: 4.1. Basic Constraints)"
- field: cert
- field: cert[0]
message: "key usage extension 'keyCertSign' must be set (see X509-SVID: 4.3. Key Usage)"
`,
input: *keyPair,
Expand All @@ -337,7 +195,7 @@ bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
return testCase{
expectedErr: `
violations:
- field: cert
- field: cert[0]
message: "key usage extension 'keyCertSign' must be set (see X509-SVID: 4.3. Key Usage)"
`,
input: *keyPair,
Expand All @@ -360,7 +218,7 @@ bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
return testCase{
expectedErr: `
violations:
- field: cert
- field: cert[0]
message: "key usage extension 'digitalSignature' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)"
`,
input: *keyPair,
Expand All @@ -383,7 +241,7 @@ bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
return testCase{
expectedErr: `
violations:
- field: cert
- field: cert[0]
message: "key usage extension 'keyAgreement' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)"
`,
input: *keyPair,
Expand All @@ -406,7 +264,7 @@ bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
return testCase{
expectedErr: `
violations:
- field: cert
- field: cert[0]
message: "key usage extension 'keyEncipherment' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)"
`,
input: *keyPair,
Expand All @@ -428,15 +286,15 @@ bgeEDefxTxoTMgJ1urwl0KX6R9dbv9YWZWJXk2DQj6UwkMEyXpc+kw==
return testCase{
expectedErr: `
violations:
- field: cert
- field: cert[0]
message: "basic constraint 'CA' must be set to 'true' (see X509-SVID: 4.1. Basic Constraints)"
- field: cert
- field: cert[0]
message: "key usage extension 'keyCertSign' must be set (see X509-SVID: 4.3. Key Usage)"
- field: cert
- field: cert[0]
message: "key usage extension 'digitalSignature' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)"
- field: cert
- field: cert[0]
message: "key usage extension 'keyAgreement' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)"
- field: cert
- field: cert[0]
message: "key usage extension 'keyEncipherment' must NOT be set (see X509-SVID: Appendix A. X.509 Field Reference)"
`,
input: *keyPair,
Expand Down
16 changes: 16 additions & 0 deletions test/e2e/mtls/universal/e2e_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package universal_test

import (
"testing"

"github.com/kumahq/kuma/pkg/test"
"github.com/kumahq/kuma/test/framework"
)

func TestE2EMTLSUniversal(t *testing.T) {
if framework.IsK8sClustersStarted() {
test.RunSpecs(t, "mTLS Universal Suite")
} else {
t.SkipNow()
}
}
Loading

0 comments on commit dba1a9c

Please sign in to comment.