Skip to content

[BUG] incorrect CA certificate path when using generate: true with a custom caSecret for HTTP TLS with operator 3.0.0-alpha #1279

@arnitolog

Description

@arnitolog

What is the bug?

When configuring the OpenSearch Operator with http TLS enabled, generate: true, and a specific caSecret, the operator incorrectly configures the plugins.security.ssl.http.pemtrustedcas_filepath to point to a non-existent directory tls-http-ca/ca.crt.

When generate is set to true, the operator generates a certificate signed by the provided CA and stores it in a new secret (e.g., cluster-name-http-cert). This generated secret contains ca.crt, tls.crt, and tls.key and is mounted at /usr/share/opensearch/config/tls-http.

generated secret:

Image

volumeMounts:

Image

But, it looks like an operator skips mounting CA cert as a separate folder, because of generate: true
https://github.com/opensearch-project/opensearch-k8s-operator/blob/main/opensearch-operator/pkg/reconcilers/tls.go#L619

if tlsConfig.Generate {
...
}
else {
...
		// Implement new mounting logic based on CaSecret.Name configuration
		switch name := tlsConfig.CaSecret.Name; name {
		case "":
			// If CaSecret.Name is empty, mount Secret.Name as a directory
			mountFolder("http", "certs", tlsConfig.Secret.Name, r.reconcilerContext)
		case tlsConfig.Secret.Name:
			// If CaSecret.Name is same as Secret.Name, mount only Secret.Name as a directory
			mountFolder("http", "certs", tlsConfig.Secret.Name, r.reconcilerContext)
		default:
			// If CaSecret.Name is different from Secret.Name, mount both secrets as directories
			// Mount Secret.Name as tls-http/
			mountFolder("http", "certs", tlsConfig.Secret.Name, r.reconcilerContext)
			// Mount CaSecret.Name as tls-http-ca/
			mountFolder("http", "ca", tlsConfig.CaSecret.Name, r.reconcilerContext)
}

and then where it uses it as tls-http-ca/ca.crt:
https://github.com/opensearch-project/opensearch-k8s-operator/blob/main/opensearch-operator/pkg/reconcilers/tls.go#L724

	if tlsConfig.CaSecret.Name == "" || tlsConfig.CaSecret.Name == tlsConfig.Secret.Name {
		// Single secret mounted as directory
		r.reconcilerContext.AddConfig("plugins.security.ssl.http.pemcert_filepath", fmt.Sprintf("tls-http/%s", corev1.TLSCertKey))
		r.reconcilerContext.AddConfig("plugins.security.ssl.http.pemkey_filepath", fmt.Sprintf("tls-http/%s", corev1.TLSPrivateKeyKey))
		r.reconcilerContext.AddConfig("plugins.security.ssl.http.pemtrustedcas_filepath", fmt.Sprintf("tls-http/%s", CaCertKey))
	} else {
		// Separate secrets mounted as directories
		r.reconcilerContext.AddConfig("plugins.security.ssl.http.pemcert_filepath", fmt.Sprintf("tls-http/%s", corev1.TLSCertKey))
		r.reconcilerContext.AddConfig("plugins.security.ssl.http.pemkey_filepath", fmt.Sprintf("tls-http/%s", corev1.TLSPrivateKeyKey))
		r.reconcilerContext.AddConfig("plugins.security.ssl.http.pemtrustedcas_filepath", fmt.Sprintf("tls-http-ca/%s", CaCertKey))
	}

How can one reproduce the bug?

Deploy an OpenSearchCluster with the following TLS configuration:

tls:
  http:
    enabled: true
    generate: true
    caSecret:
      name: opensearch-ca # Specify custom CA

The OpenSearch Pods fail to start with the following error:

java.lang.IllegalStateException: failed to load plugin class [org.opensearch.security.OpenSearchSecurityPlugin]
Likely root cause: OpenSearchException[Unable to read the file tls-http-ca/ca.crt. Please make sure this files exists and is readable regarding to permissions]

What is the expected behavior?

probably it makes sense to mount and use ca.crt from the generated secret in case genanrate:true and caSecret is not null. In this case line https://github.com/opensearch-project/opensearch-k8s-operator/blob/main/opensearch-operator/pkg/reconcilers/tls.go#L715 just needs to be changed to:

	if tlsConfig.Generate || tlsConfig.CaSecret.Name == "" || tlsConfig.CaSecret.Name == tlsConfig.Secret.Name {

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    🆕 New

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions