From eed3e5deaf3fd13c353361e45420735a93d0f3d0 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Wed, 13 Jul 2022 16:53:43 +0200 Subject: Return granted capabilities from PeerAuthorizer Introduce new ConnectionAuthContext as replacement for AuthorizationResult/SecurityContext. --- .../rpc/security/MultiTenantRpcAuthorizer.java | 8 ++-- .../rpc/security/MultiTenantRpcAuthorizerTest.java | 10 +++-- jrt/src/com/yahoo/jrt/Connection.java | 6 ++- jrt/src/com/yahoo/jrt/CryptoSocket.java | 6 ++- jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java | 6 ++- jrt/src/com/yahoo/jrt/SecurityContext.java | 24 ------------ jrt/src/com/yahoo/jrt/Target.java | 6 ++- jrt/src/com/yahoo/jrt/TlsCryptoSocket.java | 25 +++--------- jrt/tests/com/yahoo/jrt/EchoTest.java | 27 ++++++------- .../security/tls/authz/AuthorizationResult.java | 45 ---------------------- .../security/tls/authz/ConnectionAuthContext.java | 23 +++++++++++ .../yahoo/security/tls/authz/PeerAuthorizer.java | 11 ++++-- .../tls/authz/PeerAuthorizerTrustManager.java | 10 ++--- .../yahoo/security/tls/policy/CapabilitySet.java | 10 +++++ .../security/tls/authz/PeerAuthorizerTest.java | 39 ++++++++++++++++--- 15 files changed, 125 insertions(+), 131 deletions(-) delete mode 100644 jrt/src/com/yahoo/jrt/SecurityContext.java delete mode 100644 security-utils/src/main/java/com/yahoo/security/tls/authz/AuthorizationResult.java create mode 100644 security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java index f5b570fed40..6ca39a25d9c 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java @@ -10,9 +10,9 @@ import com.yahoo.config.provision.security.NodeIdentifier; import com.yahoo.config.provision.security.NodeIdentifierException; import com.yahoo.config.provision.security.NodeIdentity; import com.yahoo.jrt.Request; -import com.yahoo.jrt.SecurityContext; import com.yahoo.security.tls.MixedMode; import com.yahoo.security.tls.TransportSecurityUtils; +import com.yahoo.security.tls.authz.ConnectionAuthContext; import com.yahoo.vespa.config.ConfigKey; import com.yahoo.vespa.config.protocol.JRTServerConfigRequestV3; import com.yahoo.vespa.config.server.RequestHandler; @@ -166,14 +166,14 @@ public class MultiTenantRpcAuthorizer implements RpcAuthorizer { // TODO Make peer identity mandatory once TLS mixed mode is removed private Optional getPeerIdentity(Request request) { - Optional securityContext = request.target().getSecurityContext(); - if (securityContext.isEmpty()) { + Optional authCtx = request.target().getConnectionAuthContext(); + if (authCtx.isEmpty()) { if (TransportSecurityUtils.getInsecureMixedMode() == MixedMode.DISABLED) { throw new IllegalStateException("Security context missing"); // security context should always be present } return Optional.empty(); // client choose to communicate over insecure channel } - List certChain = securityContext.get().peerCertificateChain(); + List certChain = authCtx.get().peerCertificate(); if (certChain.isEmpty()) { throw new IllegalStateException("Client authentication is not enforced!"); // clients should be required to authenticate when TLS is enabled } diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java index 2650b23a38e..7a2e0f00433 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java @@ -11,7 +11,6 @@ import com.yahoo.config.provision.security.NodeIdentifier; import com.yahoo.config.provision.security.NodeIdentifierException; import com.yahoo.config.provision.security.NodeIdentity; import com.yahoo.jrt.Request; -import com.yahoo.jrt.SecurityContext; import com.yahoo.jrt.StringValue; import com.yahoo.jrt.Target; import com.yahoo.jrt.Values; @@ -19,6 +18,8 @@ import com.yahoo.security.KeyAlgorithm; import com.yahoo.security.KeyUtils; import com.yahoo.security.SignatureAlgorithm; import com.yahoo.security.X509CertificateBuilder; +import com.yahoo.security.tls.authz.ConnectionAuthContext; +import com.yahoo.security.tls.policy.CapabilitySet; import com.yahoo.slime.Cursor; import com.yahoo.slime.JsonFormat; import com.yahoo.slime.Slime; @@ -40,6 +41,7 @@ import java.time.Instant; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.TreeSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -248,10 +250,10 @@ public class MultiTenantRpcAuthorizerTest { } private static Request mockJrtRpcRequest(String payload) { - SecurityContext securityContext = mock(SecurityContext.class); - when(securityContext.peerCertificateChain()).thenReturn(PEER_CERTIFICATE_CHAIN); + ConnectionAuthContext authContext = + new ConnectionAuthContext(PEER_CERTIFICATE_CHAIN, CapabilitySet.none(), new TreeSet<>()); Target target = mock(Target.class); - when(target.getSecurityContext()).thenReturn(Optional.of(securityContext)); + when(target.getConnectionAuthContext()).thenReturn(Optional.of(authContext)); Request request = mock(Request.class); when(request.target()).thenReturn(target); Values values = new Values(); diff --git a/jrt/src/com/yahoo/jrt/Connection.java b/jrt/src/com/yahoo/jrt/Connection.java index 00aceb7e352..644e2ef4ff3 100644 --- a/jrt/src/com/yahoo/jrt/Connection.java +++ b/jrt/src/com/yahoo/jrt/Connection.java @@ -1,6 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jrt; +import com.yahoo.security.tls.authz.ConnectionAuthContext; + import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; @@ -436,9 +438,9 @@ class Connection extends Target { } @Override - public Optional getSecurityContext() { + public Optional getConnectionAuthContext() { return Optional.ofNullable(socket) - .flatMap(CryptoSocket::getSecurityContext); + .flatMap(CryptoSocket::getConnectionAuthContext); } public boolean isClient() { diff --git a/jrt/src/com/yahoo/jrt/CryptoSocket.java b/jrt/src/com/yahoo/jrt/CryptoSocket.java index 78308b76624..aac91362405 100644 --- a/jrt/src/com/yahoo/jrt/CryptoSocket.java +++ b/jrt/src/com/yahoo/jrt/CryptoSocket.java @@ -2,6 +2,8 @@ package com.yahoo.jrt; +import com.yahoo.security.tls.authz.ConnectionAuthContext; + import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; @@ -103,10 +105,10 @@ public interface CryptoSocket { public void dropEmptyBuffers(); /** - * Returns the security context for the current connection (given handshake completed), + * Returns the auth context for the current connection (given handshake completed), * or empty if the current connection is not secure. */ - default public Optional getSecurityContext() { + default public Optional getConnectionAuthContext() { return Optional.empty(); } } diff --git a/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java b/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java index df01f4f2fa7..42442289cd1 100644 --- a/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java +++ b/jrt/src/com/yahoo/jrt/MaybeTlsCryptoSocket.java @@ -1,6 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jrt; +import com.yahoo.security.tls.authz.ConnectionAuthContext; + import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; @@ -130,5 +132,7 @@ public class MaybeTlsCryptoSocket implements CryptoSocket { @Override public int write(ByteBuffer src) throws IOException { return socket.write(src); } @Override public FlushResult flush() throws IOException { return socket.flush(); } @Override public void dropEmptyBuffers() { socket.dropEmptyBuffers(); } - @Override public Optional getSecurityContext() { return Optional.ofNullable(socket).flatMap(CryptoSocket::getSecurityContext); } + @Override public Optional getConnectionAuthContext() { + return Optional.ofNullable(socket).flatMap(CryptoSocket::getConnectionAuthContext); + } } diff --git a/jrt/src/com/yahoo/jrt/SecurityContext.java b/jrt/src/com/yahoo/jrt/SecurityContext.java deleted file mode 100644 index 4eef99cb93f..00000000000 --- a/jrt/src/com/yahoo/jrt/SecurityContext.java +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.jrt; - -import java.security.cert.X509Certificate; -import java.util.List; - -/** - * @author bjorncs - */ -public class SecurityContext { - - private final List peerCertificateChain; - - public SecurityContext(List peerCertificateChain) { - this.peerCertificateChain = peerCertificateChain; - } - - /** - * @return the peer certificate chain if the peer was authenticated, empty list if not. - */ - public List peerCertificateChain() { - return peerCertificateChain; - } -} diff --git a/jrt/src/com/yahoo/jrt/Target.java b/jrt/src/com/yahoo/jrt/Target.java index a59aa341fe0..239a71f53b3 100644 --- a/jrt/src/com/yahoo/jrt/Target.java +++ b/jrt/src/com/yahoo/jrt/Target.java @@ -1,6 +1,8 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jrt; +import com.yahoo.security.tls.authz.ConnectionAuthContext; + import java.util.Optional; /** @@ -69,9 +71,9 @@ public abstract class Target { public Exception getConnectionLostReason() { return null; } /** - * Returns the security context associated with this target, or empty if no connection or is insecure. + * Returns the connection auth context associated with this target, or empty if no connection or is insecure. */ - public abstract Optional getSecurityContext(); + public abstract Optional getConnectionAuthContext(); /** * Check if this target represents the client side of a diff --git a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java index a899938dd45..40cb7c3938a 100644 --- a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java +++ b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java @@ -1,7 +1,7 @@ // Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.jrt; -import com.yahoo.security.tls.authz.AuthorizationResult; +import com.yahoo.security.tls.authz.ConnectionAuthContext; import com.yahoo.security.tls.authz.PeerAuthorizerTrustManager; import javax.net.ssl.SSLEngine; @@ -9,19 +9,14 @@ import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; -import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLSession; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.nio.channels.SocketChannel; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.List; import java.util.Optional; import java.util.logging.Logger; -import static java.util.stream.Collectors.toList; import static javax.net.ssl.SSLEngineResult.Status; /** @@ -46,7 +41,7 @@ public class TlsCryptoSocket implements CryptoSocket { private int sessionApplicationBufferSize; private ByteBuffer handshakeDummyBuffer; private HandshakeState handshakeState; - private AuthorizationResult authorizationResult; + private ConnectionAuthContext authorizationResult; public TlsCryptoSocket(SocketChannel channel, SSLEngine sslEngine) { this.channel = channel; @@ -224,19 +219,9 @@ public class TlsCryptoSocket implements CryptoSocket { } @Override - public Optional getSecurityContext() { - try { - if (handshakeState != HandshakeState.COMPLETED) { - return Optional.empty(); - } - List peerCertificateChain = - Arrays.stream(sslEngine.getSession().getPeerCertificates()) - .map(X509Certificate.class::cast) - .collect(toList()); - return Optional.of(new SecurityContext(peerCertificateChain)); - } catch (SSLPeerUnverifiedException e) { // unverified peer: non-certificate based ciphers or peer did not provide a certificate - return Optional.of(new SecurityContext(List.of())); // secure connection, but peer does not have a certificate chain. - } + public Optional getConnectionAuthContext() { + if (handshakeState != HandshakeState.COMPLETED) return Optional.empty(); + return Optional.ofNullable(authorizationResult); } private boolean handshakeWrap() throws IOException { diff --git a/jrt/tests/com/yahoo/jrt/EchoTest.java b/jrt/tests/com/yahoo/jrt/EchoTest.java index 26d4315fad6..7213068c0f9 100644 --- a/jrt/tests/com/yahoo/jrt/EchoTest.java +++ b/jrt/tests/com/yahoo/jrt/EchoTest.java @@ -2,6 +2,7 @@ package com.yahoo.jrt; +import com.yahoo.security.tls.authz.ConnectionAuthContext; import org.junit.After; import org.junit.Before; import org.junit.runner.RunWith; @@ -28,19 +29,19 @@ public class EchoTest { Supervisor client; Target target; Values refValues; - SecurityContext securityContext; + ConnectionAuthContext connAuthCtx; private interface MetricsAssertions { void assertMetrics(TransportMetrics.Snapshot snapshot) throws AssertionError; } - private interface SecurityContextAssertion { - void assertSecurityContext(SecurityContext securityContext) throws AssertionError; + private interface ConnectionAuthContextAssertion { + void assertConnectionAuthContext(ConnectionAuthContext authContext) throws AssertionError; } @Parameter(value = 0) public CryptoEngine crypto; @Parameter(value = 1) public MetricsAssertions metricsAssertions; - @Parameter(value = 2) public SecurityContextAssertion securityContextAssertion; + @Parameter(value = 2) public ConnectionAuthContextAssertion connAuthCtxAssertion; @Parameters(name = "{0}") public static Object[] engines() { @@ -62,8 +63,8 @@ public class EchoTest { assertEquals(1, metrics.serverTlsConnectionsEstablished()); assertEquals(1, metrics.clientTlsConnectionsEstablished()); }, - (SecurityContextAssertion) context -> { - List chain = context.peerCertificateChain(); + (ConnectionAuthContextAssertion) context -> { + List chain = context.peerCertificate(); assertEquals(1, chain.size()); assertEquals(CryptoUtils.certificate, chain.get(0)); }}, @@ -80,8 +81,8 @@ public class EchoTest { assertEquals(1, metrics.serverTlsConnectionsEstablished()); assertEquals(1, metrics.clientTlsConnectionsEstablished()); }, - (SecurityContextAssertion) context -> { - List chain = context.peerCertificateChain(); + (ConnectionAuthContextAssertion) context -> { + List chain = context.peerCertificate(); assertEquals(1, chain.size()); assertEquals(CryptoUtils.certificate, chain.get(0)); }}}; @@ -146,7 +147,7 @@ public class EchoTest { for (int i = 0; i < p.size(); i++) { r.add(p.get(i)); } - securityContext = req.target().getSecurityContext().orElse(null); + connAuthCtx = req.target().getConnectionAuthContext().orElse(null); } @org.junit.Test @@ -164,11 +165,11 @@ public class EchoTest { if (metricsAssertions != null) { metricsAssertions.assertMetrics(metrics.snapshot().changesSince(startSnapshot)); } - if (securityContextAssertion != null) { - assertNotNull(securityContext); - securityContextAssertion.assertSecurityContext(securityContext); + if (connAuthCtxAssertion != null) { + assertNotNull(connAuthCtx); + connAuthCtxAssertion.assertConnectionAuthContext(connAuthCtx); } else { - assertNull(securityContext); + assertNull(connAuthCtx); } } } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/AuthorizationResult.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/AuthorizationResult.java deleted file mode 100644 index 6fa97e30d63..00000000000 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/AuthorizationResult.java +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.security.tls.authz; - -import java.util.Collections; -import java.util.Objects; -import java.util.Set; - -/** - * @author bjorncs - */ -public class AuthorizationResult { - private final Set matchedPolicies; - - public AuthorizationResult(Set matchedPolicies) { - this.matchedPolicies = Collections.unmodifiableSet(matchedPolicies); - } - - public Set matchedPolicies() { - return matchedPolicies; - } - - public boolean succeeded() { - return matchedPolicies.size() > 0; - } - - @Override - public String toString() { - return "AuthorizationResult{" + - ", matchedPolicies=" + matchedPolicies + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - AuthorizationResult that = (AuthorizationResult) o; - return Objects.equals(matchedPolicies, that.matchedPolicies); - } - - @Override - public int hashCode() { - return Objects.hash(matchedPolicies); - } -} diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java new file mode 100644 index 00000000000..a5fb51da763 --- /dev/null +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java @@ -0,0 +1,23 @@ +package com.yahoo.security.tls.authz; + +import com.yahoo.security.tls.policy.CapabilitySet; + +import java.security.cert.X509Certificate; +import java.util.List; +import java.util.SortedSet; +import java.util.TreeSet; + +/** + * @author bjorncs + */ +public record ConnectionAuthContext(List peerCertificate, + CapabilitySet capabilities, + SortedSet matchedPolicies) { + + public ConnectionAuthContext { + matchedPolicies = new TreeSet<>(matchedPolicies); + } + + public boolean succeeded() { return matchedPolicies.size() > 0; } + +} diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java index 8c4e87c1de2..353f704b136 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java @@ -4,6 +4,7 @@ package com.yahoo.security.tls.authz; import com.yahoo.security.SubjectAlternativeName; import com.yahoo.security.X509CertificateUtils; import com.yahoo.security.tls.policy.AuthorizedPeers; +import com.yahoo.security.tls.policy.CapabilitySet; import com.yahoo.security.tls.policy.PeerPolicy; import com.yahoo.security.tls.policy.RequiredPeerCredential; @@ -12,6 +13,8 @@ import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.logging.Logger; import static com.yahoo.security.SubjectAlternativeName.Type.DNS_NAME; @@ -34,17 +37,19 @@ public class PeerAuthorizer { this.authorizedPeers = authorizedPeers; } - public AuthorizationResult authorizePeer(X509Certificate peerCertificate) { - Set matchedPolicies = new HashSet<>(); + public ConnectionAuthContext authorizePeer(X509Certificate peerCertificate) { + SortedSet matchedPolicies = new TreeSet<>(); + Set grantedCapabilities = new HashSet<>(); String cn = getCommonName(peerCertificate).orElse(null); List sans = getSubjectAlternativeNames(peerCertificate); log.fine(() -> String.format("Subject info from x509 certificate: CN=[%s], 'SAN=%s", cn, sans)); for (PeerPolicy peerPolicy : authorizedPeers.peerPolicies()) { if (matchesPolicy(peerPolicy, cn, sans)) { matchedPolicies.add(peerPolicy.policyName()); + grantedCapabilities.add(peerPolicy.capabilities()); } } - return new AuthorizationResult(matchedPolicies); + return new ConnectionAuthContext(List.of(peerCertificate), CapabilitySet.unionOf(grantedCapabilities), matchedPolicies); } private static boolean matchesPolicy(PeerPolicy peerPolicy, String cn, List sans) { diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java index e8d558205c4..925e21c63ff 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java @@ -26,7 +26,7 @@ import java.util.logging.Logger; // Note: Implementation assumes that provided X509ExtendedTrustManager will throw IllegalArgumentException when chain is empty or null public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { - public static final String HANDSHAKE_SESSION_AUTHZ_RESULT_PROPERTY = "vespa.tls.authorization.result"; + public static final String HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY = "vespa.tls.auth.ctx"; private static final Logger log = Logger.getLogger(PeerAuthorizerTrustManager.class.getName()); @@ -98,18 +98,18 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { /** * Note: The authorization result is only available during handshake. The underlying handshake session is removed once handshake is complete. */ - public static Optional getAuthorizationResult(SSLEngine sslEngine) { + public static Optional getAuthorizationResult(SSLEngine sslEngine) { return Optional.ofNullable(sslEngine.getHandshakeSession()) - .flatMap(session -> Optional.ofNullable((AuthorizationResult) session.getValue(HANDSHAKE_SESSION_AUTHZ_RESULT_PROPERTY))); + .flatMap(session -> Optional.ofNullable((ConnectionAuthContext) session.getValue(HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY))); } private void authorizePeer(X509Certificate certificate, String authType, boolean isVerifyingClient, SSLEngine sslEngine) throws CertificateException { if (mode == AuthorizationMode.DISABLE) return; log.fine(() -> "Verifying certificate: " + createInfoString(certificate, authType, isVerifyingClient)); - AuthorizationResult result = authorizer.authorizePeer(certificate); + ConnectionAuthContext result = authorizer.authorizePeer(certificate); if (sslEngine != null) { // getHandshakeSession() will never return null in this context - sslEngine.getHandshakeSession().putValue(HANDSHAKE_SESSION_AUTHZ_RESULT_PROPERTY, result); + sslEngine.getHandshakeSession().putValue(HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY, result); } if (result.succeeded()) { log.fine(() -> String.format("Verification result: %s", result)); diff --git a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java index 44ff1eedfb0..46a07972fc3 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java @@ -3,10 +3,12 @@ package com.yahoo.security.tls.policy; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.stream.Collectors; @@ -56,6 +58,12 @@ public class CapabilitySet { return new CapabilitySet(caps); } + public static CapabilitySet unionOf(Collection capSets) { + EnumSet union = EnumSet.noneOf(Capability.class); + capSets.forEach(cs -> union.addAll(cs.caps)); + return new CapabilitySet(union); + } + public static CapabilitySet from(EnumSet caps) { return new CapabilitySet(EnumSet.copyOf(caps)); } public static CapabilitySet from(Collection caps) { return new CapabilitySet(EnumSet.copyOf(caps)); } public static CapabilitySet from(Capability... caps) { return new CapabilitySet(EnumSet.copyOf(List.of(caps))); } @@ -68,6 +76,8 @@ public class CapabilitySet { return caps.stream().map(Capability::asString).collect(Collectors.toCollection(TreeSet::new)); } + public Set asSet() { return Collections.unmodifiableSet(caps); } + @Override public String toString() { return "CapabilitySet{" + diff --git a/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java index 5a4ae1f4ff6..a2f27ba42bc 100644 --- a/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java +++ b/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java @@ -6,6 +6,8 @@ import com.yahoo.security.KeyUtils; import com.yahoo.security.SubjectAlternativeName.Type; import com.yahoo.security.X509CertificateBuilder; import com.yahoo.security.tls.policy.AuthorizedPeers; +import com.yahoo.security.tls.policy.Capability; +import com.yahoo.security.tls.policy.CapabilitySet; import com.yahoo.security.tls.policy.PeerPolicy; import com.yahoo.security.tls.policy.RequiredPeerCredential; import com.yahoo.security.tls.policy.RequiredPeerCredential.Field; @@ -19,6 +21,8 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.List; +import java.util.Optional; +import java.util.Set; import static com.yahoo.security.SignatureAlgorithm.SHA256_WITH_ECDSA; import static com.yahoo.security.tls.policy.RequiredPeerCredential.Field.CN; @@ -46,7 +50,7 @@ public class PeerAuthorizerTest { RequiredPeerCredential sanRequirement = createRequiredCredential(SAN_DNS, "*.matching.san"); PeerAuthorizer authorizer = createPeerAuthorizer(createPolicy(POLICY_1, cnRequirement, sanRequirement)); - AuthorizationResult result = authorizer.authorizePeer(createCertificate("foo.matching.cn", asList("foo.matching.san", "foo.invalid.san"), emptyList())); + ConnectionAuthContext result = authorizer.authorizePeer(createCertificate("foo.matching.cn", asList("foo.matching.san", "foo.invalid.san"), emptyList())); assertAuthorized(result); assertThat(result.matchedPolicies()).containsOnly(POLICY_1); @@ -64,7 +68,7 @@ public class PeerAuthorizerTest { createPolicy(POLICY_1, cnRequirement, sanRequirement), createPolicy(POLICY_2, cnRequirement, sanRequirement)); - AuthorizationResult result = peerAuthorizer + ConnectionAuthContext result = peerAuthorizer .authorizePeer(createCertificate("foo.matching.cn", singletonList("foo.matching.san"), emptyList())); assertAuthorized(result); assertThat(result.matchedPolicies()).containsOnly(POLICY_1, POLICY_2); @@ -76,7 +80,7 @@ public class PeerAuthorizerTest { createPolicy(POLICY_1, createRequiredCredential(CN, "*.matching.cn")), createPolicy(POLICY_2, createRequiredCredential(SAN_DNS, "*.matching.san"))); - AuthorizationResult result = peerAuthorizer.authorizePeer(createCertificate("foo.invalid.cn", singletonList("foo.matching.san"), emptyList())); + ConnectionAuthContext result = peerAuthorizer.authorizePeer(createCertificate("foo.invalid.cn", singletonList("foo.matching.san"), emptyList())); assertAuthorized(result); assertThat(result.matchedPolicies()).containsOnly(POLICY_2); } @@ -101,13 +105,28 @@ public class PeerAuthorizerTest { RequiredPeerCredential sanUriRequirement = createRequiredCredential(SAN_URI, "myscheme://my/*/uri"); PeerAuthorizer authorizer = createPeerAuthorizer(createPolicy(POLICY_1, cnRequirement, sanUriRequirement)); - AuthorizationResult result = authorizer.authorizePeer(createCertificate("foo.matching.cn", singletonList("foo.irrelevant.san"), singletonList("myscheme://my/matching/uri"))); + ConnectionAuthContext result = authorizer.authorizePeer(createCertificate("foo.matching.cn", singletonList("foo.irrelevant.san"), singletonList("myscheme://my/matching/uri"))); assertAuthorized(result); assertThat(result.matchedPolicies()).containsOnly(POLICY_1); assertUnauthorized(authorizer.authorizePeer(createCertificate("foo.matching.cn", emptyList(), singletonList("myscheme://my/nonmatching/url")))); } + @Test + public void auth_context_contains_union_of_granted_capabilities_from_policies() { + RequiredPeerCredential cnRequirement = createRequiredCredential(CN, "*.matching.cn"); + RequiredPeerCredential sanRequirement = createRequiredCredential(SAN_DNS, "*.matching.san"); + + PeerAuthorizer peerAuthorizer = createPeerAuthorizer( + createPolicy(POLICY_1, List.of(Capability.SLOBROK__API, Capability.CONTENT__DOCUMENT_API), List.of(cnRequirement)), + createPolicy(POLICY_2, List.of(Capability.SLOBROK__API, Capability.CONTENT__SEARCH_API), List.of(sanRequirement))); + + var result = peerAuthorizer + .authorizePeer(createCertificate("foo.matching.cn", List.of("foo.matching.san"), List.of())); + assertAuthorized(result); + assertCapabiltiesGranted(result, Set.of(Capability.SLOBROK__API, Capability.CONTENT__DOCUMENT_API, Capability.CONTENT__SEARCH_API)); + } + private static X509Certificate createCertificate(String subjectCn, List sanDns, List sanUri) { X509CertificateBuilder builder = X509CertificateBuilder.fromKeypair( @@ -134,12 +153,20 @@ public class PeerAuthorizerTest { return new PeerPolicy(name, asList(requiredCredentials)); } - private static void assertAuthorized(AuthorizationResult result) { + private static PeerPolicy createPolicy(String name, List caps, List creds) { + return new PeerPolicy(name, Optional.empty(), CapabilitySet.from(caps), creds); + } + + private static void assertAuthorized(ConnectionAuthContext result) { assertTrue(result.succeeded()); } - private static void assertUnauthorized(AuthorizationResult result) { + private static void assertUnauthorized(ConnectionAuthContext result) { assertFalse(result.succeeded()); } + private static void assertCapabiltiesGranted(ConnectionAuthContext ctx, Set expected) { + assertThat(ctx.capabilities().asSet()).containsOnly(expected.toArray(new Capability[0])); + } + } -- cgit v1.2.3 From e69c68a2c4b9b8f8d556f376c8f023f602a95eff Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Wed, 13 Jul 2022 17:21:22 +0200 Subject: Include full certificate chain in auth context --- .../rpc/security/MultiTenantRpcAuthorizer.java | 2 +- jrt/tests/com/yahoo/jrt/EchoTest.java | 4 ++-- .../security/tls/authz/ConnectionAuthContext.java | 7 ++++++- .../yahoo/security/tls/authz/PeerAuthorizer.java | 12 ++++++++---- .../tls/authz/PeerAuthorizerTrustManager.java | 22 ++++++++++++---------- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java index 6ca39a25d9c..288d064f150 100644 --- a/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java +++ b/configserver/src/main/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizer.java @@ -173,7 +173,7 @@ public class MultiTenantRpcAuthorizer implements RpcAuthorizer { } return Optional.empty(); // client choose to communicate over insecure channel } - List certChain = authCtx.get().peerCertificate(); + List certChain = authCtx.get().peerCertificateChain(); if (certChain.isEmpty()) { throw new IllegalStateException("Client authentication is not enforced!"); // clients should be required to authenticate when TLS is enabled } diff --git a/jrt/tests/com/yahoo/jrt/EchoTest.java b/jrt/tests/com/yahoo/jrt/EchoTest.java index 7213068c0f9..e6243eaf4da 100644 --- a/jrt/tests/com/yahoo/jrt/EchoTest.java +++ b/jrt/tests/com/yahoo/jrt/EchoTest.java @@ -64,7 +64,7 @@ public class EchoTest { assertEquals(1, metrics.clientTlsConnectionsEstablished()); }, (ConnectionAuthContextAssertion) context -> { - List chain = context.peerCertificate(); + List chain = context.peerCertificateChain(); assertEquals(1, chain.size()); assertEquals(CryptoUtils.certificate, chain.get(0)); }}, @@ -82,7 +82,7 @@ public class EchoTest { assertEquals(1, metrics.clientTlsConnectionsEstablished()); }, (ConnectionAuthContextAssertion) context -> { - List chain = context.peerCertificate(); + List chain = context.peerCertificateChain(); assertEquals(1, chain.size()); assertEquals(CryptoUtils.certificate, chain.get(0)); }}}; diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java index a5fb51da763..18f61fc7aa4 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java @@ -10,14 +10,19 @@ import java.util.TreeSet; /** * @author bjorncs */ -public record ConnectionAuthContext(List peerCertificate, +public record ConnectionAuthContext(List peerCertificateChain, CapabilitySet capabilities, SortedSet matchedPolicies) { public ConnectionAuthContext { + if (peerCertificateChain.isEmpty()) throw new IllegalArgumentException("Peer certificate chain is empty"); + peerCertificateChain = List.copyOf(peerCertificateChain); + if (matchedPolicies.isEmpty() && !CapabilitySet.none().equals(capabilities)) throw new AssertionError(); matchedPolicies = new TreeSet<>(matchedPolicies); } public boolean succeeded() { return matchedPolicies.size() > 0; } + public X509Certificate peerCertificate() { return peerCertificateChain.get(0); } + } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java index 353f704b136..30b6ac3f34b 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java @@ -37,11 +37,15 @@ public class PeerAuthorizer { this.authorizedPeers = authorizedPeers; } - public ConnectionAuthContext authorizePeer(X509Certificate peerCertificate) { + + public ConnectionAuthContext authorizePeer(X509Certificate cert) { return authorizePeer(List.of(cert)); } + + public ConnectionAuthContext authorizePeer(List certChain) { + X509Certificate cert = certChain.get(0); SortedSet matchedPolicies = new TreeSet<>(); Set grantedCapabilities = new HashSet<>(); - String cn = getCommonName(peerCertificate).orElse(null); - List sans = getSubjectAlternativeNames(peerCertificate); + String cn = getCommonName(cert).orElse(null); + List sans = getSubjectAlternativeNames(cert); log.fine(() -> String.format("Subject info from x509 certificate: CN=[%s], 'SAN=%s", cn, sans)); for (PeerPolicy peerPolicy : authorizedPeers.peerPolicies()) { if (matchesPolicy(peerPolicy, cn, sans)) { @@ -49,7 +53,7 @@ public class PeerAuthorizer { grantedCapabilities.add(peerPolicy.capabilities()); } } - return new ConnectionAuthContext(List.of(peerCertificate), CapabilitySet.unionOf(grantedCapabilities), matchedPolicies); + return new ConnectionAuthContext(certChain, CapabilitySet.unionOf(grantedCapabilities), matchedPolicies); } private static boolean matchesPolicy(PeerPolicy peerPolicy, String cn, List sans) { diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java index 925e21c63ff..ea920a90c7b 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java @@ -15,6 +15,7 @@ import java.net.Socket; import java.security.KeyStore; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; +import java.util.List; import java.util.Optional; import java.util.logging.Logger; @@ -55,39 +56,39 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { defaultTrustManager.checkClientTrusted(chain, authType); - authorizePeer(chain[0], authType, true, null); + authorizePeer(chain, authType, true, null); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { defaultTrustManager.checkServerTrusted(chain, authType); - authorizePeer(chain[0], authType, false, null); + authorizePeer(chain, authType, false, null); } @Override public void checkClientTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { defaultTrustManager.checkClientTrusted(chain, authType, socket); - authorizePeer(chain[0], authType, true, null); + authorizePeer(chain, authType, true, null); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType, Socket socket) throws CertificateException { overrideHostnameVerificationForClient(socket); defaultTrustManager.checkServerTrusted(chain, authType, socket); - authorizePeer(chain[0], authType, false, null); + authorizePeer(chain, authType, false, null); } @Override public void checkClientTrusted(X509Certificate[] chain, String authType, SSLEngine sslEngine) throws CertificateException { defaultTrustManager.checkClientTrusted(chain, authType, sslEngine); - authorizePeer(chain[0], authType, true, sslEngine); + authorizePeer(chain, authType, true, sslEngine); } @Override public void checkServerTrusted(X509Certificate[] chain, String authType, SSLEngine sslEngine) throws CertificateException { overrideHostnameVerificationForClient(sslEngine); defaultTrustManager.checkServerTrusted(chain, authType, sslEngine); - authorizePeer(chain[0], authType, false, sslEngine); + authorizePeer(chain, authType, false, sslEngine); } @Override @@ -103,18 +104,19 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { .flatMap(session -> Optional.ofNullable((ConnectionAuthContext) session.getValue(HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY))); } - private void authorizePeer(X509Certificate certificate, String authType, boolean isVerifyingClient, SSLEngine sslEngine) throws CertificateException { + private void authorizePeer(X509Certificate[] certChain, String authType, boolean isVerifyingClient, SSLEngine sslEngine) throws CertificateException { if (mode == AuthorizationMode.DISABLE) return; - log.fine(() -> "Verifying certificate: " + createInfoString(certificate, authType, isVerifyingClient)); - ConnectionAuthContext result = authorizer.authorizePeer(certificate); + + log.fine(() -> "Verifying certificate: " + createInfoString(certChain[0], authType, isVerifyingClient)); + ConnectionAuthContext result = authorizer.authorizePeer(List.of(certChain)); if (sslEngine != null) { // getHandshakeSession() will never return null in this context sslEngine.getHandshakeSession().putValue(HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY, result); } if (result.succeeded()) { log.fine(() -> String.format("Verification result: %s", result)); } else { - String errorMessage = "Authorization failed: " + createInfoString(certificate, authType, isVerifyingClient); + String errorMessage = "Authorization failed: " + createInfoString(certChain[0], authType, isVerifyingClient); log.warning(errorMessage); if (mode == AuthorizationMode.ENFORCE) { throw new CertificateException(errorMessage); -- cgit v1.2.3 From 64adc479fab2fad65c398e70222f3443b75f9f32 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Wed, 13 Jul 2022 17:22:04 +0200 Subject: Rename 'succeeded' => 'authorized' --- jrt/src/com/yahoo/jrt/TlsCryptoSocket.java | 4 ++-- .../main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java | 2 +- .../java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java | 2 +- .../test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java index 40cb7c3938a..721c7c4d2e7 100644 --- a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java +++ b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java @@ -100,7 +100,7 @@ public class TlsCryptoSocket implements CryptoSocket { if (authorizationResult == null) { PeerAuthorizerTrustManager.getAuthorizationResult(sslEngine) // only available during handshake .ifPresent(result -> { - if (!result.succeeded()) { + if (!result.authorized()) { metrics.incrementPeerAuthorizationFailures(); } authorizationResult = result; @@ -144,7 +144,7 @@ public class TlsCryptoSocket implements CryptoSocket { } } catch (SSLHandshakeException e) { // sslEngine.getDelegatedTask().run() and handshakeWrap() may throw SSLHandshakeException, potentially handshakeUnwrap() and sslEngine.beginHandshake() as well. - if (authorizationResult == null || authorizationResult.succeeded()) { // don't include handshake failures due from PeerAuthorizerTrustManager + if (authorizationResult == null || authorizationResult.authorized()) { // don't include handshake failures due from PeerAuthorizerTrustManager metrics.incrementTlsCertificateVerificationFailures(); } throw e; diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java index 18f61fc7aa4..52d838d29ef 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java @@ -21,7 +21,7 @@ public record ConnectionAuthContext(List peerCertificateChain, matchedPolicies = new TreeSet<>(matchedPolicies); } - public boolean succeeded() { return matchedPolicies.size() > 0; } + public boolean authorized() { return matchedPolicies.size() > 0; } public X509Certificate peerCertificate() { return peerCertificateChain.get(0); } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java index ea920a90c7b..21a089e4295 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java @@ -113,7 +113,7 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { if (sslEngine != null) { // getHandshakeSession() will never return null in this context sslEngine.getHandshakeSession().putValue(HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY, result); } - if (result.succeeded()) { + if (result.authorized()) { log.fine(() -> String.format("Verification result: %s", result)); } else { String errorMessage = "Authorization failed: " + createInfoString(certChain[0], authType, isVerifyingClient); diff --git a/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java b/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java index a2f27ba42bc..3791aed4155 100644 --- a/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java +++ b/security-utils/src/test/java/com/yahoo/security/tls/authz/PeerAuthorizerTest.java @@ -158,11 +158,11 @@ public class PeerAuthorizerTest { } private static void assertAuthorized(ConnectionAuthContext result) { - assertTrue(result.succeeded()); + assertTrue(result.authorized()); } private static void assertUnauthorized(ConnectionAuthContext result) { - assertFalse(result.succeeded()); + assertFalse(result.authorized()); } private static void assertCapabiltiesGranted(ConnectionAuthContext ctx, Set expected) { -- cgit v1.2.3 From 9bcb0afa58fbbdaeffaefe12cad46c7008713aaa Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Fri, 15 Jul 2022 14:52:02 +0200 Subject: Change type from SortedSet to Set --- .../config/server/rpc/security/MultiTenantRpcAuthorizerTest.java | 3 +-- .../java/com/yahoo/security/tls/authz/ConnectionAuthContext.java | 7 +++---- .../src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java | 4 +--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java index 7a2e0f00433..5b5b795a412 100644 --- a/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java +++ b/configserver/src/test/java/com/yahoo/vespa/config/server/rpc/security/MultiTenantRpcAuthorizerTest.java @@ -41,7 +41,6 @@ import java.time.Instant; import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.TreeSet; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; @@ -251,7 +250,7 @@ public class MultiTenantRpcAuthorizerTest { private static Request mockJrtRpcRequest(String payload) { ConnectionAuthContext authContext = - new ConnectionAuthContext(PEER_CERTIFICATE_CHAIN, CapabilitySet.none(), new TreeSet<>()); + new ConnectionAuthContext(PEER_CERTIFICATE_CHAIN, CapabilitySet.none(), Set.of()); Target target = mock(Target.class); when(target.getConnectionAuthContext()).thenReturn(Optional.of(authContext)); Request request = mock(Request.class); diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java index 52d838d29ef..9f767dc99dd 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java @@ -4,21 +4,20 @@ import com.yahoo.security.tls.policy.CapabilitySet; import java.security.cert.X509Certificate; import java.util.List; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.Set; /** * @author bjorncs */ public record ConnectionAuthContext(List peerCertificateChain, CapabilitySet capabilities, - SortedSet matchedPolicies) { + Set matchedPolicies) { public ConnectionAuthContext { if (peerCertificateChain.isEmpty()) throw new IllegalArgumentException("Peer certificate chain is empty"); peerCertificateChain = List.copyOf(peerCertificateChain); if (matchedPolicies.isEmpty() && !CapabilitySet.none().equals(capabilities)) throw new AssertionError(); - matchedPolicies = new TreeSet<>(matchedPolicies); + matchedPolicies = Set.copyOf(matchedPolicies); } public boolean authorized() { return matchedPolicies.size() > 0; } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java index 30b6ac3f34b..cf21befadd5 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java @@ -13,8 +13,6 @@ import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; import java.util.logging.Logger; import static com.yahoo.security.SubjectAlternativeName.Type.DNS_NAME; @@ -42,7 +40,7 @@ public class PeerAuthorizer { public ConnectionAuthContext authorizePeer(List certChain) { X509Certificate cert = certChain.get(0); - SortedSet matchedPolicies = new TreeSet<>(); + Set matchedPolicies = new HashSet<>(); Set grantedCapabilities = new HashSet<>(); String cn = getCommonName(cert).orElse(null); List sans = getSubjectAlternativeNames(cert); -- cgit v1.2.3 From ef35cd168d1449c40dbdfaadc6ffb9ae19f996c4 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Fri, 15 Jul 2022 14:55:05 +0200 Subject: Rename 'hasAllCapabilities()' => 'hasAll()' --- .../yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java | 2 +- .../src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java index 195e200febb..65030fd640a 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java @@ -154,7 +154,7 @@ public class TransportSecurityOptionsJsonSerializer { authorizedPeer.requiredCredentials = new ArrayList<>(); authorizedPeer.description = peerPolicy.description().orElse(null); CapabilitySet caps = peerPolicy.capabilities(); - if (!caps.hasAllCapabilities()) { + if (!caps.hasAll()) { authorizedPeer.capabilities = List.copyOf(caps.toCapabilityNames()); } for (RequiredPeerCredential requiredPeerCredential : peerPolicy.requiredCredentials()) { diff --git a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java index 46a07972fc3..57ba155b3b7 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java @@ -70,7 +70,7 @@ public class CapabilitySet { public static CapabilitySet all() { return ALL_CAPABILITIES; } public static CapabilitySet none() { return NO_CAPABILITIES; } - public boolean hasAllCapabilities() { return this.caps.equals(ALL_CAPABILITIES.caps); } + public boolean hasAll() { return this.caps.equals(ALL_CAPABILITIES.caps); } public SortedSet toCapabilityNames() { return caps.stream().map(Capability::asString).collect(Collectors.toCollection(TreeSet::new)); -- cgit v1.2.3 From 1fba92f023c9a6f6e95cea1097b58514afffc92d Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Fri, 15 Jul 2022 15:20:38 +0200 Subject: Always run PeerAutorizer Interpret empty AuthorizedPeers as granting all capabilities unconditionally. Assume AuthorizedPeers as always present. --- .../security/tls/ConfigFileBasedTlsContext.java | 7 +--- .../com/yahoo/security/tls/DefaultTlsContext.java | 11 ++---- .../security/tls/TransportSecurityOptions.java | 6 +-- .../security/tls/authz/ConnectionAuthContext.java | 3 +- .../yahoo/security/tls/authz/PeerAuthorizer.java | 3 ++ .../tls/authz/PeerAuthorizerTrustManager.java | 9 +++-- .../TransportSecurityOptionsJsonSerializer.java | 43 +++++++++++----------- .../yahoo/security/tls/policy/AuthorizedPeers.java | 6 +++ .../yahoo/security/tls/policy/CapabilitySet.java | 1 + 9 files changed, 44 insertions(+), 45 deletions(-) diff --git a/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java index 6d4684666ea..cc664786734 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java @@ -7,7 +7,6 @@ import com.yahoo.security.KeyUtils; import com.yahoo.security.SslContextBuilder; import com.yahoo.security.X509CertificateUtils; import com.yahoo.security.tls.authz.PeerAuthorizerTrustManager; -import com.yahoo.security.tls.policy.AuthorizedPeers; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -19,7 +18,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.security.KeyStore; import java.time.Duration; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -112,9 +110,8 @@ public class ConfigFileBasedTlsContext implements TlsContext { PeerAuthentication peerAuthentication) { HostnameVerification hostnameVerification = options.isHostnameValidationDisabled() ? HostnameVerification.DISABLED : HostnameVerification.ENABLED; - PeerAuthorizerTrustManager authorizerTrustManager = options.getAuthorizedPeers() - .map(authorizedPeers -> new PeerAuthorizerTrustManager(authorizedPeers, mode, hostnameVerification, mutableTrustManager)) - .orElseGet(() -> new PeerAuthorizerTrustManager(new AuthorizedPeers(Collections.emptySet()), AuthorizationMode.DISABLE, hostnameVerification, mutableTrustManager)); + PeerAuthorizerTrustManager authorizerTrustManager = + new PeerAuthorizerTrustManager(options.getAuthorizedPeers(), mode, hostnameVerification, mutableTrustManager); SSLContext sslContext = new SslContextBuilder() .withKeyManager(mutableKeyManager) .withTrustManager(authorizerTrustManager) diff --git a/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java b/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java index a01283318b6..c2ee573dfc6 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java @@ -11,7 +11,6 @@ import javax.net.ssl.SSLParameters; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -136,13 +135,9 @@ public class DefaultTlsContext implements TlsContext { if (!caCertificates.isEmpty()) { builder.withTrustStore(caCertificates); } - if (authorizedPeers != null) { - builder.withTrustManagerFactory(truststore -> new PeerAuthorizerTrustManager(authorizedPeers, mode, hostnameVerification, truststore)); - } else { - builder.withTrustManagerFactory(truststore -> new PeerAuthorizerTrustManager( - new AuthorizedPeers(Collections.emptySet()), AuthorizationMode.DISABLE, hostnameVerification, truststore)); - } - return builder.build(); + return builder.withTrustManagerFactory(truststore -> + new PeerAuthorizerTrustManager(authorizedPeers, mode, hostnameVerification, truststore)) + .build(); } } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java b/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java index 65c87bee0b9..a8802b7f0d3 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java @@ -55,9 +55,7 @@ public class TransportSecurityOptions { return Optional.ofNullable(caCertificatesFile); } - public Optional getAuthorizedPeers() { - return Optional.ofNullable(authorizedPeers); - } + public AuthorizedPeers getAuthorizedPeers() { return authorizedPeers; } public List getAcceptedCiphers() { return acceptedCiphers; } @@ -96,7 +94,7 @@ public class TransportSecurityOptions { private Path privateKeyFile; private Path certificatesFile; private Path caCertificatesFile; - private AuthorizedPeers authorizedPeers; + private AuthorizedPeers authorizedPeers = AuthorizedPeers.empty(); private List acceptedCiphers = new ArrayList<>(); private boolean isHostnameValidationDisabled; private List acceptedProtocols = new ArrayList<>(); diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java index 9f767dc99dd..877ba4e74bd 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java @@ -16,11 +16,10 @@ public record ConnectionAuthContext(List peerCertificateChain, public ConnectionAuthContext { if (peerCertificateChain.isEmpty()) throw new IllegalArgumentException("Peer certificate chain is empty"); peerCertificateChain = List.copyOf(peerCertificateChain); - if (matchedPolicies.isEmpty() && !CapabilitySet.none().equals(capabilities)) throw new AssertionError(); matchedPolicies = Set.copyOf(matchedPolicies); } - public boolean authorized() { return matchedPolicies.size() > 0; } + public boolean authorized() { return !capabilities.hasNone(); } public X509Certificate peerCertificate() { return peerCertificateChain.get(0); } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java index cf21befadd5..a87c578f8c6 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java @@ -39,6 +39,9 @@ public class PeerAuthorizer { public ConnectionAuthContext authorizePeer(X509Certificate cert) { return authorizePeer(List.of(cert)); } public ConnectionAuthContext authorizePeer(List certChain) { + if (authorizedPeers.isEmpty()) { + return new ConnectionAuthContext(certChain, CapabilitySet.all(), Set.of()); + } X509Certificate cert = certChain.get(0); Set matchedPolicies = new HashSet<>(); Set grantedCapabilities = new HashSet<>(); diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java index 21a089e4295..15d05859d29 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java @@ -6,6 +6,7 @@ import com.yahoo.security.tls.AuthorizationMode; import com.yahoo.security.tls.HostnameVerification; import com.yahoo.security.tls.TrustManagerUtils; import com.yahoo.security.tls.policy.AuthorizedPeers; +import com.yahoo.security.tls.policy.CapabilitySet; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; @@ -17,6 +18,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.logging.Logger; /** @@ -105,11 +107,10 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { } private void authorizePeer(X509Certificate[] certChain, String authType, boolean isVerifyingClient, SSLEngine sslEngine) throws CertificateException { - if (mode == AuthorizationMode.DISABLE) return; - - log.fine(() -> "Verifying certificate: " + createInfoString(certChain[0], authType, isVerifyingClient)); - ConnectionAuthContext result = authorizer.authorizePeer(List.of(certChain)); + ConnectionAuthContext result = mode != AuthorizationMode.DISABLE + ? authorizer.authorizePeer(List.of(certChain)) + : new ConnectionAuthContext(List.of(certChain), CapabilitySet.all(), Set.of()); if (sslEngine != null) { // getHandshakeSession() will never return null in this context sslEngine.getHandshakeSession().putValue(HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY, result); } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java index 65030fd640a..7fff6ca1efa 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java @@ -144,28 +144,27 @@ public class TransportSecurityOptionsJsonSerializer { options.getCaCertificatesFile().ifPresent(value -> entity.files.caCertificatesFile = value.toString()); options.getCertificatesFile().ifPresent(value -> entity.files.certificatesFile = value.toString()); options.getPrivateKeyFile().ifPresent(value -> entity.files.privateKeyFile = value.toString()); - options.getAuthorizedPeers().ifPresent( authorizedPeers -> entity.authorizedPeers = - authorizedPeers.peerPolicies().stream() - // Makes tests stable - .sorted(Comparator.comparing(PeerPolicy::policyName)) - .map(peerPolicy -> { - AuthorizedPeer authorizedPeer = new AuthorizedPeer(); - authorizedPeer.name = peerPolicy.policyName(); - authorizedPeer.requiredCredentials = new ArrayList<>(); - authorizedPeer.description = peerPolicy.description().orElse(null); - CapabilitySet caps = peerPolicy.capabilities(); - if (!caps.hasAll()) { - authorizedPeer.capabilities = List.copyOf(caps.toCapabilityNames()); - } - for (RequiredPeerCredential requiredPeerCredential : peerPolicy.requiredCredentials()) { - RequiredCredential requiredCredential = new RequiredCredential(); - requiredCredential.field = toField(requiredPeerCredential.field()); - requiredCredential.matchExpression = requiredPeerCredential.pattern().asString(); - authorizedPeer.requiredCredentials.add(requiredCredential); - } - return authorizedPeer; - }) - .collect(toList())); + entity.authorizedPeers = options.getAuthorizedPeers().peerPolicies().stream() + // Makes tests stable + .sorted(Comparator.comparing(PeerPolicy::policyName)) + .map(peerPolicy -> { + AuthorizedPeer authorizedPeer = new AuthorizedPeer(); + authorizedPeer.name = peerPolicy.policyName(); + authorizedPeer.requiredCredentials = new ArrayList<>(); + authorizedPeer.description = peerPolicy.description().orElse(null); + CapabilitySet caps = peerPolicy.capabilities(); + if (!caps.hasAll()) { + authorizedPeer.capabilities = List.copyOf(caps.toCapabilityNames()); + } + for (RequiredPeerCredential requiredPeerCredential : peerPolicy.requiredCredentials()) { + RequiredCredential requiredCredential = new RequiredCredential(); + requiredCredential.field = toField(requiredPeerCredential.field()); + requiredCredential.matchExpression = requiredPeerCredential.pattern().asString(); + authorizedPeer.requiredCredentials.add(requiredCredential); + } + return authorizedPeer; + }) + .toList(); if (!options.getAcceptedCiphers().isEmpty()) { entity.acceptedCiphers = options.getAcceptedCiphers(); } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/policy/AuthorizedPeers.java b/security-utils/src/main/java/com/yahoo/security/tls/policy/AuthorizedPeers.java index 136022e2ed9..5e49a5b341c 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/policy/AuthorizedPeers.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/policy/AuthorizedPeers.java @@ -8,10 +8,14 @@ import java.util.Set; */ public record AuthorizedPeers(Set peerPolicies) { + private static final AuthorizedPeers EMPTY = new AuthorizedPeers(Set.of()); + public AuthorizedPeers { peerPolicies = verifyPeerPolicies(peerPolicies); } + public static AuthorizedPeers empty() { return EMPTY; } + private static Set verifyPeerPolicies(Set peerPolicies) { long distinctNames = peerPolicies.stream() .map(PeerPolicy::policyName) @@ -23,4 +27,6 @@ public record AuthorizedPeers(Set peerPolicies) { return Set.copyOf(peerPolicies); } + public boolean isEmpty() { return peerPolicies.isEmpty(); } + } diff --git a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java index 57ba155b3b7..853e386dd67 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java @@ -71,6 +71,7 @@ public class CapabilitySet { public static CapabilitySet none() { return NO_CAPABILITIES; } public boolean hasAll() { return this.caps.equals(ALL_CAPABILITIES.caps); } + public boolean hasNone() { return this.caps.equals(NO_CAPABILITIES.caps); } public SortedSet toCapabilityNames() { return caps.stream().map(Capability::asString).collect(Collectors.toCollection(TreeSet::new)); -- cgit v1.2.3 From ebae2fd47ace3a9abca620e2bdabe225a7a04e01 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Fri, 15 Jul 2022 15:23:13 +0200 Subject: Rename 'toCapabilityNames()' to 'toNames()' --- .../yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java | 2 +- .../src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java | 2 +- .../src/test/java/com/yahoo/security/tls/policy/CapabilitySetTest.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java index 7fff6ca1efa..fcd84056212 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java @@ -154,7 +154,7 @@ public class TransportSecurityOptionsJsonSerializer { authorizedPeer.description = peerPolicy.description().orElse(null); CapabilitySet caps = peerPolicy.capabilities(); if (!caps.hasAll()) { - authorizedPeer.capabilities = List.copyOf(caps.toCapabilityNames()); + authorizedPeer.capabilities = List.copyOf(caps.toNames()); } for (RequiredPeerCredential requiredPeerCredential : peerPolicy.requiredCredentials()) { RequiredCredential requiredCredential = new RequiredCredential(); diff --git a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java index 853e386dd67..50de98c621c 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java @@ -73,7 +73,7 @@ public class CapabilitySet { public boolean hasAll() { return this.caps.equals(ALL_CAPABILITIES.caps); } public boolean hasNone() { return this.caps.equals(NO_CAPABILITIES.caps); } - public SortedSet toCapabilityNames() { + public SortedSet toNames() { return caps.stream().map(Capability::asString).collect(Collectors.toCollection(TreeSet::new)); } diff --git a/security-utils/src/test/java/com/yahoo/security/tls/policy/CapabilitySetTest.java b/security-utils/src/test/java/com/yahoo/security/tls/policy/CapabilitySetTest.java index 3379c37e918..429e5b24513 100644 --- a/security-utils/src/test/java/com/yahoo/security/tls/policy/CapabilitySetTest.java +++ b/security-utils/src/test/java/com/yahoo/security/tls/policy/CapabilitySetTest.java @@ -20,7 +20,7 @@ class CapabilitySetTest { SortedSet expectedNames = Arrays.stream(Capability.values()) .map(Capability::asString) .collect(Collectors.toCollection(TreeSet::new)); - SortedSet actualNames = CapabilitySet.all().toCapabilityNames(); + SortedSet actualNames = CapabilitySet.all().toNames(); assertEquals(expectedNames, actualNames); } -- cgit v1.2.3 From fe7d61426067ceb53d95890bc24cd350cfa32f42 Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Fri, 15 Jul 2022 15:35:56 +0200 Subject: Include mode in log message --- .../com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java index 15d05859d29..bc31d8ae450 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java @@ -125,9 +125,10 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { } } - private static String createInfoString(X509Certificate certificate, String authType, boolean isVerifyingClient) { - return String.format("DN='%s', SANs=%s, authType='%s', isVerifyingClient='%b'", - certificate.getSubjectX500Principal(), X509CertificateUtils.getSubjectAlternativeNames(certificate), authType, isVerifyingClient); + private String createInfoString(X509Certificate certificate, String authType, boolean isVerifyingClient) { + return String.format("DN='%s', SANs=%s, authType='%s', isVerifyingClient='%b', mode=%s", + certificate.getSubjectX500Principal(), X509CertificateUtils.getSubjectAlternativeNames(certificate), + authType, isVerifyingClient, mode); } private void overrideHostnameVerificationForClient(SSLEngine engine) { -- cgit v1.2.3 From 529a26d7e1062a006196366454f1a047ca31202c Mon Sep 17 00:00:00 2001 From: Bjørn Christian Seime Date: Tue, 19 Jul 2022 14:29:20 +0200 Subject: Rename method/variable names to match new class name --- jrt/src/com/yahoo/jrt/TlsCryptoSocket.java | 16 ++++++++-------- .../security/tls/authz/PeerAuthorizerTrustManager.java | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java index 721c7c4d2e7..ecd76e1eb17 100644 --- a/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java +++ b/jrt/src/com/yahoo/jrt/TlsCryptoSocket.java @@ -41,7 +41,7 @@ public class TlsCryptoSocket implements CryptoSocket { private int sessionApplicationBufferSize; private ByteBuffer handshakeDummyBuffer; private HandshakeState handshakeState; - private ConnectionAuthContext authorizationResult; + private ConnectionAuthContext authContext; public TlsCryptoSocket(SocketChannel channel, SSLEngine sslEngine) { this.channel = channel; @@ -97,13 +97,13 @@ public class TlsCryptoSocket implements CryptoSocket { channelRead(); break; case NEED_WORK: - if (authorizationResult == null) { - PeerAuthorizerTrustManager.getAuthorizationResult(sslEngine) // only available during handshake - .ifPresent(result -> { - if (!result.authorized()) { + if (authContext == null) { + PeerAuthorizerTrustManager.getConnectionAuthContext(sslEngine) // only available during handshake + .ifPresent(ctx -> { + if (!ctx.authorized()) { metrics.incrementPeerAuthorizationFailures(); } - authorizationResult = result; + authContext = ctx; }); } break; @@ -144,7 +144,7 @@ public class TlsCryptoSocket implements CryptoSocket { } } catch (SSLHandshakeException e) { // sslEngine.getDelegatedTask().run() and handshakeWrap() may throw SSLHandshakeException, potentially handshakeUnwrap() and sslEngine.beginHandshake() as well. - if (authorizationResult == null || authorizationResult.authorized()) { // don't include handshake failures due from PeerAuthorizerTrustManager + if (authContext == null || authContext.authorized()) { // don't include handshake failures due from PeerAuthorizerTrustManager metrics.incrementTlsCertificateVerificationFailures(); } throw e; @@ -221,7 +221,7 @@ public class TlsCryptoSocket implements CryptoSocket { @Override public Optional getConnectionAuthContext() { if (handshakeState != HandshakeState.COMPLETED) return Optional.empty(); - return Optional.ofNullable(authorizationResult); + return Optional.ofNullable(authContext); } private boolean handshakeWrap() throws IOException { diff --git a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java index bc31d8ae450..334216a2c19 100644 --- a/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java +++ b/security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java @@ -101,7 +101,7 @@ public class PeerAuthorizerTrustManager extends X509ExtendedTrustManager { /** * Note: The authorization result is only available during handshake. The underlying handshake session is removed once handshake is complete. */ - public static Optional getAuthorizationResult(SSLEngine sslEngine) { + public static Optional getConnectionAuthContext(SSLEngine sslEngine) { return Optional.ofNullable(sslEngine.getHandshakeSession()) .flatMap(session -> Optional.ofNullable((ConnectionAuthContext) session.getValue(HANDSHAKE_SESSION_AUTH_CONTEXT_PROPERTY))); } -- cgit v1.2.3