From e205cdf43548366576b221af1a7b7ccf1162ca4b Mon Sep 17 00:00:00 2001 From: Ronnie Flathers Date: Fri, 21 Apr 2023 09:20:40 -0500 Subject: [PATCH 1/2] loop through contents adding all pem blocks --- internal/provider/data_source_certificate.go | 56 +++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/internal/provider/data_source_certificate.go b/internal/provider/data_source_certificate.go index a740b56e..40546989 100644 --- a/internal/provider/data_source_certificate.go +++ b/internal/provider/data_source_certificate.go @@ -120,37 +120,43 @@ func (ds *certificateDataSource) Read(ctx context.Context, req datasource.ReadRe var certs []CertificateModel if !newState.Content.IsNull() && !newState.Content.IsUnknown() { - block, _ := pem.Decode([]byte(newState.Content.ValueString())) - if block == nil { + pemBytes := []byte(newState.Content.ValueString()) + var block *pem.Block + // Loop through the entire contents decoding PEM blocks + for { + block, pemBytes = pem.Decode(pemBytes) + if block == nil { + break + } + preamble, err := pemBlockToPEMPreamble(block) + if err != nil { + res.Diagnostics.AddError("Failed to identify PEM preamble", err.Error()) + return + } + + if preamble != PreambleCertificate { + res.Diagnostics.AddError( + "Unexpected PEM preamble", + fmt.Sprintf("Certificate PEM should be %q, got %q", PreambleCertificate, preamble), + ) + return + } + + cert, err := x509.ParseCertificate(block.Bytes) + if err != nil { + res.Diagnostics.AddError("Unable to parse certificate", err.Error()) + return + } + certs = append(certs, certificateToStruct(cert)) + } + if len(certs) == 0 { res.Diagnostics.AddAttributeError( path.Root("content"), "Failed to decoded PEM", - "Value is not a valid PEM encoding of a certificate", + "Value is not a valid PEM encoding of certificate(s)", ) return } - - preamble, err := pemBlockToPEMPreamble(block) - if err != nil { - res.Diagnostics.AddError("Failed to identify PEM preamble", err.Error()) - return - } - - if preamble != PreambleCertificate { - res.Diagnostics.AddError( - "Unexpected PEM preamble", - fmt.Sprintf("Certificate PEM should be %q, got %q", PreambleCertificate, preamble), - ) - return - } - - cert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - res.Diagnostics.AddError("Unable to parse certificate", err.Error()) - return - } - - certs = []CertificateModel{certificateToStruct(cert)} } else { targetURL, err := url.Parse(newState.URL.ValueString()) if err != nil { From e77f0450fe601c80703009286bd85fd823a93a0c Mon Sep 17 00:00:00 2001 From: Ronnie Flathers Date: Fri, 21 Apr 2023 09:34:18 -0500 Subject: [PATCH 2/2] add test for chain from content --- .../provider/data_source_certificate_test.go | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/internal/provider/data_source_certificate_test.go b/internal/provider/data_source_certificate_test.go index 220c8f3a..2ed7061d 100644 --- a/internal/provider/data_source_certificate_test.go +++ b/internal/provider/data_source_certificate_test.go @@ -44,6 +44,51 @@ func TestDataSourceCertificate_CertificateContent(t *testing.T) { }) } +func TestDataSourceCertificate_CertificateContentChain(t *testing.T) { + r.UnitTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + + Steps: []r.TestStep{ + { + Config: ` + data "tls_certificate" "test" { + content = file("fixtures/public.pem") + } + `, + Check: r.ComposeAggregateTestCheckFunc( + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.#", "2"), + + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.signature_algorithm", "SHA256-RSA"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.public_key_algorithm", "RSA"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.serial_number", "266244246501122064554217434340898012243"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.is_ca", "false"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.version", "3"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.issuer", "CN=Root CA,O=Test Org,L=Here"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.subject", "CN=Child Cert,O=Child Co.,L=Everywhere"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.not_before", "2019-11-08T09:01:36Z"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.not_after", "2019-11-08T19:01:36Z"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.sha1_fingerprint", "61b65624427d75b61169100836904e44364df817"), + tu.TestCheckPEMFormat("data.tls_certificate.test", "certificates.0.cert_pem", PreambleCertificate.String()), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.0.cert_pem", strings.TrimSpace(fixtures.TestTlsDataSourceCertFromURL01)+"\n"), + + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.signature_algorithm", "SHA256-RSA"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.public_key_algorithm", "RSA"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.serial_number", "60512478256160404377639062250777657301"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.is_ca", "true"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.version", "3"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.issuer", "CN=Root CA,O=Test Org,L=Here"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.subject", "CN=Root CA,O=Test Org,L=Here"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.not_before", "2019-11-07T15:47:48Z"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.not_after", "2019-12-17T15:47:48Z"), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.sha1_fingerprint", "5829a9bcc57f317719c5c98d1f48d6c9957cb44e"), + tu.TestCheckPEMFormat("data.tls_certificate.test", "certificates.1.cert_pem", PreambleCertificate.String()), + r.TestCheckResourceAttr("data.tls_certificate.test", "certificates.1.cert_pem", strings.TrimSpace(fixtures.TestTlsDataSourceCertFromURL00)+"\n"), + ), + }, + }, + }) +} + func TestAccDataSourceCertificate_UpgradeFromVersion3_4_0(t *testing.T) { r.Test(t, r.TestCase{ Steps: []r.TestStep{