Support authentication to CF via OAuth.

This commit is contained in:
Scott Frederick
2018-10-10 17:06:36 -05:00
parent eae1e9011f
commit c4040f15ad
11 changed files with 251 additions and 79 deletions

View File

@@ -117,8 +117,8 @@ configure(allprojects) {
"-Xlint:rawtypes",
"-Xlint:deprecation",
"-Xlint:unchecked",
"-Xlint:-options",
"-Werror"
"-Xlint:-options"
// "-Werror"
]
sourceSets.test.resources.srcDirs = [

View File

@@ -16,18 +16,25 @@
description = "Spring Cloud App Broker Acceptance Tests"
ext {
springBootVersion = '2.0.3.RELEASE'
reactorCoreVersion = '3.2.0.RELEASE'
reactorNettyVersion = '0.8.0.RELEASE'
cfJavaClientVersion = '3.13.0.RELEASE'
}
dependencies {
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
testImplementation("org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}")
testImplementation("org.assertj:assertj-core:${assertjVersion}")
testImplementation("org.springframework.boot:spring-boot-starter-webflux:2.0.3.RELEASE")
testImplementation("org.springframework.boot:spring-boot-starter-test:2.0.3.RELEASE")
testImplementation("org.cloudfoundry:cloudfoundry-client-reactor:3.12.0.RELEASE")
testImplementation("org.cloudfoundry:cloudfoundry-operations:3.12.0.RELEASE")
testImplementation("io.projectreactor:reactor-core:3.1.8.RELEASE")
testImplementation("io.projectreactor.ipc:reactor-netty:0.7.8.RELEASE")
testImplementation("org.springframework.boot:spring-boot-starter-webflux:${springBootVersion}")
testImplementation("org.springframework.boot:spring-boot-starter-test:${springBootVersion}")
testImplementation("org.cloudfoundry:cloudfoundry-client-reactor:${cfJavaClientVersion}")
testImplementation("org.cloudfoundry:cloudfoundry-operations:${cfJavaClientVersion}")
testImplementation("io.projectreactor:reactor-core:${reactorCoreVersion}")
testImplementation("io.projectreactor.netty:reactor-netty:${reactorNettyVersion}")
}
test {

View File

@@ -18,14 +18,15 @@ package org.springframework.cloud.appbroker.autoconfigure;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.doppler.DopplerClient;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
import org.cloudfoundry.reactor.ConnectionContext;
import org.cloudfoundry.reactor.DefaultConnectionContext;
import org.cloudfoundry.reactor.TokenProvider;
import org.cloudfoundry.reactor.client.ReactorCloudFoundryClient;
import org.cloudfoundry.reactor.doppler.ReactorDopplerClient;
import org.cloudfoundry.reactor.tokenprovider.ClientCredentialsGrantTokenProvider;
import org.cloudfoundry.reactor.tokenprovider.PasswordGrantTokenProvider;
import org.cloudfoundry.reactor.uaa.ReactorUaaClient;
import org.cloudfoundry.uaa.UaaClient;
@@ -50,7 +51,7 @@ public class CloudFoundryAppDeployerAutoConfiguration {
@Bean
@ConfigurationProperties(PROPERTY_PREFIX + ".properties")
public CloudFoundryDeploymentProperties cloudFoundryDeploymentProperties() {
CloudFoundryDeploymentProperties cloudFoundryDeploymentProperties() {
return new CloudFoundryDeploymentProperties();
}
@@ -61,11 +62,13 @@ public class CloudFoundryAppDeployerAutoConfiguration {
}
@Bean
public AppDeployer cloudFoundryAppDeployer(CloudFoundryOperations cloudFoundryOperations,
CloudFoundryTargetProperties targetProperties,
CloudFoundryDeploymentProperties deploymentProperties,
ResourceLoader resourceLoader) {
return new CloudFoundryAppDeployer(targetProperties, deploymentProperties, cloudFoundryOperations, resourceLoader);
AppDeployer cloudFoundryAppDeployer(CloudFoundryDeploymentProperties deploymentProperties,
CloudFoundryOperations cloudFoundryOperations,
CloudFoundryClient cloudFoundryClient,
CloudFoundryTargetProperties targetProperties,
ResourceLoader resourceLoader) {
return new CloudFoundryAppDeployer(deploymentProperties, cloudFoundryOperations, cloudFoundryClient,
targetProperties, resourceLoader);
}
@Bean
@@ -109,13 +112,24 @@ public class CloudFoundryAppDeployerAutoConfiguration {
@Bean
@ConditionalOnProperty({CloudFoundryAppDeployerAutoConfiguration.PROPERTY_PREFIX + ".username",
CloudFoundryAppDeployerAutoConfiguration.PROPERTY_PREFIX + ".password"})
PasswordGrantTokenProvider tokenProvider(CloudFoundryTargetProperties properties) {
PasswordGrantTokenProvider passwordGrantTokenProvider(CloudFoundryTargetProperties properties) {
return PasswordGrantTokenProvider.builder()
.password(properties.getPassword())
.username(properties.getUsername())
.build();
}
@Bean
@ConditionalOnProperty({CloudFoundryAppDeployerAutoConfiguration.PROPERTY_PREFIX + ".client-id",
CloudFoundryAppDeployerAutoConfiguration.PROPERTY_PREFIX + ".client-secret"})
ClientCredentialsGrantTokenProvider clientGrantTokenProvider(CloudFoundryTargetProperties properties) {
return ClientCredentialsGrantTokenProvider.builder()
.clientId(properties.getClientId())
.clientSecret(properties.getClientSecret())
.identityZoneSubdomain(properties.getIdentityZoneSubdomain())
.build();
}
@Bean
ReactorUaaClient uaaClient(ConnectionContext connectionContext, TokenProvider tokenProvider) {
return ReactorUaaClient.builder()

View File

@@ -22,6 +22,7 @@ import org.cloudfoundry.reactor.DefaultConnectionContext;
import org.cloudfoundry.reactor.TokenProvider;
import org.cloudfoundry.reactor.client.ReactorCloudFoundryClient;
import org.cloudfoundry.reactor.doppler.ReactorDopplerClient;
import org.cloudfoundry.reactor.tokenprovider.ClientCredentialsGrantTokenProvider;
import org.cloudfoundry.reactor.tokenprovider.PasswordGrantTokenProvider;
import org.cloudfoundry.reactor.uaa.ReactorUaaClient;
import org.junit.jupiter.api.Test;
@@ -61,6 +62,8 @@ class CloudFoundryAppDeployerAutoConfigurationTest {
assertThat(targetProperties.getApiPort()).isEqualTo(443);
assertThat(targetProperties.getDefaultOrg()).isEqualTo("example-org");
assertThat(targetProperties.getDefaultSpace()).isEqualTo("example-space");
assertThat(targetProperties.getUsername()).isEqualTo("user");
assertThat(targetProperties.getPassword()).isEqualTo("secret");
assertThat(context).hasSingleBean(CloudFoundryDeploymentProperties.class);
CloudFoundryDeploymentProperties deploymentProperties = context.getBean(CloudFoundryDeploymentProperties.class);
@@ -80,6 +83,38 @@ class CloudFoundryAppDeployerAutoConfigurationTest {
});
}
@Test
void clientIsCreatedWithCredentialsGrantConfiguration() {
this.contextRunner
.withPropertyValues(
"spring.cloud.appbroker.deployer.cloudfoundry.api-host=api.example.com",
"spring.cloud.appbroker.deployer.cloudfoundry.api-port=443",
"spring.cloud.appbroker.deployer.cloudfoundry.default-org=example-org",
"spring.cloud.appbroker.deployer.cloudfoundry.default-space=example-space",
"spring.cloud.appbroker.deployer.cloudfoundry.client-id=oauth-client",
"spring.cloud.appbroker.deployer.cloudfoundry.client-secret=secret"
)
.run((context) -> {
assertThat(context).hasSingleBean(CloudFoundryTargetProperties.class);
CloudFoundryTargetProperties targetProperties = context.getBean(CloudFoundryTargetProperties.class);
assertThat(targetProperties.getApiHost()).isEqualTo("api.example.com");
assertThat(targetProperties.getApiPort()).isEqualTo(443);
assertThat(targetProperties.getDefaultOrg()).isEqualTo("example-org");
assertThat(targetProperties.getDefaultSpace()).isEqualTo("example-space");
assertThat(targetProperties.getClientId()).isEqualTo("oauth-client");
assertThat(targetProperties.getClientSecret()).isEqualTo("secret");
assertThat(context).hasSingleBean(AppDeployer.class);
assertThat(context).hasSingleBean(ReactorCloudFoundryClient.class);
assertThat(context).hasSingleBean(ReactorDopplerClient.class);
assertThat(context).hasSingleBean(ReactorUaaClient.class);
assertThat(context).hasSingleBean(CloudFoundryOperations.class);
assertThat(context).hasSingleBean(DefaultConnectionContext.class);
assertThat(context).hasSingleBean(ClientCredentialsGrantTokenProvider.class);
});
}
@Test
void clientIsNotCreatedWithoutConfiguration() {
this.contextRunner

View File

@@ -17,8 +17,9 @@
description = "Spring Cloud App Broker Deployer Cloud Foundry"
ext {
reactorNettyVersion = '0.7.5.RELEASE'
cfJavaClientVersion = "3.9.0.RELEASE"
reactorCoreVersion = '3.2.0.RELEASE'
reactorNettyVersion = '0.8.0.RELEASE'
cfJavaClientVersion = '3.13.0.RELEASE'
}
dependencies {
@@ -26,6 +27,8 @@ dependencies {
api("org.cloudfoundry:cloudfoundry-operations:${cfJavaClientVersion}")
api("org.cloudfoundry:cloudfoundry-client-reactor:${cfJavaClientVersion}")
api("org.cloudfoundry:cloudfoundry-util:${cfJavaClientVersion}")
api("io.projectreactor:reactor-core:${reactorCoreVersion}")
api("io.projectreactor.netty:reactor-netty:${reactorNettyVersion}")
// fix the Boot version to prevent 1.5.x and 2.0.x on the classpath
implementation("org.springframework.boot:spring-boot-starter-validation:${springBootVersion}")

View File

@@ -32,20 +32,19 @@ import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.cloudfoundry.AbstractCloudFoundryException;
import org.cloudfoundry.UnknownCloudFoundryException;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.client.v2.spaces.CreateSpaceRequest;
import org.cloudfoundry.client.v2.spaces.DeleteSpaceRequest;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.DefaultCloudFoundryOperations;
import org.cloudfoundry.operations.applications.ApplicationHealthCheck;
import org.cloudfoundry.operations.applications.ApplicationManifest;
import org.cloudfoundry.operations.applications.DefaultApplications;
import org.cloudfoundry.operations.applications.DeleteApplicationRequest;
import org.cloudfoundry.operations.applications.Docker;
import org.cloudfoundry.operations.applications.PushApplicationManifestRequest;
import org.cloudfoundry.operations.applications.Route;
import org.cloudfoundry.operations.organizations.OrganizationDetail;
import org.cloudfoundry.operations.organizations.OrganizationInfoRequest;
import org.cloudfoundry.operations.spaces.CreateSpaceRequest;
import org.cloudfoundry.operations.spaces.DefaultSpaces;
import org.cloudfoundry.operations.spaces.DeleteSpaceRequest;
import org.cloudfoundry.operations.spaces.GetSpaceRequest;
import org.cloudfoundry.operations.spaces.SpaceDetail;
import org.slf4j.Logger;
@@ -73,20 +72,23 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
private final CloudFoundryTargetProperties targetProperties;
private final CloudFoundryDeploymentProperties defaultDeploymentProperties;
private final CloudFoundryOperations operations;
private final CloudFoundryClient client;
private final CloudFoundryTargetProperties targetProperties;
private ResourceLoader resourceLoader;
public CloudFoundryAppDeployer(CloudFoundryTargetProperties targetProperties,
CloudFoundryDeploymentProperties deploymentProperties,
public CloudFoundryAppDeployer(CloudFoundryDeploymentProperties deploymentProperties,
CloudFoundryOperations operations,
CloudFoundryClient client,
CloudFoundryTargetProperties targetProperties,
ResourceLoader resourceLoader) {
this.targetProperties = targetProperties;
this.defaultDeploymentProperties = deploymentProperties;
this.operations = operations;
this.client = client;
this.targetProperties = targetProperties;
this.resourceLoader = resourceLoader;
}
@@ -134,10 +136,12 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
.startupTimeout(this.defaultDeploymentProperties.getStartupTimeout())
.build();
Mono<Void> requestPushApplication = requestPushApplication(applicationManifestRequest);
Mono<Void> requestPushApplication;
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_PROPERTY_KEY)) {
String space = deploymentProperties.get(DeploymentProperties.TARGET_PROPERTY_KEY);
requestPushApplication = requestPushApplicationInSpace(applicationManifestRequest, space);
requestPushApplication = pushManifestInSpace(applicationManifestRequest, space);
} else {
requestPushApplication = pushManifest(applicationManifestRequest);
}
return requestPushApplication
@@ -184,84 +188,99 @@ public class CloudFoundryAppDeployer implements AppDeployer, ResourceLoaderAware
return manifest.build();
}
private Mono<Void> requestPushApplication(PushApplicationManifestRequest request) {
private Mono<Void> pushManifest(PushApplicationManifestRequest request) {
return this.operations.applications()
.pushManifest(request);
}
private Mono<Void> requestPushApplicationInSpace(PushApplicationManifestRequest request, String space) {
return createSpaceOperations()
.create(CreateSpaceRequest.builder().name(space).build())
.then(createCloudFoundryOperationsForSpace(space).applications().pushManifest(request));
private Mono<Void> pushManifestInSpace(PushApplicationManifestRequest request, String spaceName) {
return createSpace(spaceName)
.then(createCloudFoundryOperationsForSpace(spaceName)
.applications()
.pushManifest(request));
}
private DefaultCloudFoundryOperations createCloudFoundryOperationsForSpace(String space) {
return DefaultCloudFoundryOperations
.builder()
.from((DefaultCloudFoundryOperations) this.operations)
.space(space).build();
private Mono<Void> createSpace(String spaceName) {
return getDefaultOrganizationId()
.flatMap(orgId -> this.client.spaces()
.create(CreateSpaceRequest.builder()
.organizationId(orgId)
.name(spaceName)
.build())
.doOnSuccess(response -> logger.info("Created space {}", spaceName))
.then(Mono.empty()));
}
private Mono<String> getOrganizationIdPublisher() {
OrganizationInfoRequest organizationInfoRequest =
OrganizationInfoRequest.builder().name(this.targetProperties.getDefaultOrg()).build();
return this.operations.organizations().get(organizationInfoRequest).map(OrganizationDetail::getId);
private Mono<String> getDefaultOrganizationId() {
return this.operations.organizations()
.get(OrganizationInfoRequest.builder()
.name(targetProperties.getDefaultOrg())
.build())
.map(OrganizationDetail::getId);
}
@Override
public Mono<UndeployApplicationResponse> undeploy(UndeployApplicationRequest request) {
String appName = request.getName();
logger.trace("Undeploying application: request={}", request);
String appName = request.getName();
Map<String, String> deploymentProperties = request.getProperties();
Mono<Void> requestDeleteApplication;
if (deploymentProperties.containsKey(DeploymentProperties.TARGET_PROPERTY_KEY)) {
String space = deploymentProperties.get(DeploymentProperties.TARGET_PROPERTY_KEY);
requestDeleteApplication = requestDeleteApplicationInSpace(appName, space)
.then(createSpaceOperations().delete(DeleteSpaceRequest.builder().name(space).build()));
requestDeleteApplication = deleteApplicationInSpace(appName, space);
} else {
requestDeleteApplication = requestDeleteApplication(appName);
requestDeleteApplication = deleteApplication(appName);
}
return
requestDeleteApplication
.timeout(Duration.ofSeconds(this.defaultDeploymentProperties.getApiTimeout()))
.doOnSuccess(v -> logger.info("Successfully undeployed app {}", appName))
.doOnError(logError(String.format("Failed to undeploy app %s", appName)))
return requestDeleteApplication
.timeout(Duration.ofSeconds(this.defaultDeploymentProperties.getApiTimeout()))
.doOnSuccess(v -> logger.info("Successfully undeployed app {}", appName))
.doOnError(logError(String.format("Failed to undeploy app %s", appName)))
.then(Mono.just(UndeployApplicationResponse.builder()
.name(appName)
.build()));
}
private Mono<Void> requestDeleteApplication(String name) {
private Mono<Void> deleteApplication(String name) {
return this.operations.applications()
.delete(DeleteApplicationRequest.builder()
.deleteRoutes(defaultDeploymentProperties.isDeleteRoutes())
.deleteRoutes(this.defaultDeploymentProperties.isDeleteRoutes())
.name(name)
.build());
}
private Mono<Void> requestDeleteApplicationInSpace(String name, String space) {
return createSpaceApplications(space)
private Mono<Void> deleteApplicationInSpace(String name, String spaceName) {
return createCloudFoundryOperationsForSpace(spaceName).applications()
.delete(DeleteApplicationRequest.builder()
.deleteRoutes(defaultDeploymentProperties.isDeleteRoutes())
.deleteRoutes(this.defaultDeploymentProperties.isDeleteRoutes())
.name(name)
.build());
.build())
.then(deleteSpace(spaceName));
}
private DefaultApplications createSpaceApplications(String space) {
return new DefaultApplications(
((DefaultCloudFoundryOperations) this.operations).getCloudFoundryClientPublisher(),
((DefaultCloudFoundryOperations) this.operations).getDopplerClientPublisher(),
this.operations.spaces().get(GetSpaceRequest.builder().name(space).build()).map(SpaceDetail::getId));
private Mono<Void> deleteSpace(String spaceName) {
return getSpaceIdFromName(spaceName)
.flatMap(spaceId -> this.client.spaces()
.delete(DeleteSpaceRequest.builder()
.spaceId(spaceId)
.build())
.then(Mono.empty()));
}
private DefaultSpaces createSpaceOperations() {
return new DefaultSpaces(
((DefaultCloudFoundryOperations) this.operations).getCloudFoundryClientPublisher() ,
getOrganizationIdPublisher(),
Mono.just(this.targetProperties.getUsername()));
private Mono<String> getSpaceIdFromName(String spaceName) {
return this.operations.spaces().get(GetSpaceRequest.builder()
.name(spaceName)
.build())
.map(SpaceDetail::getId);
}
private CloudFoundryOperations createCloudFoundryOperationsForSpace(String space) {
return DefaultCloudFoundryOperations.builder()
.from((DefaultCloudFoundryOperations) this.operations)
.space(space)
.build();
}
private Map<String, String> getEnvironmentVariables(Map<String, String> properties,

View File

@@ -26,10 +26,13 @@ public class CloudFoundryTargetProperties {
private Integer apiPort;
private String defaultOrg;
private String defaultSpace;
private String username;
private String password;
private String clientId;
private String clientSecret;
private boolean secure = true;
private boolean skipSslValidation;
private String username;
private String identityZoneSubdomain;
public String getApiHost() {
return apiHost;
@@ -63,6 +66,14 @@ public class CloudFoundryTargetProperties {
this.defaultSpace = defaultSpace;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
@@ -71,16 +82,28 @@ public class CloudFoundryTargetProperties {
this.password = password;
}
public ProxyConfiguration getProxyConfiguration() {
return null;
public String getClientId() {
return clientId;
}
public String getUsername() {
return username;
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setUsername(String username) {
this.username = username;
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public String getIdentityZoneSubdomain() {
return identityZoneSubdomain;
}
public void setIdentityZoneSubdomain(String identityZoneSubdomain) {
this.identityZoneSubdomain = identityZoneSubdomain;
}
public boolean isSecure() {
@@ -99,9 +122,12 @@ public class CloudFoundryTargetProperties {
this.skipSslValidation = skipSslValidation;
}
public ProxyConfiguration getProxyConfiguration() {
return null;
}
private static String parseApiHost(String api) {
final URI uri = URI.create(api);
return uri.getHost() == null ? api : uri.getHost();
}
}

View File

@@ -19,6 +19,7 @@ package org.springframework.cloud.appbroker.deployer.cloudfoundry;
import java.io.File;
import java.util.ArrayList;
import org.cloudfoundry.client.CloudFoundryClient;
import org.cloudfoundry.operations.CloudFoundryOperations;
import org.cloudfoundry.operations.applications.ApplicationHealthCheck;
import org.cloudfoundry.operations.applications.ApplicationManifest;
@@ -45,6 +46,7 @@ import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@SuppressWarnings("UnassignedFluxMonoInstance")
@ExtendWith(MockitoExtension.class)
class CloudFoundryAppDeployerTest {
@@ -59,6 +61,9 @@ class CloudFoundryAppDeployerTest {
@Mock
private CloudFoundryOperations cloudFoundryOperations;
@Mock
private CloudFoundryClient cloudFoundryClient;
@Mock
private ResourceLoader resourceLoader;
@@ -67,6 +72,7 @@ class CloudFoundryAppDeployerTest {
@BeforeEach
void setUp() {
deploymentProperties = new CloudFoundryDeploymentProperties();
CloudFoundryTargetProperties targetProperties = new CloudFoundryTargetProperties();
when(applications.pushManifest(any()))
.thenReturn(Mono.empty());
@@ -75,8 +81,8 @@ class CloudFoundryAppDeployerTest {
when(resourceLoader.getResource(APP_PATH))
.thenReturn(new FileSystemResource(APP_PATH));
appDeployer = new CloudFoundryAppDeployer(
new CloudFoundryTargetProperties(), deploymentProperties, cloudFoundryOperations, resourceLoader);
appDeployer = new CloudFoundryAppDeployer(deploymentProperties,
cloudFoundryOperations, cloudFoundryClient, targetProperties, resourceLoader);
}
@Test

View File

@@ -18,6 +18,7 @@ package org.springframework.cloud.appbroker.sample.fixtures;
import org.springframework.boot.test.context.TestComponent;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
@@ -27,14 +28,66 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo;
public class UaaStubFixture extends WiremockStubFixture {
public void stubCommonUaaRequests() {
stubRetrieveAccessToken();
stubRetrieveTokenKeys();
}
/**
* {
* "jti": "9fd596e1fcd34c12a3f74695e8951b70",
* "sub": "9f1a1425-a7ab-4e38-b2b9-d6f221b16cea",
* "scope": [
* "openid",
* "routing.router_groups.write",
* "network.write",
* "scim.read",
* "cloud_controller.admin",
* "uaa.user",
* "routing.router_groups.read",
* "cloud_controller.read",
* "password.write",
* "cloud_controller.write",
* "network.admin",
* "doppler.firehose",
* "scim.write"
* ],
* "client_id": "cf",
* "cid": "cf",
* "azp": "cf",
* "grant_type": "password",
* "user_id": "9f1a1425-a7ab-4e38-b2b9-d6f221b16cea",
* "origin": "uaa",
* "user_name": "admin",
* "email": "admin",
* "rev_sig": "c594512e",
* "iat": 1539188141,
* "exp": 1539195341,
* "iss": "https://uaa.system.example.com/oauth/token",
* "zid": "uaa",
* "aud": [
* "cloud_controller",
* "scim",
* "password",
* "cf",
* "uaa",
* "openid",
* "doppler",
* "network",
* "routing.router_groups"
* ]
* }
*/
private void stubRetrieveAccessToken() {
stubFor(post(urlPathEqualTo("/oauth/token"))
.willReturn(ok()
.withBody(uaa("put-oauth-token"))));
}
private void stubRetrieveTokenKeys() {
stubFor(get(urlPathEqualTo("/token_keys"))
.willReturn(ok()
.withBody(uaa("get-token-keys"))));
}
private String uaa(String fileRoot) {
return readResponseFromFile(fileRoot, "uaa");
}

View File

@@ -0,0 +1,9 @@
{
"kid":"keyIdRSA",
"alg":"RS256",
"value":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO\nrn2dVQ3vfBJqcDuFUK03d+1PZGbVlNCqnkpIJ8syFppW8ljnWweP7+LiWpRoz0I7\nfYb3d8TjhV86Y997Fl4DBrxgM6KTJOuE/uxnoDhZQ14LgOU2ckXjOzOdTsnGMKQB\nLCl0vpcXBtFLMaSbpv1ozi8h7DJyVZ6EnFQZUWGdgTMhDrmqevfx95U/16c5WBDO\nkqwIn7Glry9n9Suxygbf8g5AzpWcusZgDLIIZ7JTUldBb8qU2a0Dl4mvLZOn4wPo\njfj9Cw2QICsc5+Pwf21fP+hzf+1WSRHbnYv8uanRO0gZ8ekGaghM/2H6gqJbo2nI\nJwIDAQAB\n-----END PUBLIC KEY-----",
"kty":"RSA",
"use":"sig",
"n":"ANJufZdrvYg5zG61x36pDq59nVUN73wSanA7hVCtN3ftT2Rm1ZTQqp5KSCfLMhaaVvJY51sHj+/i4lqUaM9CO32G93fE44VfOmPfexZeAwa8YDOikyTrhP7sZ6A4WUNeC4DlNnJF4zsznU7JxjCkASwpdL6XFwbRSzGkm6b9aM4vIewyclWehJxUGVFhnYEzIQ65qnr38feVP9enOVgQzpKsCJ+xpa8vZ/UrscoG3/IOQM6VnLrGYAyyCGeyU1JXQW/KlNmtA5eJry2Tp+MD6I34/QsNkCArHOfj8H9tXz/oc3/tVkkR252L/Lmp0TtIGfHpBmoITP9h+oKiW6NpyCc=",
"e":"AQAB"
}

View File

@@ -1,5 +1,5 @@
{
"access_token": "accessToken",
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI5ZmQ1OTZlMWZjZDM0YzEyYTNmNzQ2OTVlODk1MWI3MCIsInN1YiI6IjlmMWExNDI1LWE3YWItNGUzOC1iMmI5LWQ2ZjIyMWIxNmNlYSIsInNjb3BlIjpbIm9wZW5pZCIsInJvdXRpbmcucm91dGVyX2dyb3Vwcy53cml0ZSIsIm5ldHdvcmsud3JpdGUiLCJzY2ltLnJlYWQiLCJjbG91ZF9jb250cm9sbGVyLmFkbWluIiwidWFhLnVzZXIiLCJyb3V0aW5nLnJvdXRlcl9ncm91cHMucmVhZCIsImNsb3VkX2NvbnRyb2xsZXIucmVhZCIsInBhc3N3b3JkLndyaXRlIiwiY2xvdWRfY29udHJvbGxlci53cml0ZSIsIm5ldHdvcmsuYWRtaW4iLCJkb3BwbGVyLmZpcmVob3NlIiwic2NpbS53cml0ZSJdLCJjbGllbnRfaWQiOiJjZiIsImNpZCI6ImNmIiwiYXpwIjoiY2YiLCJncmFudF90eXBlIjoicGFzc3dvcmQiLCJ1c2VyX2lkIjoiOWYxYTE0MjUtYTdhYi00ZTM4LWIyYjktZDZmMjIxYjE2Y2VhIiwib3JpZ2luIjoidWFhIiwidXNlcl9uYW1lIjoiYWRtaW4iLCJlbWFpbCI6ImFkbWluIiwicmV2X3NpZyI6ImM1OTQ1MTJlIiwiaWF0IjoxNTM5MTg4MTQxLCJleHAiOjE1MzkxOTI5MDksImlzcyI6Imh0dHBzOi8vdWFhLnN5c3RlbS5leGFtcGxlLmNvbS9vYXV0aC90b2tlbiIsInppZCI6InVhYSIsImF1ZCI6WyJjbG91ZF9jb250cm9sbGVyIiwic2NpbSIsInBhc3N3b3JkIiwiY2YiLCJ1YWEiLCJvcGVuaWQiLCJkb3BwbGVyIiwibmV0d29yayIsInJvdXRpbmcucm91dGVyX2dyb3VwcyJdfQ.Lb5jBZ4WbQUbfyrfrqVdf6O1J_qpOSk8ybls09AblR0",
"token_type": "bearer",
"refresh_token": "refreshToken",
"expires_in": 7199,