Skip to content

Commit 778bab9

Browse files
jfredenelasticsearchmachine
andauthored
Add trust configuration for cross cluster api keys (#134893)
* Add trust configuration for cross cluster api keys * Update docs/changelog/134893.yaml --------- Co-authored-by: elasticsearchmachine <[email protected]>
1 parent ba9aa64 commit 778bab9

32 files changed

+1225
-607
lines changed

docs/changelog/134893.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 134893
2+
summary: Add trust configuration for cross cluster api keys
3+
area: Security
4+
type: enhancement
5+
issues: []

libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/CompositeTrustConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public boolean isSystemDefault() {
4242
return configs.stream().allMatch(SslTrustConfig::isSystemDefault);
4343
}
4444

45+
@Override
46+
public boolean hasExplicitConfig() {
47+
return configs.stream().allMatch(SslTrustConfig::hasExplicitConfig);
48+
}
49+
4550
@Override
4651
public X509ExtendedTrustManager createTrustManager() {
4752
try {

libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/PemTrustConfig.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,4 +129,8 @@ public int hashCode() {
129129
return Objects.hash(certificateAuthorities);
130130
}
131131

132+
@Override
133+
public boolean hasExplicitConfig() {
134+
return true;
135+
}
132136
}

libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/SslTrustConfig.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ public interface SslTrustConfig {
3939
*/
4040
Collection<? extends StoredCertificate> getConfiguredCertificates();
4141

42+
/**
43+
* @return {@code true} if this trust config is based on any explicit trust settings
44+
*/
45+
default boolean hasExplicitConfig() {
46+
return false;
47+
}
48+
4249
/**
4350
* @return {@code true} if this trust config is based on the system default truststore
4451
*/

libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/StoreTrustConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,9 @@ public String toString() {
162162
sb.append('}');
163163
return sb.toString();
164164
}
165+
166+
@Override
167+
public boolean hasExplicitConfig() {
168+
return true;
169+
}
165170
}

libs/ssl-config/src/main/java/org/elasticsearch/common/ssl/TrustEverythingConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ public X509ExtendedTrustManager createTrustManager() {
7575
return TRUST_MANAGER;
7676
}
7777

78+
@Override
79+
public boolean hasExplicitConfig() {
80+
return true;
81+
}
82+
7883
@Override
7984
public String toString() {
8085
return "trust everything";

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ssl/RestrictedTrustConfig.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,9 @@ private static CertificateTrustRestrictions readTrustGroup(Path path) throws IOE
8787
final List<String> trustNodeNames = settings.getAsList(RESTRICTIONS_KEY_SUBJECT_NAME);
8888
return new CertificateTrustRestrictions(trustNodeNames);
8989
}
90+
91+
@Override
92+
public boolean hasExplicitConfig() {
93+
return delegate.hasExplicitConfig();
94+
}
9095
}
Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,51 +9,53 @@
99

1010
import org.elasticsearch.common.settings.MockSecureSettings;
1111
import org.elasticsearch.common.settings.Settings;
12+
import org.elasticsearch.common.ssl.DiagnosticTrustManager;
1213
import org.elasticsearch.common.ssl.PemKeyConfig;
1314
import org.elasticsearch.test.SecurityIntegTestCase;
1415

15-
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySignerSettings.SIGNING_CERT_PATH;
16-
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySignerSettings.SIGNING_KEYSTORE_ALIAS;
17-
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySignerSettings.SIGNING_KEYSTORE_PATH;
18-
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySignerSettings.SIGNING_KEYSTORE_SECURE_PASSWORD;
19-
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySignerSettings.SIGNING_KEYSTORE_TYPE;
20-
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySignerSettings.SIGNING_KEY_PATH;
16+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.DIAGNOSE_TRUST_EXCEPTIONS;
17+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.SIGNING_CERTIFICATE_AUTHORITIES;
18+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.SIGNING_CERT_PATH;
19+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.SIGNING_KEYSTORE_ALIAS;
20+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.SIGNING_KEYSTORE_PATH;
21+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.SIGNING_KEYSTORE_SECURE_PASSWORD;
22+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.SIGNING_KEYSTORE_TYPE;
23+
import static org.elasticsearch.xpack.security.transport.CrossClusterApiKeySigningSettings.SIGNING_KEY_PATH;
2124
import static org.hamcrest.Matchers.equalToIgnoringCase;
2225

23-
public class CrossClusterApiKeySignerIntegTests extends SecurityIntegTestCase {
26+
public class CrossClusterApiKeySignatureManagerIntegTests extends SecurityIntegTestCase {
2427

2528
private static final String DYNAMIC_TEST_CLUSTER_ALIAS = "dynamic_test_cluster";
2629
private static final String STATIC_TEST_CLUSTER_ALIAS = "static_test_cluster";
2730

2831
public void testSignWithPemKeyConfig() {
29-
final CrossClusterApiKeySigner signer = getCrossClusterApiKeySignerInstance();
32+
final CrossClusterApiKeySignatureManager manager = getCrossClusterApiKeySignatureManagerInstance();
3033
final String[] testHeaders = randomArray(5, String[]::new, () -> randomAlphanumericOfLength(randomInt(20)));
3134

32-
X509CertificateSignature signature = signer.sign(STATIC_TEST_CLUSTER_ALIAS, testHeaders);
33-
signature.certificate().getPublicKey();
34-
35+
X509CertificateSignature signature = manager.signerForClusterAlias(STATIC_TEST_CLUSTER_ALIAS).sign(testHeaders);
3536
var keyConfig = new PemKeyConfig(
3637
"signing_rsa.crt",
3738
"signing_rsa.key",
3839
new char[0],
3940
getDataPath("/org/elasticsearch/xpack/security/signature/signing_rsa.crt").getParent()
4041
);
4142

43+
var verifier = manager.verifier();
44+
4245
assertThat(signature.algorithm(), equalToIgnoringCase(keyConfig.getKeys().getFirst().v2().getSigAlgName()));
43-
assertEquals(signature.certificate(), keyConfig.getKeys().getFirst().v2());
46+
assertEquals(signature.certificates()[0], keyConfig.getKeys().getFirst().v2());
47+
assertTrue(verifier.verify(signature, testHeaders));
4448
}
4549

4650
public void testSignUnknownClusterAlias() {
47-
final CrossClusterApiKeySigner signer = getCrossClusterApiKeySignerInstance();
51+
final CrossClusterApiKeySignatureManager manager = getCrossClusterApiKeySignatureManagerInstance();
4852
final String[] testHeaders = randomArray(5, String[]::new, () -> randomAlphanumericOfLength(randomInt(20)));
49-
50-
X509CertificateSignature signature = signer.sign("unknowncluster", testHeaders);
53+
X509CertificateSignature signature = manager.signerForClusterAlias("unknowncluster").sign(testHeaders);
5154
assertNull(signature);
5255
}
5356

5457
public void testSeveralKeyStoreAliases() {
55-
final CrossClusterApiKeySigner signer = getCrossClusterApiKeySignerInstance();
56-
58+
final CrossClusterApiKeySignatureManager manager = getCrossClusterApiKeySignatureManagerInstance();
5759
try {
5860
// Create a new config without an alias. Since there are several aliases in the keystore, no signature should be generated
5961
updateClusterSettings(
@@ -69,7 +71,8 @@ public void testSeveralKeyStoreAliases() {
6971
);
7072

7173
{
72-
X509CertificateSignature signature = signer.sign(DYNAMIC_TEST_CLUSTER_ALIAS, "test", "test");
74+
var signer = manager.signerForClusterAlias(DYNAMIC_TEST_CLUSTER_ALIAS);
75+
X509CertificateSignature signature = signer.sign("test", "test");
7376
assertNull(signature);
7477
}
7578

@@ -79,7 +82,8 @@ public void testSeveralKeyStoreAliases() {
7982
.put(SIGNING_KEYSTORE_ALIAS.getConcreteSettingForNamespace(DYNAMIC_TEST_CLUSTER_ALIAS).getKey(), "wholelottakey")
8083
);
8184
{
82-
X509CertificateSignature signature = signer.sign(DYNAMIC_TEST_CLUSTER_ALIAS, "test", "test");
85+
var signer = manager.signerForClusterAlias(DYNAMIC_TEST_CLUSTER_ALIAS);
86+
X509CertificateSignature signature = signer.sign("test", "test");
8387
assertNotNull(signature);
8488
}
8589

@@ -89,7 +93,8 @@ public void testSeveralKeyStoreAliases() {
8993
.put(SIGNING_KEYSTORE_ALIAS.getConcreteSettingForNamespace(DYNAMIC_TEST_CLUSTER_ALIAS).getKey(), "idonotexist")
9094
);
9195
{
92-
X509CertificateSignature signature = signer.sign(DYNAMIC_TEST_CLUSTER_ALIAS, "test", "test");
96+
var signer = manager.signerForClusterAlias(DYNAMIC_TEST_CLUSTER_ALIAS);
97+
X509CertificateSignature signature = signer.sign("test", "test");
9398
assertNotNull(signature);
9499
}
95100
} finally {
@@ -103,10 +108,28 @@ public void testSeveralKeyStoreAliases() {
103108
}
104109
}
105110

111+
public void testVerifyDiagnosticTrustManagerDisabled() {
112+
final CrossClusterApiKeySignatureManager manager = getCrossClusterApiKeySignatureManagerInstance();
113+
114+
try {
115+
updateClusterSettings(Settings.builder().put(DIAGNOSE_TRUST_EXCEPTIONS.getKey(), false));
116+
assertFalse(manager.getTrustManager() instanceof DiagnosticTrustManager);
117+
} finally {
118+
updateClusterSettings(Settings.builder().putNull(DIAGNOSE_TRUST_EXCEPTIONS.getKey()));
119+
}
120+
}
121+
122+
public void testVerifyDiagnosticTrustManagerEnabledDefault() {
123+
final CrossClusterApiKeySignatureManager manager = getCrossClusterApiKeySignatureManagerInstance();
124+
125+
assertTrue(manager.getTrustManager() instanceof DiagnosticTrustManager);
126+
}
127+
106128
@Override
107129
protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) {
108130
var builder = Settings.builder();
109131
MockSecureSettings secureSettings = (MockSecureSettings) builder.put(super.nodeSettings(nodeOrdinal, otherSettings))
132+
.put(SIGNING_CERTIFICATE_AUTHORITIES.getKey(), getDataPath("/org" + "/elasticsearch/xpack/security/signature/root.crt"))
110133
.put(
111134
SIGNING_CERT_PATH.getConcreteSettingForNamespace(STATIC_TEST_CLUSTER_ALIAS).getKey(),
112135
getDataPath("/org/elasticsearch/xpack/security/signature/signing_rsa.crt")
@@ -123,8 +146,8 @@ protected Settings nodeSettings(int nodeOrdinal, Settings otherSettings) {
123146
return builder.build();
124147
}
125148

126-
private static CrossClusterApiKeySigner getCrossClusterApiKeySignerInstance() {
127-
return CrossClusterTestHelper.getCrossClusterApiKeySigner(internalCluster());
149+
private static CrossClusterApiKeySignatureManager getCrossClusterApiKeySignatureManagerInstance() {
150+
return CrossClusterTestHelper.getCrossClusterApiKeySignatureManager(internalCluster());
128151
}
129152

130153
}

0 commit comments

Comments
 (0)