diff --git a/internal/pkg/cert/tool/cert_parser.go b/internal/pkg/cert/tool/cert_parser.go index 5cf789b..c4b70fa 100755 --- a/internal/pkg/cert/tool/cert_parser.go +++ b/internal/pkg/cert/tool/cert_parser.go @@ -156,15 +156,22 @@ } if block.Type == "CERTIFICATE" { - // x509.ParseCertificates handles both single and multiple certificates in the block bytes - parsedCerts, err := x509.ParseCertificates(block.Bytes) + // x509.ParseCertificate (singular) usually parses the first cert in the DER data. + // x509.ParseCertificates (plural) parses one or more certs concatenated in DER format. + // However, pem.Decode returns a block containing ONE encoded object. + // So block.Bytes contains usually just one certificate. + parsedCert, err := x509.ParseCertificate(block.Bytes) if err != nil { - // Skip malformed blocks but continue - fmt.Printf("Warning: skipping malformed certificate (%v)\n", err) - data = rest - continue + // Fallback to ParseCertificates if for some reason multiple are in one block (rare for PEM) + parsedCerts, err2 := x509.ParseCertificates(block.Bytes) + if err2 != nil { + fmt.Printf("Warning: skipping malformed certificate (%v)\n", err) + } else { + certs = append(certs, parsedCerts...) + } + } else { + certs = append(certs, parsedCert) } - certs = append(certs, parsedCerts...) } data = rest diff --git a/static/secrets.js b/static/secrets.js index c69b4d8..acffb93 100755 --- a/static/secrets.js +++ b/static/secrets.js @@ -164,10 +164,35 @@ // Get the full secret config, which should contain the 'certificate_pem' const secretConfig = configStore.secrets[secretName]; // Drill down to the PEM string - const certPem = secretConfig?.Type?.TlsCertificate?.certificate_chain?.Specifier?.InlineString + const certPem = secretConfig?.Type?.TlsCertificate?.certificate_chain?.Specifier?.InlineString; if (!certPem) { + // Fallback: Check if the structure matches the user provided format (snake_case/camelCase mix) + // sometimes the Go Control Plane returns slightly different JSON structure depending on version/marshalling + console.warn("Standard path to certificate_chain failed. Trying alternatives."); + } + + // Attempt to locate the inline string recursively or via known alternative paths if the above failed + // For now, let's stick to the path we see in the snippet provided by the user. + // The snippet shows: tlsCertificate -> certificateChain -> inlineString + // But the code uses: Type -> TlsCertificate -> certificate_chain -> Specifier -> InlineString + + // Let's print the secretConfig to console to debug if we were in a browser, but here we can only guess. + // However, looking at the snippet: + // tlsCertificate: + // certificateChain: + // inlineString: | + + // It seems the keys might be camelCase in the JSON response from the backend list-secrets? + // Let's try to handle both snake_case and camelCase. + + const tlsCert = secretConfig?.Type?.TlsCertificate || secretConfig?.tlsCertificate || secretConfig?.TlsCertificate; + const certChainObj = tlsCert?.certificate_chain || tlsCert?.certificateChain; + const certPemFinal = certChainObj?.Specifier?.InlineString || certChainObj?.inlineString || certChainObj?.inline_string; + + if (!certPemFinal) { alert(`Could not find certificate PEM in the configuration for secret: ${secretName}`); + console.error("Secret Config Structure:", JSON.stringify(secretConfig, null, 2)); return; } @@ -175,7 +200,7 @@ modal.style.display = 'block'; try { - const details = await getCertificateDetails(certPem); + const details = await getCertificateDetails(certPemFinal); // Display the pretty-printed JSON response content.innerHTML = `