From 02198093c6d62aaacb7544a336a8bf3e3ccc42eb Mon Sep 17 00:00:00 2001 From: Corneil du Plessis Date: Tue, 10 Dec 2024 15:36:25 +0200 Subject: [PATCH] Fix duplicate output for skipper and dataflow and some output frames. Refactor DefaultAuthoritiesMapperTests for JUnit 5 conventions. Rename DataflowOAuthIT methods for JUnit 5 conventions. Add testcontainers-keycloak to dependency management in spring-cloud-dataflow-parent. --- .../DefaultAuthoritiesMapperTests.java | 214 ++++++++-------- spring-cloud-dataflow-parent/pom.xml | 6 + spring-cloud-dataflow-server/pom.xml | 1 - .../src/main/resources/application.yml | 1 - .../test/db/AbstractDataflowTests.java | 10 +- .../test/db/container/ContainerUtils.java | 10 +- .../test/db/container/DataflowCluster.java | 231 +++++++++--------- .../test/oauth/DataflowOAuthIT.java | 110 ++++----- 8 files changed, 302 insertions(+), 281 deletions(-) diff --git a/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/test/java/org/springframework/cloud/common/security/support/DefaultAuthoritiesMapperTests.java b/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/test/java/org/springframework/cloud/common/security/support/DefaultAuthoritiesMapperTests.java index 0a66e732a3..bd3e7c3dc0 100644 --- a/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/test/java/org/springframework/cloud/common/security/support/DefaultAuthoritiesMapperTests.java +++ b/spring-cloud-common-security-config/spring-cloud-common-security-config-web/src/test/java/org/springframework/cloud/common/security/support/DefaultAuthoritiesMapperTests.java @@ -34,17 +34,17 @@ /** * @author Gunnar Hillert */ -public class DefaultAuthoritiesMapperTests { +class DefaultAuthoritiesMapperTests { @Test - public void testNullConstructor() throws Exception { + void nullConstructor() throws Exception { assertThatThrownBy(() -> { new DefaultAuthoritiesMapper(null, ""); }).isInstanceOf(IllegalArgumentException.class).hasMessageContaining("providerRoleMappings must not be null."); } @Test - public void testMapScopesToAuthoritiesWithNullParameters() throws Exception { + void mapScopesToAuthoritiesWithNullParameters() throws Exception { DefaultAuthoritiesMapper authoritiesMapper = new DefaultAuthoritiesMapper(Collections.emptyMap(), ""); assertThatThrownBy(() -> { @@ -56,18 +56,19 @@ public void testMapScopesToAuthoritiesWithNullParameters() throws Exception { } @Test - public void testThat7AuthoritiesAreReturned() throws Exception { + void that7AuthoritiesAreReturned() throws Exception { DefaultAuthoritiesMapper authoritiesMapper = new DefaultAuthoritiesMapper("uaa", false); Set authorities = authoritiesMapper.mapScopesToAuthorities("uaa", Collections.emptySet(), null); assertThat(authorities).hasSize(7); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_MANAGE", "ROLE_CREATE", "ROLE_VIEW", "ROLE_DEPLOY", "ROLE_MODIFY", "ROLE_SCHEDULE", "ROLE_DESTROY"); } @Test - public void testEmptyMapConstructor() throws Exception { + void emptyMapConstructor() throws Exception { Set scopes = new HashSet<>(); scopes.add("dataflow.manage"); scopes.add("dataflow.view"); @@ -77,12 +78,13 @@ public void testEmptyMapConstructor() throws Exception { Collection authorities = authoritiesMapper.mapScopesToAuthorities("uaa", scopes, null); assertThat(authorities).hasSize(3); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_MANAGE", "ROLE_CREATE", "ROLE_VIEW"); } @Test - public void testMapConstructorWithIncompleteRoleMappings() throws Exception { + void mmapConstructorWithIncompleteRoleMappings() throws Exception { ProviderRoleMapping roleMapping = new ProviderRoleMapping(); roleMapping.setMapOauthScopes(true); roleMapping.addRoleMapping("ROLE_MANAGE", "foo-scope-in-oauth"); @@ -93,107 +95,115 @@ public void testMapConstructorWithIncompleteRoleMappings() throws Exception { } @Test - public void testThat3MappedAuthoritiesAreReturned() throws Exception { - Map roleMappings = new HashMap<>(); - roleMappings.put("ROLE_MANAGE", "dataflow_manage"); - roleMappings.put("ROLE_VIEW", "dataflow_view"); - roleMappings.put("ROLE_CREATE", "dataflow_create"); - roleMappings.put("ROLE_MODIFY", "dataflow_modify"); - roleMappings.put("ROLE_DEPLOY", "dataflow_deploy"); - roleMappings.put("ROLE_DESTROY", "dataflow_destroy"); - roleMappings.put("ROLE_SCHEDULE", "dataflow_schedule"); + void that3MappedAuthoritiesAreReturned() throws Exception { + Map roleMappings = Map.of( + "ROLE_MANAGE", "dataflow_manage", + "ROLE_VIEW", "dataflow_view", + "ROLE_CREATE", "dataflow_create", + "ROLE_MODIFY", "dataflow_modify", + "ROLE_DEPLOY", "dataflow_deploy", + "ROLE_DESTROY", "dataflow_destroy", + "ROLE_SCHEDULE", "dataflow_schedule" + ); ProviderRoleMapping providerRoleMapping = new ProviderRoleMapping(); providerRoleMapping.setMapOauthScopes(true); providerRoleMapping.getRoleMappings().putAll(roleMappings); - Set roles = new HashSet<>(); - roles.add("dataflow_manage"); - roles.add("dataflow_view"); - roles.add("dataflow_deploy"); + Set roles = Set.of("dataflow_manage", "dataflow_view", "dataflow_deploy"); DefaultAuthoritiesMapper defaultAuthoritiesMapper = new DefaultAuthoritiesMapper("uaa", providerRoleMapping); Collection authorities = defaultAuthoritiesMapper.mapScopesToAuthorities("uaa", roles, null); assertThat(authorities).hasSize(3); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_DEPLOY", "ROLE_MANAGE", "ROLE_VIEW"); } - public void testThat7MappedAuthoritiesAreReturned() throws Exception { - Map roleMappings = new HashMap<>(); - roleMappings.put("ROLE_MANAGE", "foo-manage"); - roleMappings.put("ROLE_VIEW", "bar-view"); - roleMappings.put("ROLE_CREATE", "blubba-create"); - roleMappings.put("ROLE_MODIFY", "foo-modify"); - roleMappings.put("ROLE_DEPLOY", "foo-deploy"); - roleMappings.put("ROLE_DESTROY", "foo-destroy"); - roleMappings.put("ROLE_SCHEDULE", "foo-schedule"); + @Test + void that7MappedAuthoritiesAreReturned() throws Exception { + Map roleMappings = Map.of( + "ROLE_MANAGE", "foo-manage", + "ROLE_VIEW", "bar-view", + "ROLE_CREATE", "blubba-create", + "ROLE_MODIFY", "foo-modify", + "ROLE_DEPLOY", "foo-deploy", + "ROLE_DESTROY", "foo-destroy", + "ROLE_SCHEDULE", "foo-schedule" + ); ProviderRoleMapping providerRoleMapping = new ProviderRoleMapping(); providerRoleMapping.setMapOauthScopes(true); providerRoleMapping.getRoleMappings().putAll(roleMappings); - Set scopes = new HashSet<>(); - scopes.add("foo-manage"); - scopes.add("bar-view"); - scopes.add("blubba-create"); - scopes.add("foo-modify"); - scopes.add("foo-deploy"); - scopes.add("foo-destroy"); - scopes.add("foo-schedule"); + Set scopes = Set.of( + "foo-manage", + "bar-view", + "blubba-create", + "foo-modify", + "foo-deploy", + "foo-destroy", + "foo-schedule" + ); DefaultAuthoritiesMapper defaultAuthoritiesMapper = new DefaultAuthoritiesMapper("uaa", providerRoleMapping); Collection authorities = defaultAuthoritiesMapper.mapScopesToAuthorities("uaa", scopes, null); assertThat(authorities).hasSize(7); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_CREATE", "ROLE_DEPLOY", "ROLE_DESTROY", "ROLE_MANAGE", "ROLE_MODIFY", "ROLE_SCHEDULE", "ROLE_VIEW"); } @Test - public void testThat3MappedAuthoritiesAreReturnedForDefaultMapping() throws Exception { + void that3MappedAuthoritiesAreReturnedForDefaultMapping() throws Exception { ProviderRoleMapping providerRoleMapping = new ProviderRoleMapping(); providerRoleMapping.setMapOauthScopes(true); - Set scopes = new HashSet<>(); - scopes.add("dataflow.manage"); - scopes.add("dataflow.view"); - scopes.add("dataflow.create"); + Set scopes = Set.of( + "dataflow.manage", + "dataflow.view", + "dataflow.create" + ); DefaultAuthoritiesMapper defaultAuthoritiesExtractor = new DefaultAuthoritiesMapper("uaa", providerRoleMapping); Collection authorities = defaultAuthoritiesExtractor.mapScopesToAuthorities("uaa", scopes, null); assertThat(authorities).hasSize(3); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_MANAGE", "ROLE_CREATE", "ROLE_VIEW"); } @Test - public void testThat7MappedAuthoritiesAreReturnedForDefaultMappingWithoutMappingScopes() throws Exception { - Set scopes = new HashSet<>(); - scopes.add("dataflow.manage"); - scopes.add("dataflow.view"); - scopes.add("dataflow.create"); + void that7MappedAuthoritiesAreReturnedForDefaultMappingWithoutMappingScopes() throws Exception { + Set scopes = Set.of( + "dataflow.manage", + "dataflow.view", + "dataflow.create" + ); DefaultAuthoritiesMapper defaultAuthoritiesExtractor = new DefaultAuthoritiesMapper("uaa", false); Collection authorities = defaultAuthoritiesExtractor.mapScopesToAuthorities("uaa", scopes, null); assertThat(authorities).hasSize(7); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_CREATE", "ROLE_DEPLOY", "ROLE_DESTROY", "ROLE_MANAGE", "ROLE_MODIFY", "ROLE_SCHEDULE", "ROLE_VIEW"); } @Test - public void testThat2MappedAuthoritiesAreReturnedForDefaultMapping() throws Exception { - Set scopes = new HashSet<>(); - scopes.add("dataflow.view"); - scopes.add("dataflow.create"); + void that2MappedAuthoritiesAreReturnedForDefaultMapping() throws Exception { + Set scopes = Set.of( + "dataflow.view", + "dataflow.create" + ); DefaultAuthoritiesMapper defaultAuthoritiesExtractor = new DefaultAuthoritiesMapper("uaa", true); Collection authorities = defaultAuthoritiesExtractor.mapScopesToAuthorities("uaa", @@ -205,19 +215,18 @@ public void testThat2MappedAuthoritiesAreReturnedForDefaultMapping() throws Exce } @Test - public void testThat7AuthoritiesAreReturnedAndOneOAuthScopeCoversMultipleServerRoles() throws Exception { - Map roleMappings = new HashMap<>(); - roleMappings.put("ROLE_MANAGE", "foo-manage"); - roleMappings.put("ROLE_VIEW", "foo-manage"); - roleMappings.put("ROLE_DEPLOY", "foo-manage"); - roleMappings.put("ROLE_DESTROY", "foo-manage"); - roleMappings.put("ROLE_MODIFY", "foo-manage"); - roleMappings.put("ROLE_SCHEDULE", "foo-manage"); - roleMappings.put("ROLE_CREATE", "blubba-create"); - - Set scopes = new HashSet<>(); - scopes.add("foo-manage"); - scopes.add("blubba-create"); + void that7AuthoritiesAreReturnedAndOneOAuthScopeCoversMultipleServerRoles() throws Exception { + Map roleMappings = Map.of( + "ROLE_MANAGE", "foo-manage", + "ROLE_VIEW", "foo-manage", + "ROLE_DEPLOY", "foo-manage", + "ROLE_DESTROY", "foo-manage", + "ROLE_MODIFY", "foo-manage", + "ROLE_SCHEDULE", "foo-manage", + "ROLE_CREATE", "blubba-create" + ); + + Set scopes = Set.of("foo-manage", "blubba-create"); DefaultAuthoritiesMapper defaultAuthoritiesExtractor = new DefaultAuthoritiesMapper("uaa", true, roleMappings); Collection authorities = defaultAuthoritiesExtractor.mapScopesToAuthorities("uaa", @@ -230,61 +239,64 @@ public void testThat7AuthoritiesAreReturnedAndOneOAuthScopeCoversMultipleServerR } @Test - public void testThatUriStyleScopeRemovesLeadingPart() throws Exception { - Map roleMappings = new HashMap<>(); - roleMappings.put("ROLE_MANAGE", "foo-manage"); - roleMappings.put("ROLE_VIEW", "foo-manage"); - roleMappings.put("ROLE_DEPLOY", "foo-manage"); - roleMappings.put("ROLE_DESTROY", "foo-manage"); - roleMappings.put("ROLE_MODIFY", "foo-manage"); - roleMappings.put("ROLE_SCHEDULE", "foo-manage"); - roleMappings.put("ROLE_CREATE", "blubba-create"); - - Set scopes = new HashSet<>(); - scopes.add("api://foobar/foo-manage"); - scopes.add("blubba-create"); + void thatUriStyleScopeRemovesLeadingPart() throws Exception { + Map roleMappings = Map.of( + "ROLE_MANAGE", "foo-manage", + "ROLE_VIEW", "foo-manage", + "ROLE_DEPLOY", "foo-manage", + "ROLE_DESTROY", "foo-manage", + "ROLE_MODIFY", "foo-manage", + "ROLE_SCHEDULE", "foo-manage", + "ROLE_CREATE", "blubba-create" + ); + + Set scopes = Set.of("api://foobar/foo-manage", "blubba-create"); DefaultAuthoritiesMapper defaultAuthoritiesExtractor = new DefaultAuthoritiesMapper("uaa", true, roleMappings); Collection authorities = defaultAuthoritiesExtractor.mapScopesToAuthorities("uaa", scopes, null); assertThat(authorities).hasSize(7); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_CREATE", "ROLE_DEPLOY", "ROLE_DESTROY", "ROLE_MANAGE", "ROLE_MODIFY", "ROLE_SCHEDULE", "ROLE_VIEW"); } @Test - public void testThatUriStyleScopeParsingCanBeDisabled() throws Exception { - Map roleMappings = new HashMap<>(); - roleMappings.put("ROLE_MANAGE", "/ROLE/2000803042"); - roleMappings.put("ROLE_VIEW", "/ROLE/2000803036"); - roleMappings.put("ROLE_DEPLOY", "/ROLE/2000803039"); - roleMappings.put("ROLE_DESTROY", "/ROLE/20008030340"); - roleMappings.put("ROLE_MODIFY", "/ROLE/2000803037"); - roleMappings.put("ROLE_SCHEDULE", "/ROLE/2000803038"); - roleMappings.put("ROLE_CREATE", "/ROLE/2000803041"); + void thatUriStyleScopeParsingCanBeDisabled() throws Exception { + Map roleMappings = Map.of( + "ROLE_MANAGE", "/ROLE/2000803042", + "ROLE_VIEW", "/ROLE/2000803036", + "ROLE_DEPLOY", "/ROLE/2000803039", + "ROLE_DESTROY", "/ROLE/20008030340", + "ROLE_MODIFY", "/ROLE/2000803037", + "ROLE_SCHEDULE", "/ROLE/2000803038", + "ROLE_CREATE", "/ROLE/2000803041" + ); ProviderRoleMapping providerRoleMapping = new ProviderRoleMapping(); providerRoleMapping.setMapOauthScopes(true); providerRoleMapping.setParseOauthScopePathParts(false); providerRoleMapping.getRoleMappings().putAll(roleMappings); - Set scopes = new HashSet<>(); - scopes.add("/ROLE/2000803042"); - scopes.add("/ROLE/2000803036"); - scopes.add("/ROLE/2000803039"); - scopes.add("/ROLE/20008030340"); - scopes.add("/ROLE/2000803037"); - scopes.add("/ROLE/2000803038"); - scopes.add("/ROLE/2000803041"); + Set scopes = Set.of( + "/ROLE/2000803042", + "/ROLE/2000803036", + "/ROLE/2000803039", + "/ROLE/20008030340", + "/ROLE/2000803037", + "/ROLE/2000803038", + "/ROLE/2000803041" + ); DefaultAuthoritiesMapper defaultAuthoritiesMapper = new DefaultAuthoritiesMapper("uaa", providerRoleMapping); Collection authorities = defaultAuthoritiesMapper.mapScopesToAuthorities("uaa", scopes, null); assertThat(authorities).hasSize(7); - assertThat(authorities.stream().map(authority -> authority.getAuthority()).collect(Collectors.toList())) + assertThat(authorities) + .extracting(GrantedAuthority::getAuthority) .containsExactlyInAnyOrder("ROLE_CREATE", "ROLE_DEPLOY", "ROLE_DESTROY", "ROLE_MANAGE", "ROLE_MODIFY", "ROLE_SCHEDULE", "ROLE_VIEW"); } diff --git a/spring-cloud-dataflow-parent/pom.xml b/spring-cloud-dataflow-parent/pom.xml index a573ebf0a7..0fdbd5b1ac 100644 --- a/spring-cloud-dataflow-parent/pom.xml +++ b/spring-cloud-dataflow-parent/pom.xml @@ -62,6 +62,7 @@ 21.9.0.0 11.5.9.0 + 3.4.0 20240303 1.1.2 @@ -257,6 +258,11 @@ pom import + + com.github.dasniko + testcontainers-keycloak + ${testcontainers-keycloak.version} + diff --git a/spring-cloud-dataflow-server/pom.xml b/spring-cloud-dataflow-server/pom.xml index 8b61a44d1e..7931b9c049 100644 --- a/spring-cloud-dataflow-server/pom.xml +++ b/spring-cloud-dataflow-server/pom.xml @@ -112,7 +112,6 @@ com.github.dasniko testcontainers-keycloak - 3.4.0 test diff --git a/spring-cloud-dataflow-server/src/main/resources/application.yml b/spring-cloud-dataflow-server/src/main/resources/application.yml index 6b38177c16..2c72b96e67 100644 --- a/spring-cloud-dataflow-server/src/main/resources/application.yml +++ b/spring-cloud-dataflow-server/src/main/resources/application.yml @@ -28,7 +28,6 @@ spring: url: "{repository}/org/springframework/cloud/spring-cloud-dataflow-shell/{version}/spring-cloud-dataflow-shell-{version}.jar" checksum-sha1-url: "{repository}/org/springframework/cloud/spring-cloud-dataflow-shell/{version}/spring-cloud-dataflow-shell-{version}.jar.sha1" checksum-sha256-url: "{repository}/org/springframework/cloud/spring-cloud-dataflow-shell/{version}/spring-cloud-dataflow-shell-{version}.jar.sha256" - jpa: hibernate: ddl-auto: none diff --git a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/AbstractDataflowTests.java b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/AbstractDataflowTests.java index 5455cfb302..0d37bec796 100644 --- a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/AbstractDataflowTests.java +++ b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/AbstractDataflowTests.java @@ -58,7 +58,7 @@ protected static class EmptyConfig { public final static String SKIPPER_IMAGE_PREFIX = "springcloud/spring-cloud-skipper-server:"; - public final static List DATAFLOW_CONTAINERS = Arrays.asList( + public final static List DATAFLOW_CONTAINERS = List.of( ClusterContainer.from(TagNames.DATAFLOW_2_7, DATAFLOW_IMAGE_PREFIX + "2.7.2"), ClusterContainer.from(TagNames.DATAFLOW_2_8, DATAFLOW_IMAGE_PREFIX + "2.8.4"), ClusterContainer.from(TagNames.DATAFLOW_2_9, DATAFLOW_IMAGE_PREFIX + "2.9.6"), @@ -67,7 +67,7 @@ protected static class EmptyConfig { ClusterContainer.from(TagNames.DATAFLOW_3_0, DATAFLOW_IMAGE_PREFIX + "3.0.0") ); - public final static List SKIPPER_CONTAINERS = Arrays.asList( + public final static List SKIPPER_CONTAINERS = List.of( ClusterContainer.from(TagNames.SKIPPER_2_6, SKIPPER_IMAGE_PREFIX + "2.6.2"), ClusterContainer.from(TagNames.SKIPPER_2_7, SKIPPER_IMAGE_PREFIX + "2.7.4"), ClusterContainer.from(TagNames.SKIPPER_2_8, SKIPPER_IMAGE_PREFIX + "2.8.6"), @@ -76,7 +76,7 @@ protected static class EmptyConfig { ClusterContainer.from(TagNames.SKIPPER_3_0, SKIPPER_IMAGE_PREFIX + "3.0.0") ); - public final static List DATABASE_CONTAINERS = Arrays.asList( + public final static List DATABASE_CONTAINERS = List.of( ClusterContainer.from(TagNames.POSTGRES_10, "postgres:10", TagNames.POSTGRES), ClusterContainer.from(TagNames.POSTGRES_14, "postgres:14", TagNames.POSTGRES_14), ClusterContainer.from(TagNames.MARIADB_10_4, "mariadb:10.4", TagNames.MARIADB), @@ -90,10 +90,10 @@ protected static class EmptyConfig { ClusterContainer.from(TagNames.DB2_11_5_8_0, "icr.io/db2_community/db2:11.5.8.0", TagNames.DB2) ); - public final static List OAUTH_CONTAINERS = Arrays.asList( + public final static List OAUTH_CONTAINERS = List.of( ClusterContainer.from(TagNames.UAA_4_32, "springcloud/scdf-uaa-test:4.32", TagNames.UAA), ClusterContainer.from(TagNames.KEYCLOAK_25, "quay.io/keycloak/keycloak:25.0", TagNames.KEYCLOAK), - ClusterContainer.from(TagNames.KEYCLOAK_26, "quay.io/keycloak/keycloak:26.0", TagNames.KEYCLOAK) + ClusterContainer.from(TagNames.KEYCLOAK_26, "quay.io/keycloak/keycloak:26.0", TagNames.KEYCLOAK) ); @Autowired diff --git a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/ContainerUtils.java b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/ContainerUtils.java index 0bd52338a9..4e0b3f4e51 100644 --- a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/ContainerUtils.java +++ b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/ContainerUtils.java @@ -33,11 +33,15 @@ public class ContainerUtils { public static void output(String container, OutputFrame outputFrame) { switch (outputFrame.getType()) { case STDOUT: - logger.info("{}:{}", container, outputFrame.getUtf8String()); + logger.info("{}:{}", container, outputFrame.getUtf8StringWithoutLineEnding()); + break; case STDERR: - logger.error("{}:{}", container, outputFrame.getUtf8String()); + logger.error("{}:{}", container, outputFrame.getUtf8StringWithoutLineEnding()); + break; case END: - logger.info("{}:END:{}", container, outputFrame.getUtf8String()); + // don't log logger.info("{}:END:{}", container, outputFrame.getUtf8StringWithoutLineEnding()); + break; + } } diff --git a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/DataflowCluster.java b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/DataflowCluster.java index 37daa32880..c63343922c 100644 --- a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/DataflowCluster.java +++ b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/db/container/DataflowCluster.java @@ -31,7 +31,6 @@ import org.testcontainers.containers.Network; import org.testcontainers.containers.OracleContainer; import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.containers.output.Slf4jLogConsumer; import org.testcontainers.lifecycle.Startable; import org.springframework.cloud.dataflow.integration.test.tags.TagNames; @@ -194,7 +193,7 @@ public void startIdentityProvider(String id) { Assert.notNull(clusterContainer, String.format("Unknown oauth %s", id)); GenericContainer oauthContainer; - if(id.startsWith(TagNames.KEYCLOAK)) { + if (id.startsWith(TagNames.KEYCLOAK)) { KeycloakContainer keycloakContainer = new KeycloakContainer(clusterContainer.image) .withRealmImportFiles("/dataflow-realm.json", "/dataflow-users-0.json") .withAdminUsername("admin") @@ -207,11 +206,11 @@ public void startIdentityProvider(String id) { } oauthContainer.withNetworkAliases("oauth"); oauthContainer.withNetwork(network); - oauthContainer.withLogConsumer(new Slf4jLogConsumer(logger).withPrefix("oauth")); + oauthContainer.withLogConsumer(outputFrame -> ContainerUtils.output("oauth", outputFrame)); oauthContainer.start(); if(id.startsWith(TagNames.KEYCLOAK)) { String authServerUrl = ((KeycloakContainer) oauthContainer).getAuthServerUrl(); - logger.info("keycloak:authServerUrl=" + authServerUrl); + logger.info("keycloak using authServerUrl=" + authServerUrl); } runningOauth = oauthContainer; } @@ -414,66 +413,73 @@ private SkipperContainer buildSkipperContainer( } if (oauthContainer != null) { - if(oauthContainer.getDockerImageName().contains(TagNames.UAA)) { - String oauthUrlPrefix = "http://oauth:8099/uaa"; - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.map-oauth-scopes", "true"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_CREATE", "dataflow.create"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DEPLOY", "dataflow.deploy"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DESTROY", "dataflow.destroy"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MANAGE", "dataflow.manage"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MODIFY", "dataflow.modify"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_SCHEDULE", "dataflow.schedule"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_VIEW", "dataflow.view"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_REDIRECT_URI", "{baseUrl}/login/oauth2/code/{registrationId}"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_AUTHORIZATION_GRANT_TYPE", "authorization_code"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_ID", "dataflow"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_SECRET", "secret"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_SCOPE", "openid,dataflow.create,dataflow.deploy,dataflow.destroy,dataflow.manage,dataflow.modify,dataflow.schedule,dataflow.view"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_JWK_SET_URI", oauthUrlPrefix + "/token_keys"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_TOKEN_URI", oauthUrlPrefix + "/oauth/token"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_INFO_URI", oauthUrlPrefix + "/userinfo"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_NAME_ATTRIBUTE", "user_name"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_AUTHORIZATION_URI", oauthUrlPrefix + "/oauth/authorize"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTION_URI", oauthUrlPrefix + "/introspect"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_ID", "dataflow"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_SECRET", "secret"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECK_TOKEN_ACCESS", "isAuthenticated()"); + if(oauthContainer.getDockerImageName().contains(TagNames.KEYCLOAK)) { + configureSkipperForKeycloak(skipperContainer); } else { - String oauthUrlPrefix = "http://oauth:8080"; - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.map-oauth-scopes", "false"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.map-group-claims", "false"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_CREATE", "dataflow_create"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DEPLOY", "dataflow_deploy"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DESTROY", "dataflow_destroy"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MANAGE", "dataflow_manage"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MODIFY", "dataflow_modify"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_SCHEDULE", "dataflow_schedule"); - skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_VIEW", "dataflow_view"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_REDIRECTURI", "{baseUrl}/login/oauth2/code/{registrationId}"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_AUTHORIZATIONGRANTTYPE", "authorization_code"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTID", "dataflow"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTSECRET", "secret"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTAUTHENTICATIONMETHOD", "post"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_SCOPE", "openid, roles"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_ISSUERURI", oauthUrlPrefix + "/realms/dataflow"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_JWKSETURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/certs"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_TOKENURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USERINFOURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/userinfo"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_AUTHORIZATIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/auth"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USER_NAME_ATTRIBUTE", "user_name"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token/introspect"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTID", "dataflow"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTSECRET", "090RucamvekrMLyGHMr4lkHX9xhAlsqK"); - skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECKTOKENACCESS", "isAuthenticated()"); + configureSkipperForUAA(skipperContainer); } } - skipperContainer.withLogConsumer(new Slf4jLogConsumer(logger).withPrefix("skipper")); skipperContainer.withNetworkAliases("skipper"); skipperContainer.withNetwork(network); return skipperContainer; } + private static void configureSkipperForUAA(SkipperContainer skipperContainer) { + String oauthUrlPrefix = "http://oauth:8099/uaa"; + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.map-oauth-scopes", "true"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_CREATE", "dataflow.create"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DEPLOY", "dataflow.deploy"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DESTROY", "dataflow.destroy"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MANAGE", "dataflow.manage"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MODIFY", "dataflow.modify"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_SCHEDULE", "dataflow.schedule"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_VIEW", "dataflow.view"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_REDIRECT_URI", "{baseUrl}/login/oauth2/code/{registrationId}"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_AUTHORIZATION_GRANT_TYPE", "authorization_code"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_ID", "dataflow"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_SECRET", "secret"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_SCOPE", "openid,dataflow.create,dataflow.deploy,dataflow.destroy,dataflow.manage,dataflow.modify,dataflow.schedule,dataflow.view"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_JWK_SET_URI", oauthUrlPrefix + "/token_keys"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_TOKEN_URI", oauthUrlPrefix + "/oauth/token"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_INFO_URI", oauthUrlPrefix + "/userinfo"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_NAME_ATTRIBUTE", "user_name"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_AUTHORIZATION_URI", oauthUrlPrefix + "/oauth/authorize"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTION_URI", oauthUrlPrefix + "/introspect"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_ID", "dataflow"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_SECRET", "secret"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECK_TOKEN_ACCESS", "isAuthenticated()"); + } + + private static void configureSkipperForKeycloak(SkipperContainer skipperContainer) { + String oauthUrlPrefix = "http://oauth:8080"; + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.map-oauth-scopes", "false"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.map-group-claims", "false"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_CREATE", "dataflow_create"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DEPLOY", "dataflow_deploy"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DESTROY", "dataflow_destroy"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MANAGE", "dataflow_manage"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MODIFY", "dataflow_modify"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_SCHEDULE", "dataflow_schedule"); + skipperContainer.withEnv("spring.cloud.skipper.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_VIEW", "dataflow_view"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_REDIRECTURI", "{baseUrl}/login/oauth2/code/{registrationId}"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_AUTHORIZATIONGRANTTYPE", "authorization_code"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTID", "dataflow"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTSECRET", "secret"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTAUTHENTICATIONMETHOD", "post"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_SCOPE", "openid, roles"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_ISSUERURI", oauthUrlPrefix + "/realms/dataflow"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_JWKSETURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/certs"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_TOKENURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USERINFOURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/userinfo"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_AUTHORIZATIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/auth"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USER_NAME_ATTRIBUTE", "user_name"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token/introspect"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTID", "dataflow"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTSECRET", "090RucamvekrMLyGHMr4lkHX9xhAlsqK"); + skipperContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECKTOKENACCESS", "isAuthenticated()"); + } + private DataflowContainer buildDataflowContainer( ClusterContainer clusterContainer, JdbcDatabaseContainer databaseContainer, GenericContainer oauthContainer, @@ -507,72 +513,77 @@ private DataflowContainer buildDataflowContainer( dataflowContainer.withEnv("SPRING_DATASOURCE_URL", databaseContainer.getJdbcUrl()); } } - dataflowContainer.withEnv("SPRING_CLOUD_SKIPPER_CLIENT_SERVER_URI", String.format("http://%s:%s/api", "skipper", SKIPPER_PORT)); + dataflowContainer.withEnv("SPRING_CLOUD_SKIPPER_CLIENT_SERVER_URI", String.format("http://skipper:%s/api", SKIPPER_PORT)); if (oauthContainer != null) { - if(oauthContainer.getDockerImageName().contains(TagNames.UAA)) { - String oauthUrlPrefix = "http://oauth:" + UAA_PORT + "/uaa"; - dataflowContainer.withEnv("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY", "DEBUG"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.map-oauth-scopes", "true"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_CREATE", "dataflow.create"); - dataflowContainer.withEnv( "spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DEPLOY", "dataflow.deploy"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DESTROY", "dataflow.destroy"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MANAGE", "dataflow.manage"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MODIFY", "dataflow.modify"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_SCHEDULE", "dataflow.schedule"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_VIEW", "dataflow.view"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_REDIRECT_URI", "{baseUrl}/login/oauth2/code/{registrationId}"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_AUTHORIZATION_GRANT_TYPE", "authorization_code"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_ID", "dataflow"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_SECRET", "secret"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_SCOPE", "openid,dataflow.create,dataflow.deploy,dataflow.destroy,dataflow.manage,dataflow.modify,dataflow.schedule,dataflow.view"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_JWK_SET_URI", oauthUrlPrefix + "/token_keys"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_TOKEN_URI", oauthUrlPrefix + "/oauth/token"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_INFO_URI", oauthUrlPrefix + "/userinfo"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_NAME_ATTRIBUTE", "user_name"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_AUTHORIZATION_URI", oauthUrlPrefix + "/oauth/authorize"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTION_URI", oauthUrlPrefix + "/introspect"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_ID", "dataflow"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_SECRET", "secret"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECK_TOKEN_ACCESS", "isAuthenticated()"); + if(oauthContainer.getDockerImageName().contains(TagNames.KEYCLOAK)) { + configureDataflowForKeycloak(dataflowContainer); } else { - String oauthUrlPrefix = "http://oauth:" + KEYCLOAK_PORT; - // dataflowContainer.withEnv("LOGGING_LEVEL_ROOT", "DEBUG"); - dataflowContainer.withEnv("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY", "DEBUG"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.map-oauth-scopes", "false"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.map-group-claims", "false"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_CREATE", "dataflow_create"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DEPLOY", "dataflow_deploy"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DESTROY", "dataflow_destroy"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MANAGE", "dataflow_manage"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MODIFY", "dataflow_modify"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_SCHEDULE", "dataflow_schedule"); - dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_VIEW", "dataflow_view"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_REDIRECTURI", "{baseUrl}/login/oauth2/code/{registrationId}"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_AUTHORIZATIONGRANTTYPE", "authorization_code"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTID", "dataflow"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTSECRET", "090RucamvekrMLyGHMr4lkHX9xhAlsqK"); - // dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTAUTHENTICATIONMETHOD", "post"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_SCOPE", "openid,roles"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_ISSUERURI", oauthUrlPrefix + "/realms/dataflow"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_JWKSETURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/certs"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_TOKENURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USERINFOURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/userinfo"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_AUTHORIZATIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/auth"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USERNAMEATTRIBUTE", "user_name"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token/introspect"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTID", "dataflow"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTSECRET", "090RucamvekrMLyGHMr4lkHX9xhAlsqK"); - dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECKTOKENACCESS", "isAuthenticated()"); + configureDataflowForUAA(dataflowContainer); } } - dataflowContainer.withLogConsumer(new Slf4jLogConsumer(logger).withPrefix("dataflow")); dataflowContainer.withNetworkAliases("dataflow"); dataflowContainer.withNetwork(network); return dataflowContainer; } + private void configureDataflowForKeycloak(DataflowContainer dataflowContainer) { + String oauthUrlPrefix = "http://oauth:" + KEYCLOAK_PORT; + dataflowContainer.withEnv("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY", "DEBUG"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.map-oauth-scopes", "false"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.map-group-claims", "false"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_CREATE", "dataflow_create"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DEPLOY", "dataflow_deploy"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_DESTROY", "dataflow_destroy"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MANAGE", "dataflow_manage"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_MODIFY", "dataflow_modify"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_SCHEDULE", "dataflow_schedule"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.keycloak.role-mappings.ROLE_VIEW", "dataflow_view"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_REDIRECTURI", "{baseUrl}/login/oauth2/code/{registrationId}"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_AUTHORIZATIONGRANTTYPE", "authorization_code"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTID", "dataflow"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_CLIENTSECRET", "090RucamvekrMLyGHMr4lkHX9xhAlsqK"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KEYCLOAK_SCOPE", "openid,roles"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_ISSUERURI", oauthUrlPrefix + "/realms/dataflow"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_JWKSETURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/certs"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_TOKENURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USERINFOURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/userinfo"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_AUTHORIZATIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/auth"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_KEYCLOAK_USERNAMEATTRIBUTE", "user_name"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTIONURI", oauthUrlPrefix + "/realms/dataflow/protocol/openid-connect/token/introspect"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTID", "dataflow"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENTSECRET", "090RucamvekrMLyGHMr4lkHX9xhAlsqK"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECKTOKENACCESS", "isAuthenticated()"); + } + + private void configureDataflowForUAA(DataflowContainer dataflowContainer) { + String oauthUrlPrefix = "http://oauth:" + UAA_PORT + "/uaa"; + dataflowContainer.withEnv("LOGGING_LEVEL_ORG_SPRINGFRAMEWORK_SECURITY", "DEBUG"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.map-oauth-scopes", "true"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_CREATE", "dataflow.create"); + dataflowContainer.withEnv( "spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DEPLOY", "dataflow.deploy"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_DESTROY", "dataflow.destroy"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MANAGE", "dataflow.manage"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_MODIFY", "dataflow.modify"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_SCHEDULE", "dataflow.schedule"); + dataflowContainer.withEnv("spring.cloud.dataflow.security.authorization.provider-role-mappings.uaa.role-mappings.ROLE_VIEW", "dataflow.view"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_REDIRECT_URI", "{baseUrl}/login/oauth2/code/{registrationId}"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_AUTHORIZATION_GRANT_TYPE", "authorization_code"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_ID", "dataflow"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_CLIENT_SECRET", "secret"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_UAA_SCOPE", "openid,dataflow.create,dataflow.deploy,dataflow.destroy,dataflow.manage,dataflow.modify,dataflow.schedule,dataflow.view"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_JWK_SET_URI", oauthUrlPrefix + "/token_keys"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_TOKEN_URI", oauthUrlPrefix + "/oauth/token"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_INFO_URI", oauthUrlPrefix + "/userinfo"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_USER_NAME_ATTRIBUTE", "user_name"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_UAA_AUTHORIZATION_URI", oauthUrlPrefix + "/oauth/authorize"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_INTROSPECTION_URI", oauthUrlPrefix + "/introspect"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_ID", "dataflow"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_RESOURCESERVER_OPAQUETOKEN_CLIENT_SECRET", "secret"); + dataflowContainer.withEnv("SPRING_SECURITY_OAUTH2_AUTHORIZATION_CHECK_TOKEN_ACCESS", "isAuthenticated()"); + } + public static class ClusterContainer { String id; diff --git a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/oauth/DataflowOAuthIT.java b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/oauth/DataflowOAuthIT.java index 30faf78c90..ce51091ec7 100644 --- a/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/oauth/DataflowOAuthIT.java +++ b/spring-cloud-dataflow-server/src/test/java/org/springframework/cloud/dataflow/integration/test/oauth/DataflowOAuthIT.java @@ -16,6 +16,7 @@ package org.springframework.cloud.dataflow.integration.test.oauth; +import java.io.IOException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; @@ -34,14 +35,14 @@ import static org.assertj.core.api.Assertions.assertThat; @Oauth -@ActiveProfiles({TagNames.PROFILE_OAUTH}) +@ActiveProfiles(TagNames.PROFILE_OAUTH) class DataflowOAuthIT extends AbstractDataflowTests { private final Logger log = LoggerFactory.getLogger(DataflowOAuthIT.class); @Test - void securedSetupUAA() throws Exception { - log.info("Running securedSetupUAA()"); + void runningUAASecuredSetup() throws Exception { + log.info("Running UAASecuredSetup"); this.dataflowCluster.startIdentityProvider(TagNames.UAA_4_32); this.dataflowCluster.startSkipper(TagNames.SKIPPER_main); this.dataflowCluster.startDataflow(TagNames.DATAFLOW_main); @@ -60,30 +61,10 @@ void securedSetupUAA() throws Exception { .ignoreExceptions() .atMost(90, TimeUnit.SECONDS) .untilAsserted(() -> { - log.info("Checking auth using curl"); - ExecResult cmdResult = execInToolsContainer("curl", "-v", "-u", "janne:janne", "http://dataflow:9393/about"); - String response = cmdResult.getStdout(); - if (StringUtils.hasText(response)) { - log.info("Response is {}", response); - } - stderr.set(cmdResult.getStderr()); - assertThat(response).contains("\"authenticated\":true"); - assertThat(response).contains("\"username\":\"janne\""); - stderr.set(""); + assertGetAboutWithUser("janne", "janne", stderr); }); - log.info("Checking without credentials using curl"); - ExecResult cmdResult = execInToolsContainer("curl", "-v", "-f", "http://dataflow:9393/about"); - String response = cmdResult.getStdout(); - if (StringUtils.hasText(response)) { - log.info("Response is {}", response); - } - response = cmdResult.getStderr(); - if(StringUtils.hasText(response)) { - log.warn("Error is {}", response); - } - stderr.set(cmdResult.getStderr()); - assertThat(cmdResult.getExitCode()).isNotZero(); - stderr.set(""); + log.info("Checking without credentials using curl"); + assertAboutWithoutUser(stderr); } finally { String msg = stderr.get(); @@ -94,8 +75,8 @@ void securedSetupUAA() throws Exception { } @Test - void securedSetupKeycloak() throws Exception { - log.info("Running securedSetupKeycloak()"); + void runningKeycloakSecuredSetup() throws Exception { + log.info("Running KeycloakSecuredSetup"); this.dataflowCluster.startIdentityProvider(TagNames.KEYCLOAK_26); this.dataflowCluster.startSkipper(TagNames.SKIPPER_main); this.dataflowCluster.startDataflow(TagNames.DATAFLOW_main); @@ -107,39 +88,17 @@ void securedSetupKeycloak() throws Exception { AtomicReference stderr = new AtomicReference<>(); try { - with().pollInterval(5, TimeUnit.SECONDS) - .and() - .await() - .ignoreExceptions() - .atMost(90, TimeUnit.SECONDS) - .untilAsserted(() -> { - log.info("Checking auth using curl"); - ExecResult cmdResult = execInToolsContainer("curl", "-v", "-u", "joe:password", "http://dataflow:9393/about"); - String response = cmdResult.getStdout(); - if (StringUtils.hasText(response)) { - log.info("Response is {}", response); - } - if(StringUtils.hasText(cmdResult.getStderr())) { - log.error(cmdResult.getStderr()); - } - stderr.set(cmdResult.getStderr()); - assertThat(response).contains("\"authenticated\":true"); - assertThat(response).contains("\"username\":\"joe\""); - stderr.set(""); - }); + with() + .pollInterval(5, TimeUnit.SECONDS) + .and() + .await() + .ignoreExceptions() + .atMost(90, TimeUnit.SECONDS) + .untilAsserted(() -> { + assertGetAboutWithUser("joe", "password", stderr); + }); log.info("Checking without credentials using curl"); - ExecResult cmdResult = execInToolsContainer("curl", "-v", "-f", "http://dataflow:9393/about"); - String response = cmdResult.getStdout(); - if (StringUtils.hasText(response)) { - log.info("Response is {}", response); - } - response = cmdResult.getStderr(); - if(StringUtils.hasText(response)) { - log.warn("Error is {}", response); - } - stderr.set(cmdResult.getStderr()); - assertThat(cmdResult.getExitCode()).isNotZero(); - stderr.set(""); + assertAboutWithoutUser(stderr); } finally { String msg = stderr.get(); @@ -148,4 +107,35 @@ void securedSetupKeycloak() throws Exception { } } } + + private void assertGetAboutWithUser(String username, String password, AtomicReference stderr) throws IOException, InterruptedException { + log.info("Checking auth using curl"); + ExecResult cmdResult = execInToolsContainer("curl", "-v", "-u", username + ":" + password, "http://dataflow:9393/about"); + String response = cmdResult.getStdout(); + if (StringUtils.hasText(response)) { + log.info("Response is {}", response); + } + if(StringUtils.hasText(cmdResult.getStderr())) { + log.error(cmdResult.getStderr()); + } + stderr.set(cmdResult.getStderr()); + assertThat(response).contains("\"authenticated\":true"); + assertThat(response).contains("\"username\":\"" + username + "\""); + stderr.set(""); + } + + private void assertAboutWithoutUser(AtomicReference stderr) throws IOException, InterruptedException { + ExecResult cmdResult = execInToolsContainer("curl", "-v", "-f", "http://dataflow:9393/about"); + String response = cmdResult.getStdout(); + if (StringUtils.hasText(response)) { + log.info("Response is {}", response); + } + response = cmdResult.getStderr(); + if(StringUtils.hasText(response)) { + log.warn("Error is {}", response); + } + stderr.set(cmdResult.getStderr()); + assertThat(cmdResult.getExitCode()).isNotZero(); + stderr.set(""); + } }