From 77a335d1e82b45a2bc17e20349669215e1882d45 Mon Sep 17 00:00:00 2001 From: Manuel Fink <123368068+finkmanAtSap@users.noreply.github.com> Date: Tue, 16 Jan 2024 15:03:11 +0100 Subject: [PATCH] Fix service plan casing and add binding name in ServiceBindingMapper (#1429) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix service plan casing in ServiceBindingMapper and add service binding name property to configs * keep configs grouped by uppercased plan in K8sEnvironment for backward-compatibility * change fallback plan from "APPLICATION" to "application" in ServiceBindingMapper * Fix K8sConstants to use K8sConstants Update the K8sEnvironment to use the EnumMap instead of a Map Signed-off-by: liga-oz --------- Signed-off-by: liga-oz Co-authored-by: liga-oz Co-authored-by: Līga <72249435+liga-oz@users.noreply.github.com> --- .../security/config/ServiceBindingMapper.java | 17 ++-- .../security/config/k8s/K8sEnvironment.java | 43 +++++++---- .../config/k8s/K8sEnvironmentTest.java | 24 +++--- .../k8s/xsuaa/xsuaa-application2/clientid | 1 + .../k8s/xsuaa/xsuaa-application2/clientsecret | 1 + .../k8s/xsuaa/xsuaa-application2/plan | 1 + .../k8s/xsuaa/xsuaa-application2/uaadomain | 1 + .../k8s/xsuaa/xsuaa-application2/url | 1 + .../k8s/xsuaa/xsuaa-application2/xsappname | 1 + .../cloud/security/config/cf/CFConstants.java | 1 + .../security/config/k8s/K8sConstants.java | 10 ++- ...IdentityServicesPropertySourceFactory.java | 4 +- .../OAuth2ServiceConfigurationProperties.java | 16 ++++ ...PropertySourceFactoryBrokerNoHoleTest.java | 62 +++++++++++---- ...pertySourceFactoryFourXsuaaOneIasTest.java | 77 +++++++++++++++---- ...tityServicesPropertySourceFactoryTest.java | 18 ++++- .../fourXsuaaBindingsAndOneIasBinding.json | 7 +- .../resources/singleXsuaaAndIasBinding.json | 4 +- .../xsuaaBindingsTwoApplicationsNoBroker.json | 5 +- 19 files changed, 222 insertions(+), 72 deletions(-) create mode 100644 env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientid create mode 100644 env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientsecret create mode 100644 env/src/test/resources/k8s/xsuaa/xsuaa-application2/plan create mode 100644 env/src/test/resources/k8s/xsuaa/xsuaa-application2/uaadomain create mode 100644 env/src/test/resources/k8s/xsuaa/xsuaa-application2/url create mode 100644 env/src/test/resources/k8s/xsuaa/xsuaa-application2/xsappname diff --git a/env/src/main/java/com/sap/cloud/security/config/ServiceBindingMapper.java b/env/src/main/java/com/sap/cloud/security/config/ServiceBindingMapper.java index 7f6d8b4b1..367df9721 100644 --- a/env/src/main/java/com/sap/cloud/security/config/ServiceBindingMapper.java +++ b/env/src/main/java/com/sap/cloud/security/config/ServiceBindingMapper.java @@ -2,7 +2,7 @@ import com.sap.cloud.environment.servicebinding.api.ServiceBinding; import com.sap.cloud.environment.servicebinding.api.TypedMapView; -import com.sap.cloud.security.config.k8s.K8sConstants; +import com.sap.cloud.security.config.cf.CFConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,18 +13,24 @@ import static com.sap.cloud.security.config.Service.IAS; import static com.sap.cloud.security.config.cf.CFConstants.IAS.DOMAIN; import static com.sap.cloud.security.config.cf.CFConstants.IAS.DOMAINS; +import static com.sap.cloud.security.config.cf.CFConstants.NAME; import static com.sap.cloud.security.config.cf.CFConstants.SERVICE_PLAN; -@Deprecated public class ServiceBindingMapper { private static final Logger LOGGER = LoggerFactory.getLogger(ServiceBindingMapper.class); - @Deprecated + /** + * Parses a service binding by extracting the configuration information and + * passing it to a configuration builder. + * + * @return a new {@link OAuth2ServiceConfigurationBuilder} that is configured + * based on the given {@link ServiceBinding}. + */ @Nullable public static OAuth2ServiceConfigurationBuilder mapToOAuth2ServiceConfigurationBuilder(ServiceBinding b) { if (!b.getServiceName().isPresent()) { LOGGER.error("Ignores Service Binding with name {} as service name is not provided.", b.getName()); - return null; // as of now, method is never called when service name isn't given + return null; } final Service service = Service.from(b.getServiceName().get()); @@ -38,7 +44,8 @@ public static OAuth2ServiceConfigurationBuilder mapToOAuth2ServiceConfigurationB TypedMapView credentials = TypedMapView.ofCredentials(b); OAuth2ServiceConfigurationBuilder builder = OAuth2ServiceConfigurationBuilder.forService(service) .withProperties(credentials.getEntries(String.class)) - .withProperty(SERVICE_PLAN, b.getServicePlan().orElse(K8sConstants.Plan.APPLICATION.name()).toUpperCase()); + .withProperty(NAME, b.getName().orElse("")) + .withProperty(SERVICE_PLAN, b.getServicePlan().orElse(CFConstants.Plan.APPLICATION.toString())); if (IAS.equals(service)) { parseDomains(builder, credentials); diff --git a/env/src/main/java/com/sap/cloud/security/config/k8s/K8sEnvironment.java b/env/src/main/java/com/sap/cloud/security/config/k8s/K8sEnvironment.java index e394f4f92..9c4d85578 100644 --- a/env/src/main/java/com/sap/cloud/security/config/k8s/K8sEnvironment.java +++ b/env/src/main/java/com/sap/cloud/security/config/k8s/K8sEnvironment.java @@ -15,7 +15,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; import static com.sap.cloud.security.config.cf.CFConstants.SERVICE_PLAN; @@ -30,7 +29,7 @@ public class K8sEnvironment implements Environment { private static final Logger LOGGER = LoggerFactory.getLogger(K8sEnvironment.class); static K8sEnvironment instance; - private final Map> serviceConfigurations; + private final Map> serviceConfigurations; private K8sEnvironment() { serviceConfigurations = new EnumMap<>(Service.class); @@ -53,20 +52,32 @@ public Type getType() { private void loadAll() { List serviceBindings = DefaultServiceBindingAccessor.getInstance().getServiceBindings(); - Map xsuaaPlans = serviceBindings.stream() + EnumMap xsuaaPlans = serviceBindings.stream() .filter(b -> Service.XSUAA.equals(Service.from(b.getServiceName().orElse(null)))) .map(ServiceBindingMapper::mapToOAuth2ServiceConfigurationBuilder) .filter(Objects::nonNull) .map(OAuth2ServiceConfigurationBuilder::build) - .collect(Collectors.toMap(config -> config.getProperty(SERVICE_PLAN), - Function.identity())); - Map identityPlans = serviceBindings.stream() + .collect(Collectors.toMap(config -> Plan.from(config.getProperty(SERVICE_PLAN)), + config -> config, + (l, r) -> { + LOGGER.info("Found 2 service configurations of '{}' plan, taking the last one", + r.getProperty(SERVICE_PLAN)); + return r; + }, + () -> new EnumMap<>(Plan.class))); + EnumMap identityPlans = serviceBindings.stream() .filter(b -> Service.IAS.equals(Service.from(b.getServiceName().orElse(null)))) .map(ServiceBindingMapper::mapToOAuth2ServiceConfigurationBuilder) .filter(Objects::nonNull) .map(OAuth2ServiceConfigurationBuilder::build) - .collect(Collectors.toMap(config -> config.getProperty(SERVICE_PLAN), - Function.identity())); + .collect(Collectors.toMap(config -> Plan.from(config.getProperty(SERVICE_PLAN)), + config -> config, + (l, r) -> { + LOGGER.info("Found 2 service configurations of '{}' plan, taking the last one", + r.getProperty(SERVICE_PLAN)); + return r; + }, + () -> new EnumMap<>(Plan.class))); serviceConfigurations.put(Service.XSUAA, xsuaaPlans); serviceConfigurations.put(Service.IAS, identityPlans); } @@ -79,19 +90,17 @@ private void loadAll() { * @return the map of all found configurations or empty map, in case there are * no service bindings. */ - Map getServiceConfigurationsOf(Service service) { - return serviceConfigurations.getOrDefault(service, Collections.emptyMap()); + EnumMap getServiceConfigurationsOf(Service service) { + return serviceConfigurations.getOrDefault(service, new EnumMap<>(Plan.class)); } @Nullable @Override public OAuth2ServiceConfiguration getXsuaaConfiguration() { - return Optional.ofNullable(getServiceConfigurationsOf(Service.XSUAA).get(Plan.APPLICATION.name())) - .orElse(Optional.ofNullable(getServiceConfigurationsOf(Service.XSUAA).get(Plan.BROKER.name())) - .orElse(Optional.ofNullable(getServiceConfigurationsOf(Service.XSUAA).get(Plan.SPACE.name())) - .orElse(Optional - .ofNullable(getServiceConfigurationsOf(Service.XSUAA).get(Plan.DEFAULT.name())) - .orElse(null)))); + return Optional.ofNullable(getServiceConfigurationsOf(Service.XSUAA).get(Plan.APPLICATION)) + .orElse(Optional.ofNullable(getServiceConfigurationsOf(Service.XSUAA).get(Plan.BROKER)) + .orElse(Optional.ofNullable(getServiceConfigurationsOf(Service.XSUAA).get(Plan.SPACE)) + .orElse(getServiceConfigurationsOf(Service.XSUAA).get(Plan.DEFAULT)))); } @@ -99,7 +108,7 @@ public OAuth2ServiceConfiguration getXsuaaConfiguration() { @Override public OAuth2ServiceConfiguration getXsuaaConfigurationForTokenExchange() { if (getNumberOfXsuaaConfigurations() > 1) { - return getServiceConfigurationsOf(Service.XSUAA).get(Plan.BROKER.name()); + return getServiceConfigurationsOf(Service.XSUAA).get(Plan.BROKER); } return getXsuaaConfiguration(); } diff --git a/env/src/test/java/com/sap/cloud/security/config/k8s/K8sEnvironmentTest.java b/env/src/test/java/com/sap/cloud/security/config/k8s/K8sEnvironmentTest.java index 27249ed49..bfa27142a 100644 --- a/env/src/test/java/com/sap/cloud/security/config/k8s/K8sEnvironmentTest.java +++ b/env/src/test/java/com/sap/cloud/security/config/k8s/K8sEnvironmentTest.java @@ -13,17 +13,19 @@ import com.sap.cloud.security.config.OAuth2ServiceConfiguration; import com.sap.cloud.security.config.Service; import com.sap.cloud.security.config.cf.CFConstants; -import org.junit.jupiter.api.*; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import java.nio.file.Paths; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; import static com.sap.cloud.environment.servicebinding.SapServiceOperatorLayeredServiceBindingAccessor.DEFAULT_PARSING_STRATEGIES; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.*; class K8sEnvironmentTest { @@ -45,11 +47,11 @@ void afterEach() { void getXsuaaConfiguration() { cut = K8sEnvironment.getInstance(); OAuth2ServiceConfiguration config = cut.getXsuaaConfiguration(); - assertEquals("xsuaaClientId", config.getClientId()); - assertEquals("uaadomain.org", config.getProperty(CFConstants.XSUAA.UAA_DOMAIN)); - assertEquals("xsuaa-basic", config.getProperty(CFConstants.XSUAA.APP_ID)); - assertEquals("xsuaaSecret", config.getClientSecret()); - assertEquals("https://auth.sap.com", config.getUrl().toString()); + assertEquals("xsuaaClientId2", config.getClientId()); + assertEquals("uaadomain2.org", config.getProperty(CFConstants.XSUAA.UAA_DOMAIN)); + assertEquals("xsuaa-basic2", config.getProperty(CFConstants.XSUAA.APP_ID)); + assertEquals("xsuaaSecret2", config.getClientSecret()); + assertEquals("https://auth2.sap.com", config.getUrl().toString()); } @Test diff --git a/env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientid b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientid new file mode 100644 index 000000000..46d25274b --- /dev/null +++ b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientid @@ -0,0 +1 @@ +xsuaaClientId2 \ No newline at end of file diff --git a/env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientsecret b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientsecret new file mode 100644 index 000000000..5724ef44f --- /dev/null +++ b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/clientsecret @@ -0,0 +1 @@ +xsuaaSecret2 \ No newline at end of file diff --git a/env/src/test/resources/k8s/xsuaa/xsuaa-application2/plan b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/plan new file mode 100644 index 000000000..e1993483a --- /dev/null +++ b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/plan @@ -0,0 +1 @@ +application \ No newline at end of file diff --git a/env/src/test/resources/k8s/xsuaa/xsuaa-application2/uaadomain b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/uaadomain new file mode 100644 index 000000000..a3c9a38a3 --- /dev/null +++ b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/uaadomain @@ -0,0 +1 @@ +uaadomain2.org \ No newline at end of file diff --git a/env/src/test/resources/k8s/xsuaa/xsuaa-application2/url b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/url new file mode 100644 index 000000000..a76f4dd9a --- /dev/null +++ b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/url @@ -0,0 +1 @@ +https://auth2.sap.com \ No newline at end of file diff --git a/env/src/test/resources/k8s/xsuaa/xsuaa-application2/xsappname b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/xsappname new file mode 100644 index 000000000..a7af1a8c0 --- /dev/null +++ b/env/src/test/resources/k8s/xsuaa/xsuaa-application2/xsappname @@ -0,0 +1 @@ +xsuaa-basic2 \ No newline at end of file diff --git a/java-api/src/main/java/com/sap/cloud/security/config/cf/CFConstants.java b/java-api/src/main/java/com/sap/cloud/security/config/cf/CFConstants.java index 4013d97bf..c4973c334 100644 --- a/java-api/src/main/java/com/sap/cloud/security/config/cf/CFConstants.java +++ b/java-api/src/main/java/com/sap/cloud/security/config/cf/CFConstants.java @@ -14,6 +14,7 @@ public class CFConstants { public static final String VCAP_APPLICATION = "VCAP_APPLICATION"; public static final String CREDENTIALS = "credentials"; public static final String SERVICE_PLAN = "plan"; + public static final String NAME = "name"; public static final String URL = "url"; public static final String CLIENT_ID = "clientid"; public static final String CLIENT_SECRET = "clientsecret"; diff --git a/java-api/src/main/java/com/sap/cloud/security/config/k8s/K8sConstants.java b/java-api/src/main/java/com/sap/cloud/security/config/k8s/K8sConstants.java index 434c8fa96..9707de3c6 100644 --- a/java-api/src/main/java/com/sap/cloud/security/config/k8s/K8sConstants.java +++ b/java-api/src/main/java/com/sap/cloud/security/config/k8s/K8sConstants.java @@ -5,8 +5,6 @@ */ package com.sap.cloud.security.config.k8s; -import com.sap.cloud.security.config.cf.CFConstants; - /** * Constants that simplifies access to service configuration properties in the * Kubernetes environment. @@ -24,9 +22,13 @@ private K8sConstants() { public enum Plan { DEFAULT, BROKER, APPLICATION, SPACE, APIACCESS, SYSTEM; - public static CFConstants.Plan from(String planAsString) { - return CFConstants.Plan.valueOf(planAsString.toUpperCase()); + public static K8sConstants.Plan from(String planAsString) { + if (planAsString == null) { + return APPLICATION; + } + return K8sConstants.Plan.valueOf(planAsString.toUpperCase()); } + } } diff --git a/spring-security/src/main/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactory.java b/spring-security/src/main/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactory.java index 297fd8463..d38a1d855 100644 --- a/spring-security/src/main/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactory.java +++ b/spring-security/src/main/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactory.java @@ -54,10 +54,10 @@ public class IdentityServicesPropertySourceFactory implements PropertySourceFact .asList(new String[] { "clientid", "clientsecret", "identityzoneid", "sburl", "tenantid", "tenantmode", "uaadomain", "url", "verificationkey", "xsappname", "certificate", - "key", "credential-type", "certurl" })); + "key", "credential-type", "certurl", "name", "plan" })); private static final List IAS_ATTRIBUTES = Collections.unmodifiableList(Arrays - .asList(new String[] { "clientid", "clientsecret", "domains", "url" })); + .asList(new String[] { "clientid", "clientsecret", "domains", "url", "name", "plan" })); private Properties properties; diff --git a/spring-security/src/main/java/com/sap/cloud/security/spring/config/OAuth2ServiceConfigurationProperties.java b/spring-security/src/main/java/com/sap/cloud/security/spring/config/OAuth2ServiceConfigurationProperties.java index dc62e09c8..cc0eed373 100644 --- a/spring-security/src/main/java/com/sap/cloud/security/spring/config/OAuth2ServiceConfigurationProperties.java +++ b/spring-security/src/main/java/com/sap/cloud/security/spring/config/OAuth2ServiceConfigurationProperties.java @@ -206,6 +206,22 @@ public Service getService() { return getConfiguration().getService(); } + public void setName(String name) { + builder.withProperty(CFConstants.NAME, name); + } + + public String getName() { + return getConfiguration().getProperty(CFConstants.NAME); + } + + public void setPlan(String plan) { + builder.withProperty(CFConstants.SERVICE_PLAN, plan); + } + + public String getPlan() { + return getConfiguration().getProperty(CFConstants.SERVICE_PLAN); + } + @Override public boolean isLegacyMode() { return getConfiguration().isLegacyMode(); diff --git a/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryBrokerNoHoleTest.java b/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryBrokerNoHoleTest.java index 516290a7a..d61e9a661 100644 --- a/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryBrokerNoHoleTest.java +++ b/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryBrokerNoHoleTest.java @@ -5,11 +5,6 @@ */ package com.sap.cloud.security.spring.config; -import static org.junit.Assert.assertTrue; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.List; - import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -17,6 +12,22 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests that the {@link IdentityServicesPropertySourceFactory} puts 2 XSUAA + * service instances with plan 'application' into the Spring properties without + * creating a hole at index 1. For backward-compatibility, the order of the + * service instance must be as follows: Index 0: Configuration accessible via + * Environment#getXsuaaConfiguration (Application) Index 1: Configuration + * accessible via Environment#getXsuaaConfigurationForTokenExchange (Broker) if + * exists, otherwise next XSUAA configuration Index 2+: Remaining XSUAA + * configurations In addition, tests that the IAS service instance from the + * environment is correctly added as well. + */ @SpringBootTest(classes = { BrokerHoleTestConfigurationFromFile.class }) class IdentityServicesPropertySourceFactoryBrokerNoHoleTest { @@ -24,30 +35,36 @@ class IdentityServicesPropertySourceFactoryBrokerNoHoleTest { BrokerHoleTestConfigurationFromFile configuration; @Test - void testInjectedPropertyValues_fourXsuaaBindings() { + void testInjectedPropertyValues() { /* Index 0 */ assertEquals("client-id2", configuration.xsuaaClientId0); assertEquals("client-secret2", configuration.xsuaaClientSecret0); assertEquals("http://domain.xsuaadomain", configuration.xsuaaUrl0); assertEquals("xsuaadomain", configuration.xsuaaDomain0); assertEquals("xsappname2", configuration.xsuaaAppName0); + assertEquals("xsuaaInstance0", configuration.xsuaaName0); + assertEquals("application", configuration.xsuaaPlan0); assertEquals("", configuration.unknown0); /* Index 1 */ assertEquals("client-id", configuration.xsuaaClientId1); assertEquals("client-secret", configuration.xsuaaClientSecret1); assertEquals("xsappname", configuration.xsuaaAppName1); + assertEquals("xsuaaInstance1", configuration.xsuaaName1); + assertEquals("application", configuration.xsuaaPlan1); /* Index 2 */ assertEquals("none", configuration.xsuaaClientId2); assertEquals("none", configuration.xsuaaClientSecret2); - + /* IAS */ assertEquals("client-id-ias", configuration.identityClientId); assertEquals("client-secret-ias", configuration.identityClientSecret); assertTrue(configuration.identityDomains.contains("iasdomain")); assertTrue(configuration.identityDomains.contains("iasdomain.com")); assertEquals(2, configuration.identityDomains.size()); + assertEquals("identityInstance0", configuration.identityName0); + assertEquals("broker", configuration.identityPlan); } } @@ -57,7 +74,7 @@ void testInjectedPropertyValues_fourXsuaaBindings() { class BrokerHoleTestConfigurationFromFile { /* Index 0 */ - + @Value("${sap.security.services.xsuaa[0].url:}") public String xsuaaUrl0; @@ -73,12 +90,17 @@ class BrokerHoleTestConfigurationFromFile { @Value("${sap.security.services.xsuaa[0].xsappname:}") public String xsuaaAppName0; + @Value("${sap.security.services.xsuaa[0].name:}") + public String xsuaaName0; + + @Value("${sap.security.services.xsuaa[0].plan:}") + public String xsuaaPlan0; + @Value("${sap.security.services.xsuaa[0].unknown:}") public String unknown0; - /* Index 1 */ - + @Value("${sap.security.services.xsuaa[1].clientid:none}") public String xsuaaClientId1; @@ -87,19 +109,23 @@ class BrokerHoleTestConfigurationFromFile { @Value("${sap.security.services.xsuaa[1].xsappname}") public String xsuaaAppName1; - + + @Value("${sap.security.services.xsuaa[1].name:}") + public String xsuaaName1; + + @Value("${sap.security.services.xsuaa[1].plan:}") + public String xsuaaPlan1; + /* Index 2 */ - + @Value("${sap.security.services.xsuaa[2].clientid:none}") public String xsuaaClientId2; @Value("${sap.security.services.xsuaa[2].clientsecret:none}") public String xsuaaClientSecret2; - - /* IAS */ - + @Value("${sap.security.services.identity.clientid:}") public String identityClientId; @@ -108,4 +134,10 @@ class BrokerHoleTestConfigurationFromFile { @Value("${sap.security.services.identity.domains:}") public List identityDomains; + + @Value("${sap.security.services.identity.name:}") + public String identityName0; + + @Value("${sap.security.services.identity.plan:}") + public String identityPlan; } diff --git a/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryFourXsuaaOneIasTest.java b/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryFourXsuaaOneIasTest.java index 38a11fecd..5b32d4240 100644 --- a/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryFourXsuaaOneIasTest.java +++ b/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryFourXsuaaOneIasTest.java @@ -5,11 +5,6 @@ */ package com.sap.cloud.security.spring.config; -import static org.junit.Assert.assertTrue; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.List; - import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -17,6 +12,22 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * Tests that the {@link IdentityServicesPropertySourceFactory} puts 2 XSUAA + * service instances with plan 'application' and 2 with plan 'broker' into the + * Spring properties in the correct order. For backward-compatibility, the order + * of the service instance must be as follows: Index 0: Configuration accessible + * via Environment#getXsuaaConfiguration (Application) Index 1: Configuration + * accessible via Environment#getXsuaaConfigurationForTokenExchange (Broker) if + * exists, otherwise next XSUAA configuration Index 2+: Remaining XSUAA + * configurations In addition, tests that the IAS service instance from the + * environment is correctly added as well. + */ @SpringBootTest(classes = { FourXsuaaOneIasTestConfigurationFromFile.class }) class IdentityServicesPropertySourceFactoryFourXsuaaOneIasTest { @@ -31,27 +42,37 @@ void testInjectedPropertyValues_fourXsuaaBindings() { assertEquals("http://domain.xsuaadomain", configuration.xsuaaUrl0); assertEquals("xsuaadomain", configuration.xsuaaDomain0); assertEquals("xsappname2", configuration.xsuaaAppName0); + assertEquals("xsuaaInstance2", configuration.xsuaaName0); + assertEquals("application", configuration.xsuaaPlan0); assertEquals("", configuration.unknown0); /* Index 1 */ assertEquals("client-id-broker", configuration.xsuaaClientId1); assertEquals("client-secret-broker", configuration.xsuaaClientSecret1); + assertEquals("xsuaaInstance0", configuration.xsuaaName1); + assertEquals("broker", configuration.xsuaaPlan1); /* Index 2 */ assertEquals("client-id-broker2", configuration.xsuaaClientId2); assertEquals("client-secret-broker2", configuration.xsuaaClientSecret2); + assertEquals("xsuaaInstance1", configuration.xsuaaName2); + assertEquals("broker", configuration.xsuaaPlan2); /* Index 3 */ assertEquals("client-id", configuration.xsuaaClientId3); assertEquals("client-secret", configuration.xsuaaClientSecret3); assertEquals("xsappname", configuration.xsuaaAppName3); - + assertEquals("xsuaaInstance3", configuration.xsuaaName3); + assertEquals("application", configuration.xsuaaPlan3); + /* IAS */ assertEquals("client-id-ias", configuration.identityClientId); assertEquals("client-secret-ias", configuration.identityClientSecret); assertTrue(configuration.identityDomains.contains("iasdomain")); assertTrue(configuration.identityDomains.contains("iasdomain.com")); assertEquals(2, configuration.identityDomains.size()); + assertEquals("identityInstance0", configuration.identityName0); + assertEquals("broker", configuration.identityPlan); } } @@ -61,7 +82,7 @@ void testInjectedPropertyValues_fourXsuaaBindings() { class FourXsuaaOneIasTestConfigurationFromFile { /* Index 0 */ - + @Value("${sap.security.services.xsuaa[0].url:}") public String xsuaaUrl0; @@ -77,29 +98,45 @@ class FourXsuaaOneIasTestConfigurationFromFile { @Value("${sap.security.services.xsuaa[0].xsappname:}") public String xsuaaAppName0; + @Value("${sap.security.services.xsuaa[0].name:}") + public String xsuaaName0; + + @Value("${sap.security.services.xsuaa[0].plan:}") + public String xsuaaPlan0; + @Value("${sap.security.services.xsuaa[0].unknown:}") public String unknown0; - /* Index 1 */ - + @Value("${sap.security.services.xsuaa[1].clientid:}") public String xsuaaClientId1; @Value("${sap.security.services.xsuaa[1].clientsecret:}") public String xsuaaClientSecret1; - + @Value("${sap.security.services.xsuaa[1].name:}") + public String xsuaaName1; + + @Value("${sap.security.services.xsuaa[1].plan:}") + public String xsuaaPlan1; + /* Index 2 */ - + @Value("${sap.security.services.xsuaa[2].clientid:}") public String xsuaaClientId2; @Value("${sap.security.services.xsuaa[2].clientsecret:}") public String xsuaaClientSecret2; + @Value("${sap.security.services.xsuaa[2].name:}") + public String xsuaaName2; + + @Value("${sap.security.services.xsuaa[2].plan:}") + public String xsuaaPlan2; + /* Index 3 */ - + @Value("${sap.security.services.xsuaa[3].clientid:}") public String xsuaaClientId3; @@ -108,9 +145,15 @@ class FourXsuaaOneIasTestConfigurationFromFile { @Value("${sap.security.services.xsuaa[3].xsappname:}") public String xsuaaAppName3; - + + @Value("${sap.security.services.xsuaa[3].name:}") + public String xsuaaName3; + + @Value("${sap.security.services.xsuaa[3].plan:}") + public String xsuaaPlan3; + /* IAS */ - + @Value("${sap.security.services.identity.clientid:}") public String identityClientId; @@ -119,4 +162,10 @@ class FourXsuaaOneIasTestConfigurationFromFile { @Value("${sap.security.services.identity.domains:}") public List identityDomains; + + @Value("${sap.security.services.identity.name:}") + public String identityName0; + + @Value("${sap.security.services.identity.plan:}") + public String identityPlan; } diff --git a/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryTest.java b/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryTest.java index c4bb4ca99..f29a7cc68 100644 --- a/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryTest.java +++ b/spring-security/src/test/java/com/sap/cloud/security/spring/config/IdentityServicesPropertySourceFactoryTest.java @@ -1,6 +1,6 @@ /** * SPDX-FileCopyrightText: 2018-2023 SAP SE or an SAP affiliate company and Cloud Security Client Java contributors - *

+ *

* SPDX-License-Identifier: Apache-2.0 */ package com.sap.cloud.security.spring.config; @@ -29,12 +29,16 @@ void testInjectedPropertyValues() { assertEquals("http://domain.xsuaadomain", configuration.xsuaaUrl); assertEquals("xsuaadomain", configuration.xsuaaDomain); assertEquals("xsappname", configuration.xsuaaAppName); + assertEquals("xsuaaInstance0", configuration.xsuaaName); + assertEquals("application", configuration.xsuaaPlan); assertEquals("", configuration.unknown); assertEquals("client-id-ias", configuration.identityClientId); assertEquals("client-secret-ias", configuration.identityClientSecret); assertEquals("iasdomain", configuration.identityDomains.get(0)); + assertEquals("identityInstance0", configuration.identityName); + assertEquals("broker", configuration.identityPlan); } } @@ -58,6 +62,12 @@ class TestConfigurationFromFile { @Value("${sap.security.services.xsuaa.xsappname:}") public String xsuaaAppName; + @Value("${sap.security.services.xsuaa.name:}") + public String xsuaaName; + + @Value("${sap.security.services.xsuaa.plan:}") + public String xsuaaPlan; + @Value("${sap.security.services.xsuaa.unknown:}") public String unknown; @@ -69,4 +79,10 @@ class TestConfigurationFromFile { @Value("${sap.security.services.identity.domains:}") public List identityDomains; + + @Value("${sap.security.services.identity.name:}") + public String identityName; + + @Value("${sap.security.services.identity.plan:}") + public String identityPlan; } diff --git a/spring-security/src/test/resources/fourXsuaaBindingsAndOneIasBinding.json b/spring-security/src/test/resources/fourXsuaaBindingsAndOneIasBinding.json index 12b75825a..395e64369 100644 --- a/spring-security/src/test/resources/fourXsuaaBindingsAndOneIasBinding.json +++ b/spring-security/src/test/resources/fourXsuaaBindingsAndOneIasBinding.json @@ -5,6 +5,7 @@ "clientid": "client-id-broker", "clientsecret": "client-secret-broker" }, + "name": "xsuaaInstance0", "plan": "broker" }, { @@ -12,6 +13,7 @@ "clientid": "client-id-broker2", "clientsecret": "client-secret-broker2" }, + "name": "xsuaaInstance1", "plan": "broker" }, { @@ -22,6 +24,7 @@ "uaadomain": "xsuaadomain", "xsappname": "xsappname2" }, + "name": "xsuaaInstance2", "plan": "application" }, { @@ -32,6 +35,7 @@ "uaadomain": "xsuaadomain", "xsappname": "xsappname" }, + "name": "xsuaaInstance3", "plan": "application" } ], @@ -43,7 +47,8 @@ "url": "http://domain.iasdomain", "domains": ["iasdomain", "iasdomain.com"] }, + "name": "identityInstance0", "plan": "broker" } - ] + ] } diff --git a/spring-security/src/test/resources/singleXsuaaAndIasBinding.json b/spring-security/src/test/resources/singleXsuaaAndIasBinding.json index cbb8f8e0d..9bce16435 100644 --- a/spring-security/src/test/resources/singleXsuaaAndIasBinding.json +++ b/spring-security/src/test/resources/singleXsuaaAndIasBinding.json @@ -8,6 +8,7 @@ "uaadomain": "xsuaadomain", "xsappname": "xsappname" }, + "name": "xsuaaInstance0", "plan": "application" } ], @@ -19,7 +20,8 @@ "url": "http://domain.iasdomain", "domains": ["iasdomain"] }, + "name": "identityInstance0", "plan": "broker" } - ] + ] } diff --git a/spring-security/src/test/resources/xsuaaBindingsTwoApplicationsNoBroker.json b/spring-security/src/test/resources/xsuaaBindingsTwoApplicationsNoBroker.json index ed6466f03..12a77ee12 100644 --- a/spring-security/src/test/resources/xsuaaBindingsTwoApplicationsNoBroker.json +++ b/spring-security/src/test/resources/xsuaaBindingsTwoApplicationsNoBroker.json @@ -8,6 +8,7 @@ "uaadomain": "xsuaadomain", "xsappname": "xsappname2" }, + "name": "xsuaaInstance0", "plan": "application" }, { @@ -18,6 +19,7 @@ "uaadomain": "xsuaadomain", "xsappname": "xsappname" }, + "name": "xsuaaInstance1", "plan": "application" } ], @@ -29,7 +31,8 @@ "url": "http://domain.iasdomain", "domains": ["iasdomain", "iasdomain.com"] }, + "name": "identityInstance0", "plan": "broker" } - ] + ] }