summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Christian Seime <bjorncs@yahooinc.com>2022-07-15 15:20:38 +0200
committerBjørn Christian Seime <bjorncs@yahooinc.com>2022-07-15 15:35:10 +0200
commit1fba92f023c9a6f6e95cea1097b58514afffc92d (patch)
tree06a61563b80a729dbf5e4ad7da1e9a902bba6f14
parentef35cd168d1449c40dbdfaadc6ffb9ae19f996c4 (diff)
Always run PeerAutorizer
Interpret empty AuthorizedPeers as granting all capabilities unconditionally. Assume AuthorizedPeers as always present.
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/ConfigFileBasedTlsContext.java7
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/DefaultTlsContext.java11
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/TransportSecurityOptions.java6
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/authz/ConnectionAuthContext.java3
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizer.java3
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/authz/PeerAuthorizerTrustManager.java9
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/json/TransportSecurityOptionsJsonSerializer.java43
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/policy/AuthorizedPeers.java6
-rw-r--r--security-utils/src/main/java/com/yahoo/security/tls/policy/CapabilitySet.java1
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));