diff options
author | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-07-15 15:20:38 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@yahooinc.com> | 2022-07-15 15:35:10 +0200 |
commit | 1fba92f023c9a6f6e95cea1097b58514afffc92d (patch) | |
tree | 06a61563b80a729dbf5e4ad7da1e9a902bba6f14 | |
parent | ef35cd168d1449c40dbdfaadc6ffb9ae19f996c4 (diff) |
Always run PeerAutorizer
Interpret empty AuthorizedPeers as granting all capabilities unconditionally.
Assume AuthorizedPeers as always present.
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<AuthorizedPeers> getAuthorizedPeers() { - return Optional.ofNullable(authorizedPeers); - } + public AuthorizedPeers getAuthorizedPeers() { return authorizedPeers; } public List<String> 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<String> acceptedCiphers = new ArrayList<>(); private boolean isHostnameValidationDisabled; private List<String> 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<X509Certificate> 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<X509Certificate> certChain) { + if (authorizedPeers.isEmpty()) { + return new ConnectionAuthContext(certChain, CapabilitySet.all(), Set.of()); + } X509Certificate cert = certChain.get(0); Set<String> matchedPolicies = new HashSet<>(); Set<CapabilitySet> 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<PeerPolicy> peerPolicies) { + private static final AuthorizedPeers EMPTY = new AuthorizedPeers(Set.of()); + public AuthorizedPeers { peerPolicies = verifyPeerPolicies(peerPolicies); } + public static AuthorizedPeers empty() { return EMPTY; } + private static Set<PeerPolicy> verifyPeerPolicies(Set<PeerPolicy> peerPolicies) { long distinctNames = peerPolicies.stream() .map(PeerPolicy::policyName) @@ -23,4 +27,6 @@ public record AuthorizedPeers(Set<PeerPolicy> 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<String> toCapabilityNames() { return caps.stream().map(Capability::asString).collect(Collectors.toCollection(TreeSet::new)); |