Add mutual_tls authentication plugin for HTTP-based sources#6916
Add mutual_tls authentication plugin for HTTP-based sources#6916divakarsingh wants to merge 1 commit into
Conversation
Add a new ArmeriaHttpAuthenticationProvider plugin called mutual_tls
that configures Armeria with ClientAuth.REQUIRE and a trust CA for
client certificate verification at the TLS handshake level.
Extends the ArmeriaHttpAuthenticationProvider interface with a
getTlsCustomizer() method so authentication plugins can configure
TLS-level settings. BaseHttpSource applies this during server setup.
This applies to all HTTP-based sources (http, opensearch_api,
otel_trace_source, otel_metrics_source, otel_logs_source) since they
all inherit from BaseHttpSource.
Configuration:
authentication:
mutual_tls:
ssl_trust_certificate_file: /path/to/ca.crt
Resolves opensearch-project#6889
Signed-off-by: Divakar Pratap Singh <divakar.p.singh@gmail.com>
srikanthpadakanti
left a comment
There was a problem hiding this comment.
Hello @divakarsingh Thank you for your contribution. Can you please look into these comments.
| new ByteArrayInputStream(certificate.getPrivateKey().getBytes(StandardCharsets.UTF_8) | ||
| ) | ||
| ); | ||
| authenticationProvider.getTlsCustomizer().ifPresent(sb::tlsCustomizer); |
There was a problem hiding this comment.
getTlsCustomizer is applied only inside if (sourceConfig.isSsl()); if user configures mutual_tls without ssl: true, server starts unauthenticated with no warning, silent fail-open
| @@ -0,0 +1,28 @@ | |||
| -----BEGIN PRIVATE KEY----- | |||
There was a problem hiding this comment.
Unencrypted private keys committed to repo. Test PEMs must be generated at runtime via BouncyCastle PEMParser, not committed.
| @@ -0,0 +1,28 @@ | |||
| -----BEGIN PRIVATE KEY----- | |||
There was a problem hiding this comment.
Unencrypted private keys committed to repo. Test PEMs must be generated at runtime via BouncyCastle PEMParser, not committed.
| @@ -0,0 +1,28 @@ | |||
| -----BEGIN PRIVATE KEY----- | |||
There was a problem hiding this comment.
Unencrypted private keys committed to repo. Test PEMs must be generated at runtime via BouncyCastle PEMParser, not committed.
| public class MutualTlsAuthenticationConfig { | ||
|
|
||
| @JsonProperty("ssl_trust_certificate_file") | ||
| @NotBlank(message = "ssl_trust_certificate_file is required for mutual_tls authentication") |
There was a problem hiding this comment.
Only @notblank validation. No check that the file exists, is readable, or parses as an X.509 CA cert. Failure surfaces as an SSL exception at server start instead of a clear config-time validation error.
| public class MutualTlsAuthenticationConfig { | ||
|
|
||
| @JsonProperty("ssl_trust_certificate_file") | ||
| @NotBlank(message = "ssl_trust_certificate_file is required for mutual_tls authentication") |
There was a problem hiding this comment.
only a file path is accepted. Inline PEM content (used elsewhere via http-client-common) is not supported. Inconsistent UX across auth configs
| public class MutualTlsAuthenticationConfig { | ||
|
|
||
| @JsonProperty("ssl_trust_certificate_file") | ||
| @NotBlank(message = "ssl_trust_certificate_file is required for mutual_tls authentication") |
There was a problem hiding this comment.
single trust cert file only. No list, no multiple CAs. Multi-tenant or staging-plus-prod deployments cannot use this as-is.
| @Override | ||
| public Optional<Consumer<SslContextBuilder>> getTlsCustomizer() { | ||
| return Optional.of(sslContextBuilder -> { | ||
| sslContextBuilder.clientAuth(ClientAuth.REQUIRE); |
There was a problem hiding this comment.
no CRL or OCSP wiring. mTLS without revocation does not survive a leaked client cert. At minimum, add a follow-up issue and document the gap.
| * Called during server setup when SSL is enabled. | ||
| * | ||
| * @return an optional consumer that configures the {@link SslContextBuilder} | ||
| */ |
There was a problem hiding this comment.
getTlsCustomizer returns Consumer<SslContextBuilder>, giving any plugin full mutation rights over the SslContext (server key, server cert, protocols). A misbehaving plugin can downgrade or break TLS. Narrow the contract (e.g., a small interface that only exposes trustManager and clientAuth setters).
| import java.util.Objects; | ||
| import java.util.Optional; | ||
| import java.util.function.Consumer; | ||
|
|
There was a problem hiding this comment.
No logging or metric on TLS handshake rejection. An operator cannot distinguish a network blip from a cert-rejection from a misconfigured client. Add a counter or a structured log emit on handshake failure
Description
Adds a
mutual_tlsauthentication plugin that enables mTLS client certificateauthentication on all HTTP-based sources. Clients must present a valid certificate
signed by the configured trust CA to connect.
This is implemented as an
ArmeriaHttpAuthenticationProviderplugin (consistent withhttp_basicandunauthenticated), with a newgetTlsCustomizer()method on theinterface for TLS-layer configuration.
Configuration example:
Works on all HTTP-based sources:
http,opensearch_api,otel_trace_source,otel_metrics_source,otel_logs_source.Issues Resolved
Resolves #6889
Check List