Skip to content

read cert from header when trusted proxy sets it#6287

Open
asifabashar wants to merge 1 commit into
opensearch-project:mainfrom
asifabashar:proxy_set_header_cert
Open

read cert from header when trusted proxy sets it#6287
asifabashar wants to merge 1 commit into
opensearch-project:mainfrom
asifabashar:proxy_set_header_cert

Conversation

@asifabashar

@asifabashar asifabashar commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Description

Where there a external load balancer/proxy that itself does mTLS authentication, it forwards the request to opensearch where client to opensearch is load balancer and original client cert is no longer performing client cert authentication with OpenSearch , it is the load balancer that is performing client authentication with opensearch cluster.

What solution would you like?
To preserve identity of the original client, we can have first opensearch do client authentication validation with external load balancer /proxy , during TLS handshake and then external load balancer/proxy can store the original client certificate in header as URL encoded value in header field x-client-cert (This is configurable by setting "plugins.security.ssl.http.clientauth_header_cert_name"). The external load balancer/proxy will connect to opensearch cluster and forward the request with original client cert in header so that opensearch cluster can assign original client's principle which is correct identity of the original client. The load balancer has to be trusted by the opensearch so that it can trust its header so load balancer certificate will be validated at every request by opensearch using its standard certficate based authentication and then will validate if the external load balancer certificate principle matches setting plugins.security.ssl.http.clientauth_header_cert_allowed_for_principle list of regex.

The feature will be controlled by flag settings "clientauth_header_cert_allowed_for_principle" where by default this feature will be disabled.

  • Category (Enhancement)

  • Why these changes are required?
    Some of the general purpose load balancers are allowing the actual cert to be placed in header, but those load balancers are not setting x-forwarded-for field with the principle as its dedicated for IP. So allowing opensearch to extract its desired field from the certificate allows both opensearch and load balancer to work with their own requirements and configuration but still work together. In this scenerio,load balancer will validate original client and but it does not have the role mapping or correct principle extraction logic, so it will just pass the cert as is, Opensearch then will know the request is from proxy from proxy(external load balancer) by validating client cert authentication of the load balancer/proxy,  so it will trust the request , but it should assume the actual client associated user that belongs to original client and not the load balancer , so it will then use certificate from header  to switch to that principle .

  • What is the old behavior before changes and new behavior after changes?
    By default the flag to read from header cert is false, so it does not change default behaviour.
    If user sets this flag plugins.security.ssl.http.clientauth_use_header_cert to true, then a header cert will be checked when plugins.security.ssl.http.clientauth_header_cert_allowed_for_principle setting has the principle regex list that matches proxy server (external load balancer) client cert principle matching .

Issues Resolved

[ #6268 ]

Is this a backport? If so, please add backport PR # and/or commits #, and remove backport-failed label from the original PR.

  • Not a backport
    Do these changes introduce new permission(s) to be displayed in the static dropdown on the front-end? If so, please open a draft PR in the security dashboards plugin and link the draft PR here
    -No new permission

Testing

[unit testing added]

Check List

  • [x ] New functionality includes testing
  • [ x] New functionality has been documented - if approved, I will add a documentation PR
  • New Roles/Permissions have a corresponding security dashboards plugin PR
  • API changes companion pull request created
  • [x ] Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Signed-off-by: Asif Bashar <asif.bashar@gmail.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

PR Code Analyzer ❗

AI-powered 'Code-Diff-Analyzer' found issues on commit 9eea16f.

PathLineSeverityDescription
src/main/java/org/opensearch/security/ssl/util/HeaderClientCertResolver.java67highThe certificate parsed from the HTTP header is never validated against the configured CA trust store. `factory.generateCertificate()` only deserializes the DER/PEM bytes into an X509Certificate object — it does not verify the signature chain, check revocation, or confirm the cert was issued by a trusted CA. Any allowed proxy principal (i.e., any connection whose TLS cert matches the allowlist) can present a completely self-signed or forged certificate in the header and have its principal accepted as the authenticated identity. A compromised or impersonated proxy principal therefore gives an attacker full control over which user they authenticate as.
src/main/java/org/opensearch/security/ssl/util/HeaderClientCertResolver.java44mediumThe feature introduces an authentication-override path driven by an untrusted HTTP header. Even though it is gated behind `SECURITY_SSL_HTTP_USE_HEADER_CERT=true` and an allowed-principal check, any misconfiguration (e.g., an overly broad wildcard in `SECURITY_SSL_HTTP_HEADER_CERT_ALLOWED_PROXY_PRINCIPLE`, or TLS termination that does not strip incoming headers before adding its own) allows a client to supply an arbitrary certificate identity and bypass the TLS handshake-based authentication entirely. The design fundamentally trusts user-controlled header data for authentication decisions.
src/main/java/org/opensearch/security/ssl/util/HeaderClientCertResolver.java43lowThe default header name `x-client-cert` is a well-known, predictable name. If a deployment enables the feature but the upstream proxy or ingress controller does not explicitly strip this header from external requests before appending its own validated value, an external attacker can inject an arbitrary certificate identity. There is no warning in the code or documentation that the operator must configure the ingress to sanitize this header.

The table above displays the top 10 most important findings.

Total: 3 | Critical: 0 | High: 1 | Medium: 1 | Low: 1


Pull Requests Author(s): Please update your Pull Request according to the report above.

Repository Maintainer(s): You can bypass diff analyzer by adding label skip-diff-analyzer after reviewing the changes carefully, then re-run failed actions. To re-enable the analyzer, remove the label, then re-run all actions.


⚠️ Note: The Code-Diff-Analyzer helps protect against potentially harmful code patterns. Please ensure you have thoroughly reviewed the changes beforehand.

Thanks.

@asifabashar

asifabashar commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

PR Code Analyzer ❗

AI-powered 'Code-Diff-Analyzer' found issues on commit 9eea16f.

PathLineSeverityDescription
src/main/java/org/opensearch/security/ssl/util/HeaderClientCertResolver.java67highThe certificate parsed from the HTTP header is never validated against the configured CA trust store. `factory.generateCertificate()` only deserializes the DER/PEM bytes into an X509Certificate object — it does not verify the signature chain, check revocation, or confirm the cert was issued by a trusted CA. Any allowed proxy principal (i.e., any connection whose TLS cert matches the allowlist) can present a completely self-signed or forged certificate in the header and have its principal accepted as the authenticated identity. A compromised or impersonated proxy principal therefore gives an attacker full control over which user they authenticate as.
src/main/java/org/opensearch/security/ssl/util/HeaderClientCertResolver.java44mediumThe feature introduces an authentication-override path driven by an untrusted HTTP header. Even though it is gated behind `SECURITY_SSL_HTTP_USE_HEADER_CERT=true` and an allowed-principal check, any misconfiguration (e.g., an overly broad wildcard in `SECURITY_SSL_HTTP_HEADER_CERT_ALLOWED_PROXY_PRINCIPLE`, or TLS termination that does not strip incoming headers before adding its own) allows a client to supply an arbitrary certificate identity and bypass the TLS handshake-based authentication entirely. The design fundamentally trusts user-controlled header data for authentication decisions.
src/main/java/org/opensearch/security/ssl/util/HeaderClientCertResolver.java43lowThe default header name `x-client-cert` is a well-known, predictable name. If a deployment enables the feature but the upstream proxy or ingress controller does not explicitly strip this header from external requests before appending its own validated value, an external attacker can inject an arbitrary certificate identity. There is no warning in the code or documentation that the operator must configure the ingress to sanitize this header.

The table above displays the top 10 most important findings.

Total: 3 | Critical: 0 | High: 1 | Medium: 1 | Low: 1


Pull Requests Author(s): Please update your Pull Request according to the report above.

Repository Maintainer(s): You can bypass diff analyzer by adding label skip-diff-analyzer after reviewing the changes carefully, then re-run failed actions. To re-enable the analyzer, remove the label, then re-run all actions.


⚠️ Note: The Code-Diff-Analyzer helps protect against potentially harmful code patterns. Please ensure you have thoroughly reviewed the changes beforehand.

Thanks.

The ssl validation for client happens at the load balancers/proxy servers , the opensearch still validates load balancers/proxy certificates and trust that load balancer did correct validation. So it is dependent on load balancer/proxy to do original client validation.

@asifabashar

Copy link
Copy Markdown
Contributor Author

@cwperks please review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant