From 18a2c11c63a6e0d4e6fd769a1d8d667b7f12b4d0 Mon Sep 17 00:00:00 2001 From: Charlie Egan Date: Mon, 20 Nov 2023 17:07:33 +0000 Subject: [PATCH] topdown/crypto: Add RawURIs field to JSON certs This is being added to make it easier to write policy on the contents of certificate URI SANs. This is where information like SPIFFE IDs etc are contained and it's helpful to Rego authors to have access to these values without rebuilding the URI from the parsed data under URIs. Fixes https://github.com/open-policy-agent/opa/issues/6416 Signed-off-by: Charlie Egan --- ...-cryptox509parsecertificates-raw-uris.yaml | 14 +++++++++++ topdown/crypto.go | 25 +++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 test/cases/testdata/cryptox509parsecertificates/test-cryptox509parsecertificates-raw-uris.yaml 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 00000000000..17f00af60c1 --- /dev/null +++ b/test/cases/testdata/cryptox509parsecertificates/test-cryptox509parsecertificates-raw-uris.yaml @@ -0,0 +1,14 @@ +cases: +- data: + modules: + - | + package generated + + certs = "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUIxekNDQVh5Z0F3SUJBZ0lJZGxpT1dVY1NXM3N3Q2dZSUtvWkl6ajBFQXdJd1BURUxNQWtHQTFVRUJoTUMKUjBJeEVEQU9CZ05WQkFvVEIwVjRZVzF3YkdVeEhEQWFCZ05WQkFVVEV6RTFPREV4TnpnNU56UTJPRFkxTmpneQpOalF3SUJjTk1qTXhNVEl3TVRZMU5USTRXaGdQTWpFeU1qRXdNamN4TmpVMU1qaGFNRDB4Q3pBSkJnTlZCQVlUCkFrZENNUkF3RGdZRFZRUUtFd2RGZUdGdGNHeGxNUnd3R2dZRFZRUUZFeE00TlRJM056SXlOREE0TlRJeE5qVXoKTVRFMU1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRXp0UDNrQnNpQXY4UUF5eWxUalJZSFlWegpjWTB5YmpBdC9VbWpZb3Fxb0o4SEtIdXF1ckRaUmVwa05qUXdwV3pmZndZZ0xaNk42SisyVUlPdlZ0TDZEcU5rCk1HSXdEZ1lEVlIwUEFRSC9CQVFEQWdlQU1CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0QKQVRBTUJnTlZIUk1CQWY4RUFqQUFNQ01HQTFVZEVRUWNNQnFHR0hOd2FXWm1aVG92TDJWNFlXMXdiR1V1WTI5dApMMjl3WVRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQXlRNDhPd25lTHkzMjZqYitEUjd5RjJhcS94Wnl1cW9qCitUU3ZLVVB5NEU0Q0lRQ0VMUlp3K0dWTjhJR0drVGV4MGxxTDNxY21mWldJbm15VitrbnQ0d3p3L3c9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==" + + uri_strings = crypto.x509.parse_certificates(certs)[0].URIStrings + note: cryptox509parsecertificates/invalid DER or PEM data, string + query: data.generated.uri_strings = x + want_result: + - x: + - spiffe://example.com/opa diff --git a/topdown/crypto.go b/topdown/crypto.go index c33abb2c93c..96645619a3b 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(extentCertificates(certs)) if err != nil { return err } @@ -64,6 +64,27 @@ func builtinCryptoX509ParseCertificates(_ BuiltinContext, operands []*ast.Term, return iter(ast.NewTerm(v)) } +type extendedCert struct { + x509.Certificate + URIStrings []string +} + +func extentCertificates(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 +108,7 @@ func builtinCryptoX509ParseAndVerifyCertificates(_ BuiltinContext, operands []*a return iter(invalid) } - value, err := ast.InterfaceToValue(verified) + value, err := ast.InterfaceToValue(extentCertificates(verified)) if err != nil { return err }