diff --git a/test/cases/testdata/cryptox509parseandverifycertificates/test-cryptox509parseandverifycertificates.yaml b/test/cases/testdata/cryptox509parseandverifycertificates/test-cryptox509parseandverifycertificates.yaml new file mode 100644 index 0000000000..a01fce8061 --- /dev/null +++ b/test/cases/testdata/cryptox509parseandverifycertificates/test-cryptox509parseandverifycertificates.yaml @@ -0,0 +1,138 @@ +cases: +- data: + modules: + - | + package test + + import future.keywords + + certs := `-----BEGIN CERTIFICATE----- + MIIBoDCCAUagAwIBAgIRAJXcMYZALXooNq/VV/grXhMwCgYIKoZIzj0EAwIwLjER + MA8GA1UEChMIT1BBIFRlc3QxGTAXBgNVBAMTEE9QQSBUZXN0IFJvb3QgQ0EwHhcN + MjEwNzAxMTc0MTUzWhcNMzEwNjI5MTc0MTUzWjAuMREwDwYDVQQKEwhPUEEgVGVz + dDEZMBcGA1UEAxMQT1BBIFRlc3QgUm9vdCBDQTBZMBMGByqGSM49AgEGCCqGSM49 + AwEHA0IABFqhdZA5LjsJgzsBvhgzfayZFOk+C7PmGCi7xz6zOC3xWORJZSNOyZeJ + YzSKFmoMZkcFMfslTW1jp9fwe1xl3HWjRTBDMA4GA1UdDwEB/wQEAwIBBjASBgNV + HRMBAf8ECDAGAQH/AgEBMB0GA1UdDgQWBBTch60qxQvLl+AfDfcaXmjvT8GvpzAK + BggqhkjOPQQDAgNIADBFAiBqraIP0l2U0oNuH0+rf36hDks94wSB5EGlGH3lYNMR + ugIhANkbukX5hOP8pJDRWP/pYuv6MBnRY4BS8gpp9Vu31qOb + -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- + MIIByDCCAW6gAwIBAgIQC0k4DPGrh9me73EJX5zntTAKBggqhkjOPQQDAjAuMREw + DwYDVQQKEwhPUEEgVGVzdDEZMBcGA1UEAxMQT1BBIFRlc3QgUm9vdCBDQTAeFw0y + MTA3MDExNzQxNTNaFw0zMTA2MjkxNzQxNTNaMDYxETAPBgNVBAoTCE9QQSBUZXN0 + MSEwHwYDVQQDExhPUEEgVGVzdCBJbnRlcm1lZGlhdGUgQ0EwWTATBgcqhkjOPQIB + BggqhkjOPQMBBwNCAARvXQa7fy476gDI81nqLYb2SnD459WxBmU0hk2bA3ZuNtI+ + H20KXz6ISmxH3MZ2WBm6rOy7y4Gn+WMCJuxzcl5jo2YwZDAOBgNVHQ8BAf8EBAMC + AQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUuslZNjJl0V8I1Gj17IID + ALy/9WEwHwYDVR0jBBgwFoAU3IetKsULy5fgHw33Gl5o70/Br6cwCgYIKoZIzj0E + AwIDSAAwRQIgUwsYApW9Tsm6AstWswaKGie0srB4FUkUbfKwWmUI2JgCIQCBTySN + MF+EiQAMKyz/N9KUuXEckC356WvKcyJaYYcV0w== + -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- + MIIB8zCCAZqgAwIBAgIRAID4gPKg7DDiuOfzUYFSXLAwCgYIKoZIzj0EAwIwNjER + MA8GA1UEChMIT1BBIFRlc3QxITAfBgNVBAMTGE9QQSBUZXN0IEludGVybWVkaWF0 + ZSBDQTAeFw0yMTA3MDUxNzQ5NTBaFw0zNjA3MDExNzQ5NDdaMCUxIzAhBgNVBAMT + Gm5vdGFyZWFsc2l0ZS5vcGEubG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0D + AQcDQgAE1YSXZXeaGGL+XeYyoPi/QdA39Ds4fgxSHJTMh+js393kByPm2PNtFkem + tUii3KCRJw3SEh3z0JWr/9y4+ua2L6OBmTCBljAOBgNVHQ8BAf8EBAMCB4AwHQYD + VR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBRL0P0g17viZHo9 + CnXe3ZQJm48LXTAfBgNVHSMEGDAWgBS6yVk2MmXRXwjUaPXsggMAvL/1YTAlBgNV + HREEHjAcghpub3RhcmVhbHNpdGUub3BhLmxvY2FsaG9zdDAKBggqhkjOPQQDAgNH + ADBEAiAtmZewL94ijN0YwUGaJM9BXCaoTQPwkzugqjCj+K912QIgKKFvbPu4asrE + nwy7dzejHmQUcZ/aUNbc4VTbiv15ESk= + -----END CERTIFICATE----- + ` + + value := crypto.x509.parse_and_verify_certificates(certs) + + result := { + "valid": value[0], + "certs": [c| + some cert in value[1] + c := { + "CN": cert.Subject.CommonName, + "DNS": cert.DNSNames, + "URI": cert.URIStrings, + } + ], + } + + note: cryptox509parseandverifycertificates/base_case + query: data.test.result = x + want_result: + - x: + certs: + - CN: notarealsite.opa.localhost + DNS: + - notarealsite.opa.localhost + URI: + - CN: OPA Test Intermediate CA + DNS: + URI: + - CN: OPA Test Root CA + DNS: + URI: + valid: true +- data: + modules: + - | + package test + + import future.keywords + + certs := `-----BEGIN CERTIFICATE----- + MIIB1TCCAXugAwIBAgIIKIoxsnMwJJ4wCgYIKoZIzj0EAwIwPTELMAkGA1UEBhMC + R0IxEDAOBgNVBAoTB0V4YW1wbGUxHDAaBgNVBAUTEzI5MjEyMDE5NTA4MDk2NjI2 + MjIwIBcNMjMxMTI5MTc1NTQ2WhgPMjEyMzExMDUxNzU1NDZaMD0xCzAJBgNVBAYT + AkdCMRAwDgYDVQQKEwdFeGFtcGxlMRwwGgYDVQQFExMyOTIxMjAxOTUwODA5NjYy + NjIyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEkvI9ddM0SuP9LvBWS1y64fuK + ELCjVF5W3FSKm3azKEkDi8Eq1I1UM80MgCjC5ChNNyM4+cmVUDrCkTl3SqRxa6Nj + MGEwDgYDVR0PAQH/BAQDAgIEMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFF7H + A8n3mXXnwUP0ypMJ9JwY5wasMB8GA1UdEQQYMBaGFHNwaWZmZTovL2V4YW1wbGUu + Y29tMAoGCCqGSM49BAMCA0gAMEUCIByB2l5RIWmaU8qcRv13qigbB9BV/F2raEk+ + pRQnsUcgAiEA9OvBpPKC/FBkI5vVvR7WgK5sGPna4+a0RkXxRQgN2jM= + -----END CERTIFICATE----- + -----BEGIN CERTIFICATE----- + MIIB1jCCAXygAwIBAgIIV9914tIKKkMwCgYIKoZIzj0EAwIwPTELMAkGA1UEBhMC + R0IxEDAOBgNVBAoTB0V4YW1wbGUxHDAaBgNVBAUTEzI5MjEyMDE5NTA4MDk2NjI2 + MjIwIBcNMjMxMTI5MTc1NTQ2WhgPMjEyMjExMDUxNzU1NDZaMD0xCzAJBgNVBAYT + AkdCMRAwDgYDVQQKEwdFeGFtcGxlMRwwGgYDVQQFExM2MzMxOTA5MjE4MTUzMTQ2 + OTQ3MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEMoy2UqvC8zL3sPfLNvG1nX5p + 6hhEyDjFtokORB4VkKiPXFryIFn8XHG0ipz6aKSwVMoDT2T/YXP/wWpVwPJCi6Nk + MGIwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD + ATAMBgNVHRMBAf8EAjAAMCMGA1UdEQQcMBqGGHNwaWZmZTovL2V4YW1wbGUuY29t + L29wYTAKBggqhkjOPQQDAgNIADBFAiBEmdSKGj2+9J5SQPIAmwdxpVTOxqmVQv2x + Vvita/AmowIhAOyX/alNJxL4iCfKUNwlC2lYxGhuWopWgB1Q32bQhTEh + -----END CERTIFICATE----- + ` + + value := crypto.x509.parse_and_verify_certificates(certs) + + result := { + "valid": value[0], + "certs": [c| + some cert in value[1] + c := { + "CN": cert.Subject.CommonName, + "DNS": cert.DNSNames, + "URI": cert.URIStrings, + } + ], + } + + note: cryptox509parseandverifycertificates/uri_strings + query: data.test.result = x + want_result: + - x: + certs: + - CN: '' + DNS: null + URI: + - spiffe://example.com/opa + - CN: '' + DNS: null + URI: + - spiffe://example.com + valid: true + diff --git a/test/cases/testdata/cryptox509parsecertificates/test-cryptox509parsecertificates-raw-uris.yaml b/test/cases/testdata/cryptox509parsecertificates/test-cryptox509parsecertificates-raw-uris.yaml new file mode 100644 index 0000000000..131c86da5f --- /dev/null +++ b/test/cases/testdata/cryptox509parsecertificates/test-cryptox509parsecertificates-raw-uris.yaml @@ -0,0 +1,26 @@ +cases: +- data: + modules: + - | + package generated + + certs = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUIxekNDQVh5Z0F3SUJBZ0lJZGxpT1dVY1NXM3N3Q2dZSUtvWkl6ajBFQXdJd1BURUxNQWtHQTFVRUJoTUMKUjBJeEVEQU9CZ05WQkFvVEIwVjRZVzF3YkdVeEhEQWFCZ05WQkFVVEV6RTFPREV4TnpnNU56UTJPRFkxTmpneQpOalF3SUJjTk1qTXhNVEl3TVRZMU5USTRXaGdQTWpFeU1qRXdNamN4TmpVMU1qaGFNRDB4Q3pBSkJnTlZCQVlUCkFrZENNUkF3RGdZRFZRUUtFd2RGZUdGdGNHeGxNUnd3R2dZRFZRUUZFeE00TlRJM056SXlOREE0TlRJeE5qVXoKTVRFMU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXp0UDNrQnNpQXY4UUF5eWxUalJZSFlWegpjWTB5YmpBdC9VbWpZb3Fxb0o4SEtIdXF1ckRaUmVwa05qUXdwV3pmZndZZ0xaNk42SisyVUlPdlZ0TDZEcU5rCk1HSXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0QKQVRBTUJnTlZIUk1CQWY4RUFqQUFNQ01HQTFVZEVRUWNNQnFHR0hOd2FXWm1aVG92TDJWNFlXMXdiR1V1WTI5dApMMjl3WVRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQXlRNDhPd25lTHkzMjZqYitEUjd5RjJhcS94Wnl1cW9qCitUU3ZLVVB5NEU0Q0lRQ0VMUlp3K0dWTjhJR0drVGV4MGxxTDNxY21mWldJbm15VitrbnQ0d3p3L3c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==" + + uri_strings = crypto.x509.parse_certificates(certs)[0].URIStrings + note: cryptox509parsecertificates/uri_strings + query: data.generated.uri_strings = x + want_result: + - x: + - spiffe://example.com/opa +- data: + modules: + - | + package generated + + certs = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNTakNDQWJPZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRMEZBREJDTVFzd0NRWURWUVFHRXdKMWN6RUwKTUFrR0ExVUVDQXdDUTBFeEVEQU9CZ05WQkFvTUIwVjRZVzF3YkdVeEZEQVNCZ05WQkFNTUMyVjRZVzF3YkdVdQpZMjl0TUI0WERUSXpNVEV5T1RFMk5ESXdPRm9YRFRJME1URXlPREUyTkRJd09Gb3dRakVMTUFrR0ExVUVCaE1DCmRYTXhDekFKQmdOVkJBZ01Ba05CTVJBd0RnWURWUVFLREFkRmVHRnRjR3hsTVJRd0VnWURWUVFEREF0bGVHRnQKY0d4bExtTnZiVENCbnpBTkJna3Foa2lHOXcwQkFRRUZBQU9CalFBd2dZa0NnWUVBempOT1puY05DL25MdEZQYwpUNnNlSzZ0ditTbU9GaGk3NVBKRm9sQ0dFZUFiTHJHTzhaUmR2cXY2OStTTk41MUhrNFBJUDUrejk4aHZIdWJQClVtcGdOMVdVM3FKK2tOVTJXL3poR3pLMTdIL2c3YjVJTjRHZmx3bXJlRWZscnRicnZKSGRlRkVhVGtmYnVld0YKVmZvLzRiaG0yYUthczNHcUo3RnlBNDVxeVUwQ0F3RUFBYU5RTUU0d0hRWURWUjBPQkJZRUZOUStDMUVOK0dSYwpGS1dyTll6ZWdnbFc3TE9lTUI4R0ExVWRJd1FZTUJhQUZOUStDMUVOK0dSY0ZLV3JOWXplZ2dsVzdMT2VNQXdHCkExVWRFd1FGTUFNQkFmOHdEUVlKS29aSWh2Y05BUUVOQlFBRGdZRUF1cXdVVWVXbTFJaURRbmphK1hqd1VCaXUKQXBYWEx5NlFZRG9jUkhoRHlJS3BKSWRJOXltNi9RcVhkOFQ2WGlYUTJDbFNJbGxBSTByQWJYNUZvYzNxaWRkUAp0d2huT1pxd3NZdFhUNy9XOHFLSm5FVnhZckJuRmZSdk9SU3ZlOEtwSDErVHQ2elZEYlJ5bENacTR1TTNrZXN2CmJabXlVdlM1bldBVm44ZmhFdUU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=" + + uri_strings = crypto.x509.parse_certificates(certs)[0].URIStrings + note: cryptox509parsecertificates/uri_strings_no_uris + query: data.generated.uri_strings = x + want_result: + - x: null diff --git a/topdown/crypto.go b/topdown/crypto.go index c33abb2c93..520c051860 100644 --- a/topdown/crypto.go +++ b/topdown/crypto.go @@ -56,7 +56,7 @@ func builtinCryptoX509ParseCertificates(_ BuiltinContext, operands []*ast.Term, return err } - v, err := ast.InterfaceToValue(certs) + v, err := ast.InterfaceToValue(extendCertificates(certs)) if err != nil { return err } @@ -64,6 +64,28 @@ func builtinCryptoX509ParseCertificates(_ BuiltinContext, operands []*ast.Term, return iter(ast.NewTerm(v)) } +// extendedCert is a wrapper around x509.Certificate that adds additional fields for JSON serialization. +type extendedCert struct { + x509.Certificate + URIStrings []string +} + +func extendCertificates(certs []*x509.Certificate) []extendedCert { + // add a field to certs containing the URIs as strings + processedCerts := make([]extendedCert, len(certs)) + + for i, cert := range certs { + processedCerts[i].Certificate = *cert + if cert.URIs != nil { + processedCerts[i].URIStrings = make([]string, len(cert.URIs)) + for j, uri := range cert.URIs { + processedCerts[i].URIStrings[j] = uri.String() + } + } + } + return processedCerts +} + func builtinCryptoX509ParseAndVerifyCertificates(_ BuiltinContext, operands []*ast.Term, iter func(*ast.Term) error) error { a := operands[0].Value @@ -87,7 +109,7 @@ func builtinCryptoX509ParseAndVerifyCertificates(_ BuiltinContext, operands []*a return iter(invalid) } - value, err := ast.InterfaceToValue(verified) + value, err := ast.InterfaceToValue(extendCertificates(verified)) if err != nil { return err }