Skip to content
This repository was archived by the owner on Sep 16, 2024. It is now read-only.

Commit f22a2f8

Browse files
authored
Merge pull request #464 from marklogic-community/feature/171-cloud-auth
DEVEXP-171: Added properties for cloud auth
2 parents 0239701 + d3e1310 commit f22a2f8

File tree

15 files changed

+262
-47
lines changed

15 files changed

+262
-47
lines changed

src/main/java/com/marklogic/appdeployer/AppConfig.java

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public class AppConfig {
7171
public static final String DEFAULT_PASSWORD = "admin";
7272

7373
private String host = DEFAULT_HOST;
74+
private String cloudApiKey;
7475

7576
private boolean catchDeployExceptions = false;
7677
private boolean catchUndeployExceptions = false;
@@ -97,9 +98,11 @@ public class AppConfig {
9798
private boolean restUseDefaultKeystore;
9899
private String restSslProtocol;
99100
private String restTrustManagementAlgorithm;
101+
private String restBasePath;
100102

101103
private Integer restPort = DEFAULT_PORT;
102104
private Integer testRestPort;
105+
private String testRestBasePath;
103106

104107
// Connection info for using the App Services client REST API - e.g. to load non-REST API modules
105108
private DatabaseClient.ConnectionType appServicesConnectionType;
@@ -116,6 +119,7 @@ public class AppConfig {
116119
private boolean appServicesUseDefaultKeystore;
117120
private String appServicesSslProtocol;
118121
private String appServicesTrustManagementAlgorithm;
122+
private String appServicesBasePath;
119123

120124
// These can all be set to override the default names that are generated off of the "name" attribute.
121125
private String groupName = DEFAULT_GROUP;
@@ -367,7 +371,11 @@ public DatabaseClient newDatabaseClient() {
367371
* @return
368372
*/
369373
public DatabaseClient newTestDatabaseClient() {
370-
return configuredDatabaseClientFactory.newDatabaseClient(newRestDatabaseClientConfig(getTestRestPort()));
374+
DatabaseClientConfig config = newRestDatabaseClientConfig(getTestRestPort());
375+
if (StringUtils.hasText(getTestRestBasePath())) {
376+
config.setBasePath(getTestRestBasePath());
377+
}
378+
return configuredDatabaseClientFactory.newDatabaseClient(config);
371379
}
372380

373381
public DatabaseClientConfig newRestDatabaseClientConfig(int port) {
@@ -377,6 +385,8 @@ public DatabaseClientConfig newRestDatabaseClientConfig(int port) {
377385
config.setConnectionType(restConnectionType);
378386
config.setExternalName(restExternalName);
379387
config.setSecurityContextType(restSecurityContextType);
388+
config.setCloudApiKey(cloudApiKey);
389+
config.setBasePath(restBasePath);
380390

381391
if (restUseDefaultKeystore) {
382392
config.setSslProtocol(StringUtils.hasText(restSslProtocol) ? restSslProtocol : SslUtil.DEFAULT_SSL_PROTOCOL);
@@ -417,6 +427,8 @@ public DatabaseClient newAppServicesDatabaseClient(String databaseName) {
417427
config.setDatabase(databaseName);
418428
config.setExternalName(appServicesExternalName);
419429
config.setSecurityContextType(appServicesSecurityContextType);
430+
config.setCloudApiKey(cloudApiKey);
431+
config.setBasePath(appServicesBasePath);
420432

421433
if (appServicesUseDefaultKeystore) {
422434
config.setSslProtocol(StringUtils.hasText(appServicesSslProtocol) ? appServicesSslProtocol : SslUtil.DEFAULT_SSL_PROTOCOL);
@@ -1451,4 +1463,36 @@ public String getModuleUriPrefix() {
14511463
public void setModuleUriPrefix(String moduleUriPrefix) {
14521464
this.moduleUriPrefix = moduleUriPrefix;
14531465
}
1466+
1467+
public String getCloudApiKey() {
1468+
return cloudApiKey;
1469+
}
1470+
1471+
public void setCloudApiKey(String cloudApiKey) {
1472+
this.cloudApiKey = cloudApiKey;
1473+
}
1474+
1475+
public String getRestBasePath() {
1476+
return restBasePath;
1477+
}
1478+
1479+
public void setRestBasePath(String restBasePath) {
1480+
this.restBasePath = restBasePath;
1481+
}
1482+
1483+
public String getAppServicesBasePath() {
1484+
return appServicesBasePath;
1485+
}
1486+
1487+
public void setAppServicesBasePath(String appServicesBasePath) {
1488+
this.appServicesBasePath = appServicesBasePath;
1489+
}
1490+
1491+
public String getTestRestBasePath() {
1492+
return testRestBasePath;
1493+
}
1494+
1495+
public void setTestRestBasePath(String testRestBasePath) {
1496+
this.testRestBasePath = testRestBasePath;
1497+
}
14541498
}

src/main/java/com/marklogic/appdeployer/DefaultAppConfigFactory.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ public void initialize() {
184184
config.setHost(prop);
185185
});
186186

187+
propertyConsumerMap.put("mlCloudApiKey", (config, prop) -> {
188+
logger.info("Setting cloud API key");
189+
config.setCloudApiKey(prop);
190+
});
191+
187192
/**
188193
* Defaults to port 8000. In rare cases, the ML App-Services app server will have been changed to listen on a
189194
* different port, in which case you can set this to that port.
@@ -251,6 +256,11 @@ public void initialize() {
251256
config.setAppServicesTrustManagementAlgorithm(prop);
252257
});
253258

259+
propertyConsumerMap.put("mlAppServicesBasePath", (config, prop) -> {
260+
logger.info("App-Services base path: " + prop);
261+
config.setAppServicesBasePath(prop);
262+
});
263+
254264
/**
255265
* Set this to true to prevent creating a REST API server by default.
256266
*/
@@ -304,6 +314,14 @@ public void initialize() {
304314
logger.info("REST external name: " + prop);
305315
config.setRestExternalName(prop);
306316
});
317+
propertyConsumerMap.put("mlRestBasePath", (config, prop) -> {
318+
logger.info("REST base path: " + prop);
319+
config.setRestBasePath(prop);
320+
});
321+
propertyConsumerMap.put("mlTestRestBasePath", (config, prop) -> {
322+
logger.info("Test REST base path: " + prop);
323+
config.setTestRestBasePath(prop);
324+
});
307325

308326
/**
309327
* When modules are loaded via the Client REST API, if the app server requires an SSL connection, then
@@ -373,7 +391,7 @@ public void initialize() {
373391
* If a test REST API server is created, it will use the following port.
374392
*/
375393
propertyConsumerMap.put("mlTestRestPort", (config, prop) -> {
376-
logger.info("App test REST port: " + prop);
394+
logger.info("Test REST port: " + prop);
377395
config.setTestRestPort(Integer.parseInt(prop));
378396
});
379397

src/main/java/com/marklogic/mgmt/DefaultManageConfigFactory.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,16 @@ public void initialize() {
7272
}
7373
});
7474

75+
propertyConsumerMap.put("mlCloudApiKey", (config, prop) -> {
76+
logger.info("Setting cloud API key");
77+
config.setCloudApiKey(prop);
78+
});
79+
80+
propertyConsumerMap.put("mlManageBasePath", (config, prop) -> {
81+
logger.info("Manage base path: " + prop);
82+
config.setBasePath(prop);
83+
});
84+
7585
propertyConsumerMap.put("mlManageScheme", (config, prop) -> {
7686
logger.info("Manage scheme: " + prop);
7787
config.setScheme(prop);

src/main/java/com/marklogic/mgmt/ManageClient.java

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,12 @@ public void setManageConfig(ManageConfig config) {
6262
logger.info(format("Initializing separate connection to Manage API with user '%s' that should have the 'manage-admin' and 'security' roles", securityUsername));
6363
}
6464

65-
RestConfig rc = new RestConfig(config.getHost(), config.getPort(), securityUsername, config.getSecurityPassword());
66-
rc.setScheme(config.getScheme());
67-
rc.setConfigureSimpleSsl(config.isConfigureSimpleSsl());
68-
rc.setHostnameVerifier(config.getHostnameVerifier());
69-
65+
RestConfig rc = new RestConfig(config);
66+
// Override settings based on the 3 "security user"-specific properties known by ManageConfig
67+
rc.setUsername(config.getSecurityUsername());
68+
rc.setPassword(config.getSecurityPassword());
7069
if (config.getSecuritySslContext() != null) {
7170
rc.setSslContext(config.getSecuritySslContext());
72-
} else {
73-
rc.setSslContext(config.getSslContext());
7471
}
7572

7673
this.securityUserRestTemplate = RestTemplateUtil.newRestTemplate(rc);
@@ -267,14 +264,14 @@ public HttpEntity<String> buildXmlEntity(String xml) {
267264
protected void logRequest(String path, String contentType, String method) {
268265
if (logger.isInfoEnabled()) {
269266
String username = manageConfig != null ? manageConfig.getUsername() : "(unknown)";
270-
logger.info(String.format("Sending %s %s request as user '%s' to path: %s", contentType, method, username, path));
267+
logger.info(String.format("Sending %s %s request as user '%s' to path: %s", contentType, method, username, buildUri(path)));
271268
}
272269
}
273270

274271
protected void logSecurityUserRequest(String path, String contentType, String method) {
275272
if (logger.isInfoEnabled()) {
276273
logger.info(String.format("Sending %s %s request as user '%s' (who should have the 'manage-admin' and 'security' roles) to path: %s",
277-
contentType, method, determineUsernameForSecurityUserRequest(), path));
274+
contentType, method, determineUsernameForSecurityUserRequest(), buildUri(path)));
278275
}
279276
}
280277

src/main/java/com/marklogic/mgmt/admin/AdminConfig.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ public AdminConfig(String host, int port, String username, String password) {
2020
super(host, port, username, password);
2121
}
2222

23-
public AdminConfig(AdminConfig other) {
23+
/**
24+
* Because this class adds no state and only sets sensible default values for connecting to MarkLogic's Admin app
25+
* server, this copy constructor only requires an instance of {@code RestConfig}.
26+
*
27+
* @param other
28+
*/
29+
public AdminConfig(RestConfig other) {
2430
super(other);
2531
}
2632
}

src/main/java/com/marklogic/mgmt/admin/AdminManager.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.marklogic.mgmt.AbstractManager;
44
import com.marklogic.rest.util.Fragment;
5+
import com.marklogic.rest.util.RestConfig;
56
import com.marklogic.rest.util.RestTemplateUtil;
67
import org.springframework.core.io.ByteArrayResource;
78
import org.springframework.core.io.Resource;
@@ -189,19 +190,21 @@ public void setSslFipsEnabled(final boolean enabled, final int appServicesPort)
189190
invokeActionRequiringRestart(new ActionRequiringRestart() {
190191
@Override
191192
public boolean execute() {
192-
RestTemplate rt = RestTemplateUtil.newRestTemplate(adminConfig.getHost(), appServicesPort,
193-
adminConfig.getUsername(), adminConfig.getPassword());
193+
RestConfig evalConfig = new RestConfig(adminConfig);
194+
evalConfig.setPort(appServicesPort);
195+
194196
HttpHeaders headers = new HttpHeaders();
195197
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
196198
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
197199
map.add("xquery", xquery);
198200
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map,
199201
headers);
200-
String url = format("http://%s:%d/v1/eval", adminConfig.getHost(), appServicesPort);
202+
201203
if (logger.isInfoEnabled()) {
202204
logger.info("Setting SSL FIPS enabled: " + enabled);
203205
}
204-
rt.exchange(url, HttpMethod.POST, entity, String.class);
206+
URI url = evalConfig.buildUri("/v1/eval");
207+
RestTemplateUtil.newRestTemplate(evalConfig).exchange(url, HttpMethod.POST, entity, String.class);
205208
if (logger.isInfoEnabled()) {
206209
logger.info("Finished setting SSL FIPS enabled: " + enabled);
207210
}

src/main/java/com/marklogic/mgmt/admin/DefaultAdminConfigFactory.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,17 @@ public void initialize() {
6868
}
6969
});
7070

71-
propertyConsumerMap.put("mlAdminScheme", (config, prop) -> {
71+
propertyConsumerMap.put("mlCloudApiKey", (config, prop) -> {
72+
logger.info("Setting cloud API key");
73+
config.setCloudApiKey(prop);
74+
});
75+
76+
propertyConsumerMap.put("mlAdminBasePath", (config, prop) -> {
77+
logger.info("Admin base path: " + prop);
78+
config.setBasePath(prop);
79+
});
80+
81+
propertyConsumerMap.put("mlAdminScheme", (config, prop) -> {
7282
logger.info("Admin interface scheme: " + prop);
7383
config.setScheme(prop);
7484
});

src/main/java/com/marklogic/mgmt/resource/clusters/ClusterManager.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
import com.marklogic.mgmt.AbstractManager;
44
import com.marklogic.mgmt.ManageClient;
5+
import com.marklogic.mgmt.ManageConfig;
56
import com.marklogic.mgmt.admin.ActionRequiringRestart;
67
import com.marklogic.mgmt.admin.AdminConfig;
78
import com.marklogic.mgmt.admin.AdminManager;
89
import com.marklogic.rest.util.Fragment;
10+
import com.marklogic.rest.util.RestConfig;
911
import org.springframework.web.client.ResourceAccessException;
1012

1113
public class ClusterManager extends AbstractManager {
@@ -85,7 +87,8 @@ public void addHost(AdminManager adminManager, String hostname) throws Exception
8587
public void addHost(AdminManager adminManager, String hostname, String group, String zone) throws Exception{
8688
AdminConfig adminConfig = adminManager.getAdminConfig();
8789

88-
AdminConfig joiningHostAdminConfig = new AdminConfig(hostname, 8001, adminConfig.getUsername(), adminConfig.getPassword());
90+
AdminConfig joiningHostAdminConfig = new AdminConfig(adminConfig);
91+
joiningHostAdminConfig.setHost(hostname);
8992
AdminManager joiningHostAdminManager = new AdminManager(joiningHostAdminConfig);
9093

9194
// get the joining host's configuration
@@ -111,13 +114,17 @@ public void addHost(AdminManager adminManager, String hostname, String group, St
111114

112115
/**
113116
* Removes the specified host from the cluster. Assumes connection information is of the host to remove
117+
*
114118
* @param hostname hostname of the server to remove from the cluster
115119
*/
116-
public void removeHost(String hostname){
117-
AdminConfig adminConfig = new AdminConfig(hostname, 8001, manageClient.getManageConfig().getUsername(), manageClient.getManageConfig().getPassword());
118-
AdminManager adminManager = new AdminManager(adminConfig);
119-
adminManager.leaveCluster();
120-
120+
public void removeHost(String hostname) {
121+
removeHost(hostname, 8001);
121122
}
122123

124+
public void removeHost(String hostname, int adminPort) {
125+
AdminConfig removeConfig = new AdminConfig(manageClient.getManageConfig());
126+
removeConfig.setHost(hostname);
127+
removeConfig.setPort(adminPort);
128+
new AdminManager(removeConfig).leaveCluster();
129+
}
123130
}

src/main/java/com/marklogic/rest/util/RestConfig.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ public class RestConfig {
1818
private int port;
1919
private String username;
2020
private String password;
21+
private String cloudApiKey;
22+
private String basePath;
2123
private String scheme = "http";
2224

2325
private boolean configureSimpleSsl;
@@ -45,6 +47,9 @@ public RestConfig(RestConfig other) {
4547
this.scheme = other.scheme;
4648
}
4749

50+
this.cloudApiKey = other.cloudApiKey;
51+
this.basePath = other.basePath;
52+
4853
this.configureSimpleSsl = other.configureSimpleSsl;
4954
this.useDefaultKeystore = other.useDefaultKeystore;
5055
this.sslProtocol = other.sslProtocol;
@@ -58,10 +63,12 @@ public DatabaseClientBuilder newDatabaseClientBuilder() {
5863
DatabaseClientBuilder builder = new DatabaseClientBuilder()
5964
.withHost(getHost())
6065
.withPort(getPort())
66+
.withBasePath(getBasePath())
6167
// TODO Will support all types before the 4.5.0 release
62-
.withSecurityContextType("digest")
68+
.withSecurityContextType(StringUtils.hasText(getCloudApiKey()) ? "cloud" : "digest")
6369
.withUsername(getUsername())
64-
.withPassword(getPassword());
70+
.withPassword(getPassword())
71+
.withCloudApiKey(getCloudApiKey());
6572

6673
if (getSslContext() != null) {
6774
builder.withSSLContext(getSslContext());
@@ -105,8 +112,18 @@ public String toString() {
105112
* @return
106113
*/
107114
public URI buildUri(String path) {
115+
String basePathToAppend = "";
116+
if (basePath != null) {
117+
if (!basePath.startsWith("/")) {
118+
basePathToAppend = "/";
119+
}
120+
basePathToAppend += basePath;
121+
if (path.startsWith("/") && basePathToAppend.endsWith("/")) {
122+
basePathToAppend = basePathToAppend.substring(0, basePathToAppend.length() - 1);
123+
}
124+
}
108125
try {
109-
return new URI(String.format("%s://%s:%d%s", getScheme(), getHost(), getPort(), path.replace(" ", "+")));
126+
return new URI(String.format("%s://%s:%d%s%s", getScheme(), getHost(), getPort(), basePathToAppend, path.replace(" ", "+")));
110127
} catch (URISyntaxException ex) {
111128
throw new RuntimeException("Unable to build URI for path: " + path + "; cause: " + ex.getMessage(), ex);
112129
}
@@ -213,4 +230,20 @@ public DatabaseClientFactory.SSLHostnameVerifier getSslHostnameVerifier() {
213230
public void setSslHostnameVerifier(DatabaseClientFactory.SSLHostnameVerifier sslHostnameVerifier) {
214231
this.sslHostnameVerifier = sslHostnameVerifier;
215232
}
233+
234+
public String getCloudApiKey() {
235+
return cloudApiKey;
236+
}
237+
238+
public void setCloudApiKey(String cloudApiKey) {
239+
this.cloudApiKey = cloudApiKey;
240+
}
241+
242+
public String getBasePath() {
243+
return basePath;
244+
}
245+
246+
public void setBasePath(String basePath) {
247+
this.basePath = basePath;
248+
}
216249
}

0 commit comments

Comments
 (0)