Skip to content

Commit 654a2d2

Browse files
rahulvudutalaSanjeevani19
authored andcommitted
DHFPROD-9530: Access HubCentral on ML Cloud
1 parent 3ed1257 commit 654a2d2

File tree

6 files changed

+190
-20
lines changed

6 files changed

+190
-20
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.marklogic.hub.central;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
public class CloudParameters {
7+
public static String ML_HOST = "localhost";
8+
public static int ML_REVERSE_PROXY_PORT = 443;
9+
public static String AUTHENTICATION_TYPE = "";
10+
public static String HC_BASE_PATH = "";
11+
public static String STAGING_BASE_PATH = "";
12+
public static String FINAL_BASE_PATH = "";
13+
public static String JOB_BASE_PATH = "";
14+
public static String MANAGE_BASE_PATH = "";
15+
public static String APP_SERVICES_BASE_PATH = "";
16+
public static String ADMIN_BASE_PATH = "";
17+
18+
public static void updateCloudParameters(Map<String, String> cloudProperties) {
19+
ML_HOST = cloudProperties.get("mlHost");
20+
AUTHENTICATION_TYPE = cloudProperties.get("mlAuthentication");
21+
HC_BASE_PATH = cloudProperties.get("mlHcBasePath");
22+
STAGING_BASE_PATH = cloudProperties.get("mlStagingBasePath");
23+
FINAL_BASE_PATH = cloudProperties.get("mlFinalBasePath");
24+
JOB_BASE_PATH = cloudProperties.get("mlJobBasePath");
25+
MANAGE_BASE_PATH = cloudProperties.get("mlManageBasePath");
26+
APP_SERVICES_BASE_PATH = cloudProperties.get("mlAppServicesBasePath");
27+
ADMIN_BASE_PATH = cloudProperties.get("mlAdminBasePath");
28+
}
29+
}

marklogic-data-hub-central/src/main/java/com/marklogic/hub/central/HubCentral.java

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.marklogic.hub.central;
22

33
import com.marklogic.client.DatabaseClient;
4+
import com.marklogic.client.DatabaseClientFactory;
45
import com.marklogic.client.ext.ConfiguredDatabaseClientFactory;
56
import com.marklogic.client.ext.DatabaseClientConfig;
67
import com.marklogic.client.ext.DefaultConfiguredDatabaseClientFactory;
78
import com.marklogic.client.ext.SecurityContextType;
89
import com.marklogic.client.ext.helper.LoggingObject;
10+
import com.marklogic.client.ext.modulesloader.ssl.SimpleX509TrustManager;
911
import com.marklogic.hub.impl.HubConfigImpl;
1012
import com.marklogic.mgmt.util.PropertySource;
1113
import org.springframework.beans.factory.InitializingBean;
@@ -14,6 +16,7 @@
1416
import org.springframework.core.env.Environment;
1517
import org.springframework.stereotype.Component;
1618

19+
import javax.net.ssl.SSLContext;
1720
import java.util.Properties;
1821

1922
/**
@@ -55,6 +58,38 @@ public HubConfigImpl newHubConfig(String username, String password) {
5558
return hubConfig;
5659
}
5760

61+
/**
62+
* This constructs a HubConfigImpl by starting with the default property values in HubConfigImpl, and then applying
63+
* properties based on the Spring environment of this application plus the username/password provided by the user
64+
* logging in.
65+
*
66+
* @param cloudApiKey
67+
* @return
68+
*/
69+
public HubConfigImpl newHubConfig(String cloudApiKey) {
70+
HubConfigImpl hubConfig = new HubConfigImpl();
71+
DatabaseClient client = getStagingDbClient(cloudApiKey);
72+
Properties primaryProperties = hubConfig.getHubPropertiesFromDb(client);
73+
primaryProperties.setProperty("mlCloudApiKey", cloudApiKey);
74+
primaryProperties.setProperty("mlStagingBasePath", CloudParameters.STAGING_BASE_PATH);
75+
primaryProperties.setProperty("mlFinalBasePath", CloudParameters.FINAL_BASE_PATH);
76+
primaryProperties.setProperty("mlJobBasePath", CloudParameters.JOB_BASE_PATH);
77+
78+
primaryProperties.setProperty("mlManageBasePath", CloudParameters.MANAGE_BASE_PATH);
79+
primaryProperties.setProperty("mlAppServicesBasePath", CloudParameters.APP_SERVICES_BASE_PATH);
80+
primaryProperties.setProperty("mlAdminBasePath", CloudParameters.ADMIN_BASE_PATH);
81+
82+
primaryProperties.setProperty("mlAdminSimpleSsl", "true");
83+
primaryProperties.setProperty("mlManageSimpleSsl", "true");
84+
primaryProperties.setProperty("mlAppServicesSimpleSsl", "true");
85+
86+
primaryProperties.setProperty("mlAuthentication", CloudParameters.AUTHENTICATION_TYPE);
87+
primaryProperties.setProperty("mlSslHostnameVerifier", "ANY");
88+
primaryProperties.setProperty("mlManageAuthentication", "cloud");
89+
hubConfig.applyProperties(buildPropertySource(primaryProperties));
90+
return hubConfig;
91+
}
92+
5893
/**
5994
* Construct a PropertySource based on the properties in the Spring Boot environment plus the given username and
6095
* password, which are supplied when a user authenticates.
@@ -70,7 +105,10 @@ protected PropertySource buildPropertySource(String username, String password) {
70105
protected PropertySource buildPropertySource(String username, String password, Properties primaryProperties) {
71106
primaryProperties.setProperty("mlUsername", username);
72107
primaryProperties.setProperty("mlPassword", password);
108+
return buildPropertySource(primaryProperties);
109+
}
73110

111+
protected PropertySource buildPropertySource(Properties primaryProperties) {
74112
return propertyName -> {
75113
String value = primaryProperties.getProperty(propertyName);
76114
if (!propertyName.equals("mlUsername") && !propertyName.equals("mlPassword") && environment.getProperty(propertyName) != null) {
@@ -81,20 +119,53 @@ protected PropertySource buildPropertySource(String username, String password, P
81119
}
82120

83121
private DatabaseClient getStagingDbClient(String username, String password) {
84-
ConfiguredDatabaseClientFactory configuredDatabaseClientFactory = new DefaultConfiguredDatabaseClientFactory();
85-
DatabaseClientConfig config = new DatabaseClientConfig("localhost", 8010, username, password);
86-
config.setSecurityContextType(SecurityContextType.valueOf("DIGEST"));
122+
DatabaseClientConfig config = new DatabaseClientConfig();
123+
config.setUsername(username);
124+
config.setPassword(password);
125+
config.setCloudApiKey("");
126+
return getStagingDbClient(config);
127+
}
87128

88-
if(environment.getProperty("mlHost") != null) {
89-
config.setHost(environment.getProperty("mlHost"));
90-
}
129+
private DatabaseClient getStagingDbClient(String cloudApiKey) {
130+
DatabaseClientConfig config = new DatabaseClientConfig();
131+
config.setCloudApiKey(cloudApiKey);
91132

92-
if(environment.getProperty("mlStagingPort") != null) {
93-
config.setPort(Integer.parseInt(environment.getProperty("mlStagingPort")));
94-
}
133+
SSLContext stagingSslContext = SimpleX509TrustManager.newSSLContext();
134+
DatabaseClientFactory.SSLHostnameVerifier stagingSslHostnameVerifier = DatabaseClientFactory.SSLHostnameVerifier.ANY;
135+
SimpleX509TrustManager stagingTrustManager = new SimpleX509TrustManager();
136+
137+
config.setSslHostnameVerifier(stagingSslHostnameVerifier);
138+
config.setSslContext(stagingSslContext);
139+
config.setCertFile(null);
140+
config.setCertPassword(null);
141+
config.setExternalName(null);
142+
config.setTrustManager(stagingTrustManager);
143+
config.setUsername("");
144+
config.setPassword("");
95145

96-
if(environment.getProperty("mlStagingAuth") != null) {
97-
config.setSecurityContextType(SecurityContextType.valueOf(environment.getProperty("mlStagingAuth").toUpperCase()));
146+
return getStagingDbClient(config);
147+
}
148+
149+
private DatabaseClient getStagingDbClient(DatabaseClientConfig config) {
150+
ConfiguredDatabaseClientFactory configuredDatabaseClientFactory = new DefaultConfiguredDatabaseClientFactory();
151+
if(CloudParameters.AUTHENTICATION_TYPE.equals("cloud")) {
152+
config.setHost(CloudParameters.ML_HOST);
153+
config.setPort(CloudParameters.ML_REVERSE_PROXY_PORT);
154+
config.setBasePath(CloudParameters.STAGING_BASE_PATH);
155+
config.setSecurityContextType(SecurityContextType.CLOUD);
156+
} else {
157+
config.setHost(environment.getProperty("mlHost") != null ?
158+
environment.getProperty("mlHost") :
159+
"localhost"
160+
);
161+
config.setPort(environment.getProperty("mlStagingPort") != null ?
162+
Integer.parseInt(environment.getProperty("mlStagingPort")) :
163+
8010
164+
);
165+
config.setSecurityContextType(environment.getProperty("mlStagingAuth") != null ?
166+
SecurityContextType.valueOf(environment.getProperty("mlStagingAuth").toUpperCase()) :
167+
SecurityContextType.valueOf("DIGEST")
168+
);
98169
}
99170
// Need to work on SSL
100171
return configuredDatabaseClientFactory.newDatabaseClient(config);

marklogic-data-hub-central/src/main/java/com/marklogic/hub/central/auth/AuthenticationFilter.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
import com.fasterxml.jackson.databind.JsonNode;
1919
import com.fasterxml.jackson.databind.ObjectMapper;
2020
import com.marklogic.client.FailedRequestException;
21+
import com.marklogic.hub.central.CloudParameters;
2122
import com.marklogic.hub.central.HttpSessionHubClientProvider;
2223
import com.marklogic.hub.central.HubCentral;
2324
import com.marklogic.hub.dataservices.HubCentralService;
2425
import com.marklogic.hub.impl.HubConfigImpl;
26+
import org.apache.commons.lang3.StringUtils;
2527
import org.springframework.security.authentication.AuthenticationServiceException;
2628
import org.springframework.security.authentication.BadCredentialsException;
2729
import org.springframework.security.core.Authentication;
@@ -30,7 +32,6 @@
3032
import org.springframework.security.core.authority.SimpleGrantedAuthority;
3133
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
3234
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
33-
import org.springframework.util.StringUtils;
3435

3536
import javax.servlet.http.HttpServletRequest;
3637
import javax.servlet.http.HttpServletResponse;
@@ -79,15 +80,19 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ
7980
* @param password
8081
*/
8182
protected AuthenticationToken authenticateUser(String username, String password) {
82-
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
83-
throw new BadCredentialsException("Unauthorized");
84-
}
8583

86-
username = username.trim();
84+
if(!CloudParameters.AUTHENTICATION_TYPE.equalsIgnoreCase("cloud")) {
85+
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
86+
throw new BadCredentialsException("Unauthorized");
87+
}
88+
89+
username = username.trim();
90+
91+
HubConfigImpl hubClientConfig = hubCentral.newHubConfig(username, password);
92+
hubClientProvider.setHubClientConfig(hubClientConfig);
93+
hubClientProvider.setHubClientDelegate(hubClientConfig.newHubClient());
94+
}
8795

88-
HubConfigImpl hubClientConfig = hubCentral.newHubConfig(username, password);
89-
hubClientProvider.setHubClientConfig(hubClientConfig);
90-
hubClientProvider.setHubClientDelegate(hubClientConfig.newHubClient());
9196
List<GrantedAuthority> authorities = new ArrayList<>();
9297
JsonNode response;
9398
try {
Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,84 @@
11
package com.marklogic.hub.central.controllers;
22

3+
import com.marklogic.hub.central.CloudParameters;
4+
import com.marklogic.hub.central.HttpSessionHubClientProvider;
5+
import com.marklogic.hub.central.HubCentral;
6+
import com.marklogic.hub.impl.HubConfigImpl;
7+
import org.springframework.beans.factory.annotation.Autowired;
38
import org.springframework.boot.web.servlet.error.ErrorController;
9+
import org.springframework.core.env.Environment;
410
import org.springframework.stereotype.Controller;
511
import org.springframework.web.bind.annotation.RequestMapping;
612

13+
import javax.servlet.http.Cookie;
14+
import javax.servlet.http.HttpServletRequest;
15+
import javax.servlet.http.HttpServletResponse;
16+
import java.util.Collections;
17+
import java.util.HashMap;
18+
import java.util.Map;
19+
import java.util.stream.Collectors;
20+
721
@Controller
822
public class SinglePageAppController implements ErrorController {
923

24+
@Autowired
25+
HubCentral hubCentral;
26+
27+
@Autowired
28+
HttpSessionHubClientProvider hubClientProvider;
29+
30+
@Autowired
31+
Environment environment;
32+
33+
1034
/**
1135
* Used when running HC as an executable war file; not used when running it locally for development purposes, as the
1236
* local Node server handles this route instead.
1337
*
1438
* @return
1539
*/
1640
@RequestMapping(value = {"/"})
17-
public String index() {
41+
public String index(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
42+
if(environment.getProperty("mlAuthentication").equalsIgnoreCase("cloud")) {
43+
Map<String, String> headers = getHeadersMap(httpServletRequest);
44+
CloudParameters.updateCloudParameters(headers);
45+
createHubConfigurations(headers.getOrDefault("mlCloudApiKey", ""));
46+
addCookiesToResponse(httpServletResponse);
47+
}
1848
return "forward:index.html";
1949
}
2050

51+
private void createHubConfigurations(String cloudApikey) {
52+
HubConfigImpl hubClientConfig = hubCentral.newHubConfig(cloudApikey);
53+
hubClientProvider.setHubClientConfig(hubClientConfig);
54+
hubClientProvider.setHubClientDelegate(hubClientConfig.newHubClient());
55+
}
56+
57+
private Map<String, String> getHeadersMap(HttpServletRequest httpServletRequest) {
58+
Map<String, String> headers = new HashMap<>();
59+
Collections.list(httpServletRequest.getHeaderNames()).stream()
60+
.collect(Collectors.toMap(h -> h, httpServletRequest::getHeader));
61+
// These values are for testing
62+
addHeadersFromCloudForTesting(headers);
63+
return headers;
64+
}
65+
66+
private void addHeadersFromCloudForTesting(Map<String, String> headers) {
67+
headers.put("mlCloudApiKey", "hub-developer:password");
68+
headers.put("mlHost", "localhost");
69+
headers.put("mlAuthentication", "cloud");
70+
headers.put("mlManageAuthentication", "cloud");
71+
headers.put("mlHcBasePath", "/hc");
72+
headers.put("mlStagingBasePath", "/data-hub/staging");
73+
headers.put("mlFinalBasePath", "/data-hub/final");
74+
headers.put("mlJobBasePath", "/data-hub/jobs");
75+
headers.put("mlManageBasePath", "/local/manage");
76+
headers.put("mlAppServicesBasePath", "/local/app-services");
77+
headers.put("mlAdminBasePath", "/local/admin");
78+
}
79+
80+
private void addCookiesToResponse(HttpServletResponse response) {
81+
response.addCookie(new Cookie("mlHcBasePath", "/hc"));
82+
response.addCookie(new Cookie("mlAuthentication", "cloud"));
83+
}
2184
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mlAuthentication=cloud

marklogic-data-hub-central/ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"name": "marklogic-data-hub-central",
33
"version": "0.1.0",
44
"private": true,
5+
"homepage": "./",
56
"dependencies": {
67
"@emotion/css": "^11.1.3",
78
"@fortawesome/fontawesome-svg-core": "^1.2.28",

0 commit comments

Comments
 (0)