Skip to content

Commit dda9054

Browse files
committed
Moved tests into integration tests opensearch-project#2
Changes: - Moved testSslCertsApiTest into SslCertsRestApiIntegrationTest - Fixed tests framework certificates generation for nodes. Tests with the Legacy prefix removed since new tests use randomization for paths Signed-off-by: Andrey Pleskach <ples@aiven.io>
1 parent af358d0 commit dda9054

File tree

8 files changed

+119
-243
lines changed

8 files changed

+119
-243
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*
8+
* Modifications Copyright OpenSearch Contributors. See
9+
* GitHub history for details.
10+
*/
11+
package org.opensearch.security.api;
12+
13+
import com.fasterxml.jackson.databind.JsonNode;
14+
import org.junit.Test;
15+
16+
import org.opensearch.security.dlic.rest.api.Endpoint;
17+
import org.opensearch.test.framework.cluster.TestRestClient;
18+
19+
import static org.hamcrest.MatcherAssert.assertThat;
20+
import static org.opensearch.security.dlic.rest.api.RestApiAdminPrivilegesEvaluator.CERTS_INFO_ACTION;
21+
import static org.opensearch.security.support.ConfigConstants.SECURITY_RESTAPI_ADMIN_ENABLED;
22+
23+
public class SslCertsRestApiIntegrationTest extends AbstractApiIntegrationTest {
24+
25+
final static String REST_API_ADMIN_SSL_INFO = "rest-api-admin-ssl-info";
26+
27+
static {
28+
clusterSettings.put(SECURITY_RESTAPI_ADMIN_ENABLED, true);
29+
testSecurityConfig.withRestAdminUser(REST_ADMIN_USER, allRestAdminPermissions())
30+
.withRestAdminUser(REST_API_ADMIN_SSL_INFO, restAdminPermission(Endpoint.SSL, CERTS_INFO_ACTION));
31+
}
32+
33+
protected String sslCertsPath() {
34+
return super.apiPath("ssl", "certs");
35+
}
36+
37+
@Test
38+
public void certsInfoForbiddenForRegularUser() throws Exception {
39+
withUser(NEW_USER, client -> forbidden(() -> client.get(sslCertsPath())));
40+
}
41+
42+
@Test
43+
public void certsInfoForbiddenForAdminUser() throws Exception {
44+
withUser(NEW_USER, client -> forbidden(() -> client.get(sslCertsPath())));
45+
}
46+
47+
@Test
48+
public void certsInfoAvailableForTlsAdmin() throws Exception {
49+
withUser(ADMIN_USER_NAME, localCluster.getAdminCertificate(), this::verifySSLCertsInfo);
50+
}
51+
52+
@Test
53+
public void certsInfoAvailableForRestAdmin() throws Exception {
54+
withUser(REST_ADMIN_USER, this::verifySSLCertsInfo);
55+
withUser(REST_API_ADMIN_SSL_INFO, this::verifySSLCertsInfo);
56+
}
57+
58+
private void verifySSLCertsInfo(final TestRestClient client) throws Exception {
59+
final var response = ok(() -> client.get(sslCertsPath()));
60+
61+
final var body = response.bodyAsJsonNode();
62+
assertThat(response.getBody(), body.has("http_certificates_list"));
63+
assertThat(response.getBody(), body.get("http_certificates_list").isArray());
64+
verifyCertsJson(body.get("http_certificates_list").get(0));
65+
assertThat(response.getBody(), body.has("transport_certificates_list"));
66+
assertThat(response.getBody(), body.get("transport_certificates_list").isArray());
67+
verifyCertsJson(body.get("transport_certificates_list").get(0));
68+
}
69+
70+
private void verifyCertsJson(final JsonNode jsonNode) {
71+
assertThat(jsonNode.toPrettyString(), jsonNode.has("issuer_dn"));
72+
assertThat(jsonNode.toPrettyString(), jsonNode.has("subject_dn"));
73+
assertThat(jsonNode.toPrettyString(), jsonNode.get("subject_dn").asText().matches(".*node-\\d.example.com+"));
74+
assertThat(jsonNode.toPrettyString(), jsonNode.get("san").asText().matches(".*node-\\d.example.com.*"));
75+
assertThat(jsonNode.toPrettyString(), jsonNode.has("not_before"));
76+
assertThat(jsonNode.toPrettyString(), jsonNode.has("not_after"));
77+
}
78+
79+
}

src/integrationTest/java/org/opensearch/test/framework/certificate/TestCertificates.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,13 @@ public class TestCertificates {
5555

5656
private static final Logger log = LogManager.getLogger(TestCertificates.class);
5757

58-
public static final Integer MAX_NUMBER_OF_NODE_CERTIFICATES = 3;
58+
public static final Integer DEFAULT_NUMBER_OF_NODE_CERTIFICATES = 3;
59+
60+
public static final String CA_SUBJECT = "DC=com,DC=example,O=Example Com Inc.,OU=Example Com Inc. Root CA,CN=Example Com Inc. Root CA";
61+
62+
public static final String LDAP_SUBJECT = "DC=de,L=test,O=node,OU=node,CN=ldap.example.com";
63+
public static final String NODE_SUBJECT_PATTERN = "DC=de,L=test,O=node,OU=node,CN=node-%d.example.com";
5964

60-
private static final String CA_SUBJECT = "DC=com,DC=example,O=Example Com Inc.,OU=Example Com Inc. Root CA,CN=Example Com Inc. Root CA";
6165
private static final String ADMIN_DN = "CN=kirk,OU=client,O=client,L=test,C=de";
6266
private static final int CERTIFICATE_VALIDITY_DAYS = 365;
6367
private static final String CERTIFICATE_FILE_EXT = ".cert";
@@ -66,13 +70,18 @@ public class TestCertificates {
6670
private final CertificateData adminCertificate;
6771
private final List<CertificateData> nodeCertificates;
6872

73+
private final int numberOfNodes;
74+
6975
private final CertificateData ldapCertificate;
7076

7177
public TestCertificates() {
78+
this(DEFAULT_NUMBER_OF_NODE_CERTIFICATES);
79+
}
80+
81+
public TestCertificates(final int numberOfNodes) {
7282
this.caCertificate = createCaCertificate();
73-
this.nodeCertificates = IntStream.range(0, MAX_NUMBER_OF_NODE_CERTIFICATES)
74-
.mapToObj(this::createNodeCertificate)
75-
.collect(Collectors.toList());
83+
this.numberOfNodes = numberOfNodes;
84+
this.nodeCertificates = IntStream.range(0, this.numberOfNodes).mapToObj(this::createNodeCertificate).collect(Collectors.toList());
7685
this.ldapCertificate = createLdapCertificate();
7786
this.adminCertificate = createAdminCertificate(ADMIN_DN);
7887
log.info("Test certificates successfully generated");
@@ -109,7 +118,7 @@ public CertificateData getRootCertificateData() {
109118

110119
/**
111120
* Certificate for Open Search node. The certificate is derived from root certificate, returned by method {@link #getRootCertificate()}
112-
* @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES}
121+
* @param node is a node index. It has to be less than {@link #DEFAULT_NUMBER_OF_NODE_CERTIFICATES}
113122
* @return file which contains certificate in PEM format, defined by <a href="https://www.rfc-editor.org/rfc/rfc1421.txt">RFC 1421</a>
114123
*/
115124
public File getNodeCertificate(int node) {
@@ -123,18 +132,18 @@ public CertificateData getNodeCertificateData(int node) {
123132
}
124133

125134
private void isCorrectNodeNumber(int node) {
126-
if (node >= MAX_NUMBER_OF_NODE_CERTIFICATES) {
135+
if (node >= numberOfNodes) {
127136
String message = String.format(
128137
"Cannot get certificate for node %d, number of created certificates for nodes is %d",
129138
node,
130-
MAX_NUMBER_OF_NODE_CERTIFICATES
139+
numberOfNodes
131140
);
132141
throw new RuntimeException(message);
133142
}
134143
}
135144

136145
private CertificateData createNodeCertificate(Integer node) {
137-
String subject = String.format("DC=de,L=test,O=node,OU=node,CN=node-%d.example.com", node);
146+
final var subject = String.format(NODE_SUBJECT_PATTERN, node);
138147
String domain = String.format("node-%d.example.com", node);
139148
CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS)
140149
.withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH)
@@ -150,8 +159,7 @@ public CertificateData issueUserCertificate(String organizationUnit, String user
150159
}
151160

152161
private CertificateData createLdapCertificate() {
153-
String subject = "DC=de,L=test,O=node,OU=node,CN=ldap.example.com";
154-
CertificateMetadata metadata = CertificateMetadata.basicMetadata(subject, CERTIFICATE_VALIDITY_DAYS)
162+
CertificateMetadata metadata = CertificateMetadata.basicMetadata(LDAP_SUBJECT, CERTIFICATE_VALIDITY_DAYS)
155163
.withKeyUsage(false, DIGITAL_SIGNATURE, NON_REPUDIATION, KEY_ENCIPHERMENT, CLIENT_AUTH, SERVER_AUTH)
156164
.withSubjectAlternativeName(null, List.of("localhost"), "127.0.0.1");
157165
return CertificatesIssuerFactory.rsaBaseCertificateIssuer().issueSignedCertificate(metadata, caCertificate);
@@ -164,7 +172,7 @@ public CertificateData getLdapCertificateData() {
164172
/**
165173
* It returns private key associated with node certificate returned by method {@link #getNodeCertificate(int)}
166174
*
167-
* @param node is a node index. It has to be less than {@link #MAX_NUMBER_OF_NODE_CERTIFICATES}
175+
* @param node is a node index. It has to be less than {@link #DEFAULT_NUMBER_OF_NODE_CERTIFICATES}
168176
* @param privateKeyPassword is a password used to encode private key, can be <code>null</code> to retrieve unencrypted key.
169177
* @return file which contains private key encoded in PEM format, defined
170178
* by <a href="https://www.rfc-editor.org/rfc/rfc1421.txt">RFC 1421</a>

src/integrationTest/java/org/opensearch/test/framework/cluster/LocalCluster.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ public void before() {
141141
}
142142

143143
for (Map.Entry<String, LocalCluster> entry : remotes.entrySet()) {
144-
@SuppressWarnings("resource")
145144
InetSocketAddress transportAddress = entry.getValue().localOpenSearchCluster.clusterManagerNode().getTransportAddress();
146145
String key = "cluster.remote." + entry.getKey() + ".seeds";
147146
String value = transportAddress.getHostString() + ":" + transportAddress.getPort();
@@ -509,7 +508,7 @@ public Builder defaultConfigurationInitDirectory(String defaultConfigurationInit
509508
public LocalCluster build() {
510509
try {
511510
if (testCertificates == null) {
512-
testCertificates = new TestCertificates();
511+
testCertificates = new TestCertificates(clusterManager.getNodes());
513512
}
514513
clusterName += "_" + num.incrementAndGet();
515514
Settings settings = nodeOverrideSettingsBuilder.build();

src/integrationTest/java/org/opensearch/test/framework/cluster/LocalOpenSearchCluster.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ public class LocalOpenSearchCluster {
105105

106106
private File snapshotDir;
107107

108+
private int nodeCounter = 0;
109+
108110
public LocalOpenSearchCluster(
109111
String clusterName,
110112
ClusterManager clusterManager,
@@ -163,7 +165,6 @@ public void start() throws Exception {
163165
this.initialClusterManagerHosts = toHostList(clusterManagerPorts);
164166

165167
started = true;
166-
167168
CompletableFuture<Void> clusterManagerNodeFuture = startNodes(
168169
clusterManager.getClusterManagerNodeSettings(),
169170
clusterManagerNodeTransportPorts,
@@ -195,7 +196,6 @@ public void start() throws Exception {
195196
log.info("Startup finished. Waiting for GREEN");
196197

197198
waitForCluster(ClusterHealthStatus.GREEN, TimeValue.timeValueSeconds(10), nodes.size());
198-
199199
log.info("Started: {}", this);
200200

201201
}
@@ -303,10 +303,10 @@ private CompletableFuture<Void> startNodes(
303303
List<CompletableFuture<StartStage>> futures = new ArrayList<>();
304304

305305
for (NodeSettings nodeSettings : nodeSettingList) {
306-
Node node = new Node(nodeSettings, transportPortIterator.next(), httpPortIterator.next());
306+
Node node = new Node(nodeCounter, nodeSettings, transportPortIterator.next(), httpPortIterator.next());
307307
futures.add(node.start());
308+
nodeCounter += 1;
308309
}
309-
310310
return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
311311
}
312312

@@ -386,8 +386,10 @@ public class Node implements OpenSearchClientProvider {
386386
private PluginAwareNode node;
387387
private boolean running = false;
388388
private boolean portCollision = false;
389+
private final int nodeNumber;
389390

390-
Node(NodeSettings nodeSettings, int transportPort, int httpPort) {
391+
Node(int nodeNumber, NodeSettings nodeSettings, int transportPort, int httpPort) {
392+
this.nodeNumber = nodeNumber;
391393
this.nodeName = createNextNodeName(requireNonNull(nodeSettings, "Node settings are required."));
392394
this.nodeSettings = nodeSettings;
393395
this.nodeHomeDir = new File(clusterHomeDir, nodeName);
@@ -517,7 +519,7 @@ private Settings getOpenSearchSettings() {
517519

518520
if (nodeSettingsSupplier != null) {
519521
// TODO node number
520-
return Settings.builder().put(settings).put(nodeSettingsSupplier.get(0)).build();
522+
return Settings.builder().put(settings).put(nodeSettingsSupplier.get(nodeNumber)).build();
521523
}
522524
return settings;
523525
}

src/main/java/org/opensearch/security/ssl/OpenSearchSecuritySSLPlugin.java

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,6 @@ public class OpenSearchSecuritySSLPlugin extends Plugin implements SystemIndexPl
134134
protected final SSLConfig SSLConfig;
135135
protected volatile ThreadPool threadPool;
136136

137-
// public OpenSearchSecuritySSLPlugin(final Settings settings, final Path configPath) {
138-
// this(settings, configPath, false);
139-
// }
140-
141137
@SuppressWarnings("removal")
142138
protected OpenSearchSecuritySSLPlugin(final Settings settings, final Path configPath, boolean disabled) {
143139

src/main/java/org/opensearch/security/ssl/SecurityKeyStore.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,25 @@
2323

2424
public interface SecurityKeyStore {
2525

26-
public SSLEngine createHTTPSSLEngine() throws SSLException;
26+
SSLEngine createHTTPSSLEngine() throws SSLException;
2727

28-
public SSLEngine createServerTransportSSLEngine() throws SSLException;
28+
SSLEngine createServerTransportSSLEngine() throws SSLException;
2929

30-
public SSLEngine createClientTransportSSLEngine(String peerHost, int peerPort) throws SSLException;
30+
SSLEngine createClientTransportSSLEngine(String peerHost, int peerPort) throws SSLException;
3131

32-
public String getHTTPProviderName();
32+
String getHTTPProviderName();
3333

34-
public String getTransportServerProviderName();
34+
String getTransportServerProviderName();
3535

36-
public String getTransportClientProviderName();
36+
String getTransportClientProviderName();
3737

38-
public String getSubjectAlternativeNames(X509Certificate cert);
38+
String getSubjectAlternativeNames(X509Certificate cert);
3939

40-
public void initHttpSSLConfig();
40+
void initHttpSSLConfig();
4141

42-
public void initTransportSSLConfig();
42+
void initTransportSSLConfig();
4343

44-
public X509Certificate[] getTransportCerts();
44+
X509Certificate[] getTransportCerts();
4545

46-
public X509Certificate[] getHttpCerts();
46+
X509Certificate[] getHttpCerts();
4747
}

0 commit comments

Comments
 (0)