Repository: knox Updated Branches: refs/heads/master 8ba9d9235 -> cfb0ce18c
KNOX-1322 - Support configuration property to forcibly treat topologies as read-only Project: http://git-wip-us.apache.org/repos/asf/knox/repo Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/cfb0ce18 Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/cfb0ce18 Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/cfb0ce18 Branch: refs/heads/master Commit: cfb0ce18c9948eef01f7f9b1a0d20f2e80fb227f Parents: 8ba9d92 Author: Phil Zampino <pzamp...@apache.org> Authored: Thu May 17 18:04:14 2018 -0400 Committer: Phil Zampino <pzamp...@apache.org> Committed: Thu May 17 18:04:14 2018 -0400 ---------------------------------------------------------------------- .../gateway/config/impl/GatewayConfigImpl.java | 29 ++++++++-- .../config/impl/GatewayConfigImplTest.java | 33 +++++++++++ .../service/admin/TopologiesResource.java | 34 +++++++----- .../knox/gateway/config/GatewayConfig.java | 17 ++++-- .../apache/knox/gateway/GatewayTestConfig.java | 14 +++++ .../gateway/GatewayAdminTopologyFuncTest.java | 58 ++++++++++++++++++++ 6 files changed, 160 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/knox/blob/cfb0ce18/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java ---------------------------------------------------------------------- diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java index 56440f2..9ad0432 100644 --- a/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java +++ b/gateway-server/src/main/java/org/apache/knox/gateway/config/impl/GatewayConfigImpl.java @@ -163,12 +163,11 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig { public static final String GATEWAY_PORT_MAPPING_ENABLED = GATEWAY_PORT_MAPPING_PREFIX + "enabled"; /** - * Comma seperated list of MIME Types to be compressed by Knox on the way out. + * Comma-separated list of MIME Types to be compressed by Knox on the way out. * * @since 0.12 */ - public static final String MIME_TYPES_TO_COMPRESS = GATEWAY_CONFIG_FILE_PREFIX - + ".gzip.compress.mime.types"; + public static final String MIME_TYPES_TO_COMPRESS = GATEWAY_CONFIG_FILE_PREFIX + ".gzip.compress.mime.types"; public static final String CLUSTER_CONFIG_MONITOR_PREFIX = GATEWAY_CONFIG_FILE_PREFIX + ".cluster.config.monitor."; public static final String CLUSTER_CONFIG_MONITOR_INTERVAL_SUFFIX = ".interval"; @@ -195,6 +194,13 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig { public static final String REMOTE_ALIAS_SERVICE_ENABLED = GATEWAY_CONFIG_FILE_PREFIX + ".remote.alias.service.enabled"; + /** + * Comma-separated list of topology names, which should be forcibly treated as read-only. + * @since 1.1.0 + */ + public static final String READ_ONLY_OVERRIDE_TOPOLOGIES = + GATEWAY_CONFIG_FILE_PREFIX + ".read.only.override.topologies"; + /* Websocket defaults */ public static final boolean DEFAULT_WEBSOCKET_FEATURE_ENABLED = false; public static final int DEFAULT_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE = Integer.MAX_VALUE;; @@ -210,13 +216,12 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig { public static final boolean DEFAULT_REMOTE_ALIAS_SERVICE_ENABLED = true; - /** * Default list of MIME Type to be compressed. * @since 0.12 */ - public static final String DEFAULT_MIME_TYPES_TO_COMPRESS = "text/html, text/plain, text/xml, text/css, " - + "application/javascript, application/x-javascript, text/javascript"; + public static final String DEFAULT_MIME_TYPES_TO_COMPRESS = + "text/html, text/plain, text/xml, text/css, application/javascript, application/x-javascript, text/javascript"; public static final String COOKIE_SCOPING_ENABLED = GATEWAY_CONFIG_FILE_PREFIX + ".scope.cookies.feature.enabled"; public static final boolean DEFAULT_COOKIE_SCOPING_FEATURE_ENABLED = false; @@ -1025,4 +1030,16 @@ public class GatewayConfigImpl extends Configuration implements GatewayConfig { return Boolean.parseBoolean(result); } + @Override + public List<String> getReadOnlyOverrideTopologyNames() { + List<String> topologyNames = new ArrayList<>(); + + String value = get(READ_ONLY_OVERRIDE_TOPOLOGIES); + if (value != null && !value.isEmpty()) { + topologyNames.addAll(Arrays.asList(value.trim().split("\\s*,\\s*"))); + } + + return topologyNames; + } + } http://git-wip-us.apache.org/repos/asf/knox/blob/cfb0ce18/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java ---------------------------------------------------------------------- diff --git a/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java b/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java index 4187214..d1089c0 100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/config/impl/GatewayConfigImplTest.java @@ -257,7 +257,40 @@ public class GatewayConfigImplTest { assertEquals(TimeUnit.SECONDS.toMillis(20), config.getHttpClientConnectionTimeout()); assertEquals(TimeUnit.SECONDS.toMillis(20), config.getHttpClientSocketTimeout()); + } + + + // KNOX-1322 + @Test + public void testGetReadOnlyOverrideTopologyNames() { + GatewayConfigImpl config = new GatewayConfigImpl(); + List<String> names = config.getReadOnlyOverrideTopologyNames(); + assertNotNull(names); + assertTrue(names.isEmpty()); + + config.set(GatewayConfigImpl.READ_ONLY_OVERRIDE_TOPOLOGIES, ""); + names = config.getReadOnlyOverrideTopologyNames(); + assertNotNull(names); + assertTrue(names.isEmpty()); + + config.set(GatewayConfigImpl.READ_ONLY_OVERRIDE_TOPOLOGIES, "admin"); + names = config.getReadOnlyOverrideTopologyNames(); + assertNotNull(names); + assertFalse(names.isEmpty()); + assertEquals(1, names.size()); + assertEquals("admin", names.get(0)); + + config.set(GatewayConfigImpl.READ_ONLY_OVERRIDE_TOPOLOGIES, "admin, sandbox, test ,default"); + names = config.getReadOnlyOverrideTopologyNames(); + assertNotNull(names); + assertFalse(names.isEmpty()); + assertEquals(4, names.size()); + assertTrue(names.contains("admin")); + assertTrue(names.contains("sandbox")); + assertTrue(names.contains("test")); + assertTrue(names.contains("default")); } + } http://git-wip-us.apache.org/repos/asf/knox/blob/cfb0ce18/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java ---------------------------------------------------------------------- diff --git a/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java b/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java index 3b8f2fe..b29fcbc 100644 --- a/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java +++ b/gateway-service-admin/src/main/java/org/apache/knox/gateway/service/admin/TopologiesResource.java @@ -102,19 +102,27 @@ public class TopologiesResource { @Produces({APPLICATION_JSON, APPLICATION_XML}) @Path(SINGLE_TOPOLOGY_API_PATH) public Topology getTopology(@PathParam("id") String id) { - GatewayServices services = (GatewayServices) request.getServletContext() - .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); - GatewayConfig config = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE); + GatewayServices services = + (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); + GatewayConfig config = + (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE); TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE); for (org.apache.knox.gateway.topology.Topology t : ts.getTopologies()) { - if(t.getName().equals(id)) { + if (t.getName().equals(id)) { try { t.setUri(new URI( buildURI(t, config, request) )); } catch (URISyntaxException se) { t.setUri(null); } + + // For any read-only override topology, mark it as generated to discourage modification. + List<String> ambariManagedTopos = config.getReadOnlyOverrideTopologyNames(); + if (ambariManagedTopos.contains(t.getName())) { + t.setGenerated(true); + } + return BeanConverter.getTopology(t); } } @@ -125,25 +133,21 @@ public class TopologiesResource { @Produces({APPLICATION_JSON, APPLICATION_XML}) @Path(TOPOLOGIES_API_PATH) public SimpleTopologyWrapper getTopologies() { - GatewayServices services = (GatewayServices) request.getServletContext() - .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); - + GatewayServices services = + (GatewayServices) request.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE); + GatewayConfig config = + (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE); TopologyService ts = services.getService(GatewayServices.TOPOLOGY_SERVICE); ArrayList<SimpleTopology> st = new ArrayList<SimpleTopology>(); - GatewayConfig conf = (GatewayConfig) request.getServletContext().getAttribute(GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE); - for (org.apache.knox.gateway.topology.Topology t : ts.getTopologies()) { - st.add(getSimpleTopology(t, conf)); + st.add(getSimpleTopology(t, config)); } + st.sort(new TopologyComparator()); - Collections.sort(st, new TopologyComparator()); SimpleTopologyWrapper stw = new SimpleTopologyWrapper(); - - for(SimpleTopology t : st){ - stw.topologies.add(t); - } + stw.topologies.addAll(st); return stw; http://git-wip-us.apache.org/repos/asf/knox/blob/cfb0ce18/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java ---------------------------------------------------------------------- diff --git a/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java index 980f602..ab6a473 100644 --- a/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java +++ b/gateway-spi/src/main/java/org/apache/knox/gateway/config/GatewayConfig.java @@ -373,11 +373,20 @@ public interface GatewayConfig { /** * Returns whether the Remote Alias Service is enabled or not. - * This value also depends on whether remote registry is enabled or not. - * if it is enabled then this option takes effect else this option has no - * effect. - * @return + * + * This value also depends on whether the remote configuration registry is enabled or not. + * If it is enabled, then this option takes effect, else this option has no effect. + * + * @return true, if the remote alias service is enabled; otherwise, false; */ boolean isRemoteAliasServiceEnabled(); + /** + * Get the list of those topology names which should be treated as read-only, regardless of their actual read-write + * status. + * + * @return A list of the names of those topologies which should be treated as read-only. + */ + List<String> getReadOnlyOverrideTopologyNames(); + } http://git-wip-us.apache.org/repos/asf/knox/blob/cfb0ce18/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java ---------------------------------------------------------------------- diff --git a/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java b/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java index 1b198c9..cb2de7f 100644 --- a/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java +++ b/gateway-test-release-utils/src/main/java/org/apache/knox/gateway/GatewayTestConfig.java @@ -20,11 +20,13 @@ package org.apache.knox.gateway; import org.apache.commons.lang.StringUtils; import org.apache.hadoop.conf.Configuration; import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.config.impl.GatewayConfigImpl; import java.io.File; import java.net.InetSocketAddress; import java.net.UnknownHostException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -679,4 +681,16 @@ public class GatewayTestConfig extends Configuration implements GatewayConfig { return false; } + @Override + public List<String> getReadOnlyOverrideTopologyNames() { + List<String> readOnly = new ArrayList<>(); + + String value = get(GatewayConfigImpl.READ_ONLY_OVERRIDE_TOPOLOGIES); + if (value != null && !value.isEmpty()) { + readOnly.addAll(Arrays.asList(value.trim().split("\\s*,\\s*"))); + } + + return readOnly; + } + } http://git-wip-us.apache.org/repos/asf/knox/blob/cfb0ce18/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java ---------------------------------------------------------------------- diff --git a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java index 0bb0b23..3bd0605 100644 --- a/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java +++ b/gateway-test/src/test/java/org/apache/knox/gateway/GatewayAdminTopologyFuncTest.java @@ -36,6 +36,7 @@ import io.restassured.http.ContentType; import com.mycila.xmltool.XMLDoc; import com.mycila.xmltool.XMLTag; import org.apache.knox.gateway.config.GatewayConfig; +import org.apache.knox.gateway.config.impl.GatewayConfigImpl; import org.apache.knox.gateway.services.DefaultGatewayServices; import org.apache.knox.gateway.services.GatewayServices; import org.apache.knox.gateway.services.ServiceLifecycleException; @@ -454,6 +455,63 @@ public class GatewayAdminTopologyFuncTest { LOG_EXIT(); } + + /** + * KNOX-1322 + */ + @Test( timeout = TestUtils.LONG_TIMEOUT ) + public void testTopologyObjectForcedReadOnly() throws Exception { + LOG_ENTER(); + + final String testTopologyName = "test-cluster"; + + // First, verify that without any special config, the topology is NOT marked as generated (i.e., read-only) + validateGeneratedElement(testTopologyName, "false"); + + try { + gateway.stop(); + + // Update gateway config, such that the test topology should be marked as generated (i.e., read-only) + GatewayTestConfig conf = new GatewayTestConfig(); + conf.set(GatewayConfigImpl.READ_ONLY_OVERRIDE_TOPOLOGIES, testTopologyName); + setupGateway(conf); + + // Verify that the generate element reflects the configuration change + validateGeneratedElement(testTopologyName, "true"); + + // Verify that another topology is unaffected by the configuration + validateGeneratedElement("admin", "false"); + + } finally { + // Restart the gateway with old settings. + gateway.stop(); + setupGateway(new GatewayTestConfig()); + } + + LOG_EXIT(); + } + + + /** + * Access the specified topology, and validate the value of the generated element therein. + * + * @param topologyName The name of the topology to validate + * @param expectedValue The expected value of the generated element. + */ + private void validateGeneratedElement(String topologyName, String expectedValue) throws Exception { + String testClusterTopology = given().auth().preemptive().basic("admin", "admin-password") + .header("Accept", MediaType.APPLICATION_XML) + .then() + .statusCode(HttpStatus.SC_OK) + .when().get(clusterUrl + "/api/v1/topologies/" + topologyName) + .thenReturn().getBody().asString(); + assertNotNull(testClusterTopology); + Document doc = XmlUtils.readXml(new InputSource(new StringReader(testClusterTopology))); + assertNotNull(doc); + assertThat(doc, hasXPath("/topology/generated", is(expectedValue))); + } + + @Test( timeout = TestUtils.LONG_TIMEOUT ) public void testPositiveAuthorization() throws ClassNotFoundException{ LOG_ENTER();