Cut out broker features and concentrate on security
This commit is contained in:
@@ -1,6 +1,2 @@
|
||||
include::intro.adoc[]
|
||||
|
||||
== Service Broker Example
|
||||
|
||||
include::broker-example.adoc[]
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
|
||||
Example script to deploy and regis#ter a broker:
|
||||
|
||||
```
|
||||
DOMAIN=mydomain.net
|
||||
cf push app -p target/*.jar --no-start
|
||||
cf env app | grep SPRING_PROFILES_ACTIVE || cf set-env app SPRING_PROFILES_ACTIVE cloud
|
||||
cf env app | grep APPLICATION_DOMAIN || cf set-env app APPLICATION_DOMAIN ${DOMAIN}
|
||||
|
||||
cf services | grep configserver && cf bind app configserver
|
||||
|
||||
cf restart app
|
||||
cf create-service-broker app user secure http://app.${DOMAIN}
|
||||
|
||||
for f in `cf curl /v2/service_plans | grep '\"guid' | sed -e 's/.*: "//' -e 's/".*//'`; do
|
||||
cf curl v2/service_plans/$f -X PUT -d '{"public":true}'
|
||||
done
|
||||
|
||||
cf create-service app free appi
|
||||
```
|
||||
|
||||
At which point you have a service called "app" and a service instance called "appi":
|
||||
|
||||
```
|
||||
$ cf marketplace
|
||||
OK
|
||||
|
||||
service plans description
|
||||
app free Singleton service app
|
||||
$ cf services
|
||||
Getting services in org default / space development as admin...
|
||||
OK
|
||||
|
||||
name service plan bound apps
|
||||
appi app free
|
||||
```
|
||||
|
||||
Your application can define a configuration property
|
||||
`application.domain` (defaults to "cfapps.io") which will be used to
|
||||
construct the credentials for any app that binds to your service. Or
|
||||
it can define the URI directly using
|
||||
`cloudfoundry.service.definition.metadata.uri`.
|
||||
|
||||
You can change some other basic metadata by setting config properties:
|
||||
|
||||
* `cloudfoundry.service.definition.*` is bound to a
|
||||
`ServiceDefinition` (defined in spring-boot-cf-service-broker) which
|
||||
has optional setters for plans and metadata.
|
||||
|
||||
* `cloudfoundry.service.broker.*` is bound to an internal bean. It has
|
||||
optional setters for "name" (the service name), "description" (user
|
||||
friendly description) and "prefix" (used to create a unique id from
|
||||
the name).
|
||||
|
||||
An app which binds to your service will get credentials that contain a
|
||||
"uri" property linking to your service. A Spring Boot app can bind to
|
||||
that through the `vcap.services.[service].credentials.uri` environment
|
||||
property.
|
||||
|
||||
If your service also has a
|
||||
https://github.com/Netflix/eureka[Eureka core] dependency, and you
|
||||
can expose it as a Eureka service, then any service which registers
|
||||
with Eureka will also become a Cloud Foundry service.
|
||||
|
||||
@@ -1,3 +1,15 @@
|
||||
Integration between https://github.com/cloudfoundry[Cloud Foundry]
|
||||
and https://github.com/spring-cloud[Spring Cloud].
|
||||
Spring Cloud for Cloudfoundry makes it easy to run
|
||||
https://github.com/spring-cloud[Spring Cloud] apps in
|
||||
https://github.com/cloudfoundry[Cloud Foundry] (the Platform as a
|
||||
Service). Cloud Foundry has the notion of a "service", which is
|
||||
middlware that you "bind" to an app, essentially providing it with an
|
||||
environment variable containing credentials (e.g. the location and
|
||||
username to use for the service).
|
||||
|
||||
Add this project as a dependency to any Spring Cloud UI app or REST
|
||||
service and deploy to Cloudfoundry. If you use Spring Cloud Security
|
||||
OAuth2 features this will make them bindable to Cloud Foundry services
|
||||
instead of enironment properties in `oauth2.*`. For a UI app you can
|
||||
declare `@EnableOAuth2Sso` and bind to a service called "sso", and for
|
||||
a service you can add `@EnableOAuth2Resource` and bind to a service
|
||||
called "resource" (see below for how to change the names).
|
||||
|
||||
@@ -1,7 +1,50 @@
|
||||
Add this project to a Spring Boot REST service and deploy to
|
||||
Cloudfoundry (and use the Actuator for maximum flexibility). It will
|
||||
expose service-broker endpoints automatically (look in /mappings for
|
||||
/v2/*) and you can register it with the Cloud Controller as described
|
||||
here:
|
||||
http://docs.cloudfoundry.org/services/managing-service-brokers.html[http://docs.cloudfoundry.org/services/managing-service-brokers.html].
|
||||
Here's a Spring Cloud app with OAuth2 SSO:
|
||||
|
||||
.app.groovy
|
||||
[source,java]
|
||||
----
|
||||
@Controller
|
||||
@EnableOAuth2Sso
|
||||
class Application {
|
||||
|
||||
@RequestMapping('/')
|
||||
String home() {
|
||||
'Hello World'
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
If you run it without any service bindings:
|
||||
|
||||
----
|
||||
$ spring jar app.jar app.groovy
|
||||
$ cf push -p app.jar
|
||||
----
|
||||
|
||||
it will be secure with (Spring Boot default) Basic authentication,
|
||||
i.e. the password will be in the logs (or set it with
|
||||
`security.user.password` as normal). To turn on OAuth2 SSO all you
|
||||
need to do is bind the app to a service with the right
|
||||
credentials. For example, a
|
||||
http://docs.pivotal.io/pivotalcf/devguide/services/user-provided.html[user-provided
|
||||
service] can be created like this on PWS:
|
||||
|
||||
----
|
||||
$ cf create-user-provided-service sso -p '{clientId:"<my-client>",clientSecret:"<my-secret>",userInfoUri:"https://uaa.run.pivotal.io/userinfo",tokenUri: "https://login.run.pivotal.io/oauth/token",authorizationUri:"https://login.run.pivotal.io/oauth/authorize"}
|
||||
----
|
||||
|
||||
Then bind and restart the app:
|
||||
|
||||
----
|
||||
$ cf bind app sso
|
||||
$ cf restart app
|
||||
----
|
||||
|
||||
and visit it in a browser. It will redirect to the Cloud Foundry (PWS)
|
||||
login server instead of challenging for Basic authentication. The
|
||||
`clientId` and `clientSecret` are credentials of a registered client
|
||||
in Cloud Foundry. To get a Cloud Foundry client registration for
|
||||
testing please ask at support@run.pivotal.io (if you want it on PWS),
|
||||
or your local platform administrator (if it's a private instance).
|
||||
|
||||
|
||||
@@ -2,7 +2,74 @@
|
||||
|
||||
include::intro.adoc[]
|
||||
|
||||
== Service Broker Example
|
||||
== Quickstart
|
||||
|
||||
include::quickstart.adoc[]
|
||||
|
||||
== How Does it Work?
|
||||
|
||||
=== OAuth2 Single Sign On
|
||||
|
||||
Spring Cloud Security provides the `@EnableOAuth2Sso` annotation and
|
||||
binds the app to environment properties in `oauth2.\*`. Spring Cloud
|
||||
for Cloud Foundry just sets up default environment properties so that
|
||||
it all just works if you bind to a Cloud Foundry service instance
|
||||
called "sso". The service credentials are mapped to the SSO
|
||||
properties, i.e. `clientId`, `clientSecret`, `tokenUri`,
|
||||
`authorizationUri`, `userInfoUri`, `tokenInfoUri1, `jwt.\*` (refer to
|
||||
the Spring Cloud Security documentation for details of which
|
||||
combinations will work together). The main thing is that in Cloud
|
||||
Foundry you only need one service to cover all the necessary
|
||||
credentials.
|
||||
|
||||
To use a different sercice instance name (i.e. not "sso") just set
|
||||
`oauth2.sso.serviceId` to your custom name.
|
||||
|
||||
=== JWT Tokens
|
||||
|
||||
Spring Cloud Security already has support for decoding JWT tokens if
|
||||
you just provide the verification key (as an environment property). In
|
||||
Cloud Foundry you can pick that property up from a servcice binding
|
||||
(`jwt.keyValue` or `jwt.keyUri`).
|
||||
|
||||
For example the `jwt.keyUri` in PWS is
|
||||
"https://uaa.run.pivotal.io/token_key":
|
||||
|
||||
----
|
||||
$ curl https://uaa.run.pivotal.io/token_key
|
||||
{"alg":"SHA256withRSA","value":"-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----\n"}d
|
||||
----
|
||||
|
||||
=== OAuth2 Resource Server
|
||||
|
||||
Similarly, the `@EnableOAuth2Resource` annotation will protect your
|
||||
API endpoints if you bind to a service instance called "resource".
|
||||
The "sso" service above will work for a resource server as well (so
|
||||
just bind to that if it's there). If the OAuth2 tokens are JWTs (as in
|
||||
Cloud Foundry), it is common to use a separate service for resources
|
||||
to avoid a network round trip decoding the token on every access. A
|
||||
user-provided-service for an OAuth2 resource can be created like this
|
||||
on PWS:
|
||||
|
||||
----
|
||||
$ cf create-user-provided-service resource -p '{jwt.keyUri:"https://uaa.run.pivotal.io/token_key"}
|
||||
----
|
||||
|
||||
To use JWT you need to add the verification key as either
|
||||
`jwt.keyValue` or `jwt.keyUri` (these could be added to the "sso"
|
||||
service or the "resource" service if you have one).
|
||||
|
||||
To use a different sercice instance name (i.e. not "resource" or
|
||||
"sso") just set `oauth2.resource.serviceId` to your custom name.
|
||||
|
||||
=== The Default Environment Keys
|
||||
|
||||
The precise mapppings are as follows:
|
||||
|
||||
* `oauth2.sso.\*` to `vcap.services.${oauth2.sso.serviceId:sso}.credentials.*`
|
||||
|
||||
* `oauth2.client.\*` to `vcap.services.${oauth2.sso.serviceId:sso}.credentials.tokenUri:${vcap.services.${oauth2.resource.serviceId:resource}.credentials.*`
|
||||
|
||||
* `oauth2.resource.\*` to `vcap.services.${oauth2.resource.serviceId:resource}.credentials.tokenUri:${vcap.services.${oauth2.sso.serviceId:sso}.credentials.*`
|
||||
|
||||
include::broker-example.adoc[]
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.model.Plan;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class FreeServiceDefinitionFactory {
|
||||
|
||||
private final String prefix;
|
||||
|
||||
public FreeServiceDefinitionFactory() {
|
||||
this("");
|
||||
}
|
||||
|
||||
public FreeServiceDefinitionFactory(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public ServiceDefinition create(String name, String description) {
|
||||
return new ServiceDefinition(getId(name), name, description, true, getPlans(name));
|
||||
}
|
||||
|
||||
private List<Plan> getPlans(String appName) {
|
||||
Plan plan = new Plan(getId(appName + "-free"), "free",
|
||||
"This is a default service plan. All services are created equally.",
|
||||
getServiceDefinitionMetadata(appName), true);
|
||||
return new ArrayList<Plan>(Arrays.asList(plan));
|
||||
}
|
||||
|
||||
private Map<String, Object> getServiceDefinitionMetadata(String appName) {
|
||||
Map<String, Object> sdMetadata = new HashMap<String, Object>();
|
||||
sdMetadata.put("displayName", appName + "-service");
|
||||
sdMetadata.put("longDescription", "Platform Service for " + appName);
|
||||
sdMetadata.put("providerDisplayName", "Pivotal");
|
||||
sdMetadata.put("documentationUrl", "https://github.com/spring-platform");
|
||||
sdMetadata.put("supportUrl", "https://github.com/spring-platform");
|
||||
return sdMetadata;
|
||||
}
|
||||
|
||||
protected String getId(String name) {
|
||||
try {
|
||||
String id = DigestUtils.md5DigestAsHex((prefix + name).getBytes("UTF-8"));
|
||||
return id;
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstanceBinding;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ServiceInstanceBindingRepository {
|
||||
|
||||
ServiceInstanceBinding findOne(String bindingId);
|
||||
|
||||
void delete(String id);
|
||||
|
||||
void save(ServiceInstanceBinding binding);
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstance;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface ServiceInstanceRepository {
|
||||
|
||||
List<ServiceInstance> findAll();
|
||||
|
||||
ServiceInstance findOne(String serviceInstanceId);
|
||||
|
||||
void save(ServiceInstance instance);
|
||||
|
||||
void delete(String id);
|
||||
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.cloudfoundry.community.servicebroker.model.Catalog;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
|
||||
import org.cloudfoundry.community.servicebroker.service.BeanCatalogService;
|
||||
import org.cloudfoundry.community.servicebroker.service.CatalogService;
|
||||
import org.springframework.cloud.cloudfoundry.broker.FreeServiceDefinitionFactory;
|
||||
import org.springframework.cloud.netflix.eureka.server.advice.LeaseManagerLite;
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceCanceledEvent;
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRegisteredEvent;
|
||||
import org.springframework.cloud.netflix.eureka.server.event.EurekaInstanceRenewedEvent;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.context.event.SmartApplicationListener;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.InstanceInfo.ActionType;
|
||||
import com.netflix.eureka.lease.Lease;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class CatalogLeaseManager implements CatalogService, LeaseManagerLite<InstanceInfo>, SmartApplicationListener {
|
||||
|
||||
private static Log logger = LogFactory.getLog(CatalogLeaseManager.class);
|
||||
|
||||
private Map<String, ServiceDefinition> definitions = new HashMap<String, ServiceDefinition>();
|
||||
|
||||
private List<ServiceDefinition> values = new ArrayList<ServiceDefinition>();
|
||||
|
||||
public CatalogLeaseManager(InstanceInfo config) {
|
||||
register(config, 0, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Catalog getCatalog() {
|
||||
return new Catalog(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceDefinition getServiceDefinition(String serviceId) {
|
||||
return new BeanCatalogService(getCatalog()).getServiceDefinition(serviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
|
||||
return EurekaInstanceRegisteredEvent.class.isAssignableFrom(eventType)
|
||||
|| EurekaInstanceCanceledEvent.class.isAssignableFrom(eventType)
|
||||
|| EurekaInstanceRenewedEvent.class.isAssignableFrom(eventType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSourceType(Class<?> sourceType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (event instanceof EurekaInstanceRegisteredEvent) {
|
||||
EurekaInstanceRegisteredEvent registered = (EurekaInstanceRegisteredEvent) event;
|
||||
register(registered.getInstanceInfo(), registered.isReplication());
|
||||
}
|
||||
else if (event instanceof EurekaInstanceCanceledEvent) {
|
||||
EurekaInstanceCanceledEvent canceled = (EurekaInstanceCanceledEvent) event;
|
||||
cancel(canceled.getAppName(), canceled.getServerId(), canceled.isReplication());
|
||||
}
|
||||
else if (event instanceof EurekaInstanceRenewedEvent) {
|
||||
EurekaInstanceRenewedEvent renewed = (EurekaInstanceRenewedEvent) event;
|
||||
renew(renewed.getAppName(), renewed.getServerId(), renewed.isReplication());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(InstanceInfo info, boolean isReplication) {
|
||||
register(info, Lease.DEFAULT_DURATION_IN_SECS, isReplication);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(InstanceInfo info, int leaseDuration, boolean isReplication) {
|
||||
logger.info("Registration request for: " + info.getAppName());
|
||||
if (!definitions.containsKey(info.getAppName())) {
|
||||
logger.info("Registering: " + info.getAppName());
|
||||
ServiceDefinition definition = getServiceDefinition(info);
|
||||
definitions.put(info.getAppName(), definition);
|
||||
values.add(definition);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(String appName, String id, boolean isReplication) {
|
||||
ServiceDefinition definition = definitions.remove(appName);
|
||||
if (definition != null) {
|
||||
logger.info("Cancelling: " + appName);
|
||||
values.remove(definition);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean renew(String appName, String id, boolean isReplication) {
|
||||
if (definitions.containsKey(appName)) {
|
||||
logger.info("Renewing: " + appName);
|
||||
definitions.get(appName).getMetadata()
|
||||
.put("timestamp", System.currentTimeMillis());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict() {
|
||||
Collection<ServiceDefinition> definitions = new ArrayList<ServiceDefinition>(
|
||||
this.definitions.values());
|
||||
for (ServiceDefinition definition : definitions) {
|
||||
InstanceInfo info = (InstanceInfo) definition.getMetadata().get("info");
|
||||
if (info.getActionType() == ActionType.DELETED) {
|
||||
cancel(info.getAppName(), info.getId(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ServiceDefinition getServiceDefinition(InstanceInfo info) {
|
||||
String name = info.getAppName().toLowerCase();
|
||||
ServiceDefinition definition = new FreeServiceDefinitionFactory("eureka-")
|
||||
.create(name, "Eureka-brokered service");
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("info", (Object) info);
|
||||
map.put("uri", info.getHomePageUrl());
|
||||
map.put("timestamp", System.currentTimeMillis());
|
||||
definition.setMetadata(map);
|
||||
return definition;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.configuration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.config.BrokerApiVersionConfig;
|
||||
import org.cloudfoundry.community.servicebroker.model.Catalog;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
|
||||
import org.cloudfoundry.community.servicebroker.service.BeanCatalogService;
|
||||
import org.cloudfoundry.community.servicebroker.service.CatalogService;
|
||||
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceBindingService;
|
||||
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.cloud.cloudfoundry.broker.FreeServiceDefinitionFactory;
|
||||
import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceBindingRepository;
|
||||
import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceRepository;
|
||||
import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanceBindingRepository;
|
||||
import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanceBindingService;
|
||||
import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanceRepository;
|
||||
import org.springframework.cloud.cloudfoundry.broker.simple.SimpleServiceInstanceService;
|
||||
import org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.FilterType;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.netflix.appinfo.EurekaInstanceConfig;
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.appinfo.providers.EurekaConfigBasedInstanceInfoProvider;
|
||||
import com.netflix.eureka.lease.LeaseManager;
|
||||
|
||||
/**
|
||||
* Autoconfiguration providing simple service-broker endpoints and Netflix eureka server
|
||||
* features. The service-broker endpoints will be enabled if <a
|
||||
* href="https://github.com/cloudfoundry-community/spring-boot-cf-service-broker"
|
||||
* >spring-boot-cf-service-broker</a> is on the classpath. By default they just make the
|
||||
* current app into a service brooker for itself. The Eureka features will be added if <a
|
||||
* href="https://github.com/Netflix/eureka">ereka-core</a> is on the classpath. When
|
||||
* active any Eureka services registered using native Netflix APIs will be available as
|
||||
* Cloudfoundry services. They consist of an interceptor for the {@link LeaseManager} that
|
||||
* manages the {@link Catalog} of Cloudfoundry servvices.
|
||||
*
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@ComponentScan(basePackages = { "org.cloudfoundry.community.servicebroker" }, excludeFilters = {
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = BrokerApiVersionConfig.class),
|
||||
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = BeanCatalogService.class) })
|
||||
@ConditionalOnClass({ServiceInstanceRepository.class, BrokerApiVersionConfig.class })
|
||||
@ConditionalOnWebApplication
|
||||
@AutoConfigureAfter(EurekaClientAutoConfiguration.class)
|
||||
public class ServiceBrokerAutoConfiguration {
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(EurekaInstanceConfig.class)
|
||||
protected static class CatalogConfiguration {
|
||||
|
||||
@Autowired
|
||||
private BrokerProperties broker;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(CatalogService.class)
|
||||
public BeanCatalogService catalogService() {
|
||||
return new BeanCatalogService(catalog());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Catalog catalog() {
|
||||
return new Catalog(Arrays.asList(serviceDefinition()));
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties("cloudfoundry.service.definition")
|
||||
public ServiceDefinition serviceDefinition() {
|
||||
return new FreeServiceDefinitionFactory(broker.getPrefix()).create(
|
||||
broker.getName(), broker.getDescription());
|
||||
}
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties("cloudfoundry.server.broker")
|
||||
public static class BrokerProperties {
|
||||
private String prefix;
|
||||
@Value("${spring.application.name:application}")
|
||||
private String name;
|
||||
private String description;
|
||||
|
||||
public String getPrefix() {
|
||||
return prefix == null ? name + "-" : prefix;
|
||||
}
|
||||
|
||||
public void setPrefix(String prefix) {
|
||||
this.prefix = prefix;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description == null ? "Singleton service app" : description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnBean(EurekaInstanceConfig.class)
|
||||
protected static class EurekaCatalogConfiguration {
|
||||
|
||||
@Bean
|
||||
public CatalogLeaseManager catalogLeaseManager(EurekaInstanceConfig config) {
|
||||
InstanceInfo info = new EurekaConfigBasedInstanceInfoProvider(config).get();
|
||||
return new CatalogLeaseManager(info);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ServiceInstanceService.class)
|
||||
public SimpleServiceInstanceService serviceInstanceService(
|
||||
ServiceInstanceRepository repository) {
|
||||
return new SimpleServiceInstanceService(repository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ServiceInstanceBindingService.class)
|
||||
public SimpleServiceInstanceBindingService serviceInstanceBindingService(
|
||||
CatalogService catalog, ServiceInstanceBindingRepository repository) {
|
||||
return new SimpleServiceInstanceBindingService(catalog, repository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ServiceInstanceRepository.class)
|
||||
public SimpleServiceInstanceRepository serviceInstanceRepository(
|
||||
CatalogService catalog) {
|
||||
List<ServiceDefinition> definitions = catalog.getCatalog()
|
||||
.getServiceDefinitions();
|
||||
ServiceDefinition definition = definitions.iterator().next();
|
||||
return new SimpleServiceInstanceRepository(definition.getId());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ServiceInstanceBindingRepository.class)
|
||||
public SimpleServiceInstanceBindingRepository serviceInstanceBindingRepository(
|
||||
CatalogService catalog) {
|
||||
List<ServiceDefinition> definitions = catalog.getCatalog()
|
||||
.getServiceDefinitions();
|
||||
ServiceDefinition definition = definitions.iterator().next();
|
||||
return new SimpleServiceInstanceBindingRepository(definition.getId());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.simple;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstanceBinding;
|
||||
import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceBindingRepository;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class SimpleServiceInstanceBindingRepository implements ServiceInstanceBindingRepository {
|
||||
|
||||
private String serviceDefinitionId;
|
||||
|
||||
public SimpleServiceInstanceBindingRepository(String serviceDefinitionId) {
|
||||
this.serviceDefinitionId = serviceDefinitionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstanceBinding findOne(String id) {
|
||||
return new ServiceInstanceBinding(id, serviceDefinitionId, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(ServiceInstanceBinding instance) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.simple;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.exception.ServiceBrokerException;
|
||||
import org.cloudfoundry.community.servicebroker.exception.ServiceInstanceBindingExistsException;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstance;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstanceBinding;
|
||||
import org.cloudfoundry.community.servicebroker.service.CatalogService;
|
||||
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceBindingService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceBindingRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Simple impl to bind services.
|
||||
*
|
||||
* @author sgreenberg@gopivotal.com
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class SimpleServiceInstanceBindingService implements ServiceInstanceBindingService {
|
||||
|
||||
private ServiceInstanceBindingRepository repository;
|
||||
private CatalogService catalog;
|
||||
@Value("${application.domain:cfapps.io}")
|
||||
private String applicationDomain;
|
||||
|
||||
@Autowired
|
||||
public SimpleServiceInstanceBindingService(CatalogService catalog,
|
||||
ServiceInstanceBindingRepository repository) {
|
||||
this.catalog = catalog;
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstanceBinding createServiceInstanceBinding(String bindingId,
|
||||
ServiceInstance serviceInstance, String serviceId, String planId,
|
||||
String appGuid) throws ServiceInstanceBindingExistsException,
|
||||
ServiceBrokerException {
|
||||
|
||||
ServiceInstanceBinding binding = repository.findOne(bindingId);
|
||||
if (binding != null && binding.getAppGuid()!=null) {
|
||||
throw new ServiceInstanceBindingExistsException(binding);
|
||||
}
|
||||
|
||||
binding = new ServiceInstanceBinding(bindingId, serviceInstance.getId(),
|
||||
getCredentials(serviceInstance, serviceId, planId, appGuid), null, appGuid);
|
||||
repository.save(binding);
|
||||
|
||||
return binding;
|
||||
}
|
||||
|
||||
protected Map<String, Object> getCredentials(ServiceInstance instance,
|
||||
String serviceId, String planId, String appGuid) {
|
||||
Map<String, Object> credentials = new HashMap<String, Object>();
|
||||
credentials.put("uri", findUriFromService(serviceId));
|
||||
credentials.put("domain", applicationDomain);
|
||||
return credentials;
|
||||
}
|
||||
|
||||
protected String findUriFromService(String serviceId) {
|
||||
ServiceDefinition definition = catalog.getServiceDefinition(serviceId);
|
||||
if (definition != null && definition.getId().equals(serviceId)) {
|
||||
String uri = (String) definition.getMetadata().get("uri");
|
||||
if (uri != null) {
|
||||
return uri;
|
||||
}
|
||||
return "http://" + definition.getName() + "." + applicationDomain;
|
||||
}
|
||||
throw new IllegalStateException("Cannot locate service in catalog: " + serviceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstanceBinding getServiceInstanceBinding(String id) {
|
||||
return repository.findOne(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstanceBinding deleteServiceInstanceBinding(String id)
|
||||
throws ServiceBrokerException {
|
||||
ServiceInstanceBinding binding = getServiceInstanceBinding(id);
|
||||
if (binding != null) {
|
||||
repository.delete(id);
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.simple;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstance;
|
||||
import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceRepository;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class SimpleServiceInstanceRepository implements ServiceInstanceRepository {
|
||||
|
||||
private String serviceDefinitionId;
|
||||
|
||||
public SimpleServiceInstanceRepository(String serviceDefinitionId) {
|
||||
// TODO: add dashboard URL
|
||||
this.serviceDefinitionId = serviceDefinitionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> findAll() {
|
||||
return new ArrayList<ServiceInstance>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance findOne(String serviceInstanceId) {
|
||||
return new ServiceInstance(serviceInstanceId, serviceDefinitionId, null, null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(ServiceInstance instance) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.simple;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.cloudfoundry.community.servicebroker.exception.ServiceBrokerException;
|
||||
import org.cloudfoundry.community.servicebroker.exception.ServiceInstanceExistsException;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceDefinition;
|
||||
import org.cloudfoundry.community.servicebroker.model.ServiceInstance;
|
||||
import org.cloudfoundry.community.servicebroker.service.ServiceInstanceService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cloud.cloudfoundry.broker.ServiceInstanceRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SimpleServiceInstanceService implements ServiceInstanceService {
|
||||
|
||||
private ServiceInstanceRepository repository;
|
||||
|
||||
@Autowired
|
||||
public SimpleServiceInstanceService(ServiceInstanceRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInstance> getAllServiceInstances() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance createServiceInstance(ServiceDefinition service,
|
||||
String serviceInstanceId, String planId, String organizationGuid,
|
||||
String spaceGuid)
|
||||
throws ServiceInstanceExistsException, ServiceBrokerException {
|
||||
ServiceInstance instance = repository.findOne(serviceInstanceId);
|
||||
if (instance != null && instance.getOrganizationGuid()!=null) {
|
||||
throw new ServiceInstanceExistsException(instance);
|
||||
}
|
||||
instance = new ServiceInstance(serviceInstanceId, service.getId(),
|
||||
planId, organizationGuid, spaceGuid, null);
|
||||
repository.save(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServiceInstance getServiceInstance(String id) {
|
||||
return repository.findOne(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServiceInstance deleteServiceInstance(String id) throws ServiceBrokerException {
|
||||
ServiceInstance instance = repository.findOne(id);
|
||||
repository.delete(id);
|
||||
return instance;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.environment;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.boot.context.config.ConfigFileApplicationListener;
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class VcapServiceCredentialsListener implements
|
||||
ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
|
||||
|
||||
// After VcapApplicationListener and ConfigFileApplicationListener so values here can
|
||||
// use those ones
|
||||
private int order = ConfigFileApplicationListener.DEFAULT_ORDER + 1;
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
|
||||
Map<String, Object> source = new HashMap<String, Object>();
|
||||
source.put("oauth.sso.logoutUri",
|
||||
"${vcap.services.${oauth2.sso.serviceId:sso}.credentials.logoutUri:}");
|
||||
source.put("oauth2.resource.id",
|
||||
"${vcap.services.${oauth2.resource.serviceId:resource}.credentials.id:}");
|
||||
source.put(
|
||||
"oauth2.resource.userInfoUri",
|
||||
"${vcap.services.${oauth2.resource.serviceId:resource}.credentials.userInfoUri:"
|
||||
+ "${vcap.services.${oauth2.sso.serviceId:sso}.credentials.userInfoUri:}}");
|
||||
source.put(
|
||||
"oauth2.resource.tokenInfoUri",
|
||||
"${vcap.services.${oauth2.resource.serviceId:resource}.credentials.tokenInfoUri:"
|
||||
+ "${vcap.services.${oauth2.sso.serviceId:sso}.credentials.tokenInfoUri:}}");
|
||||
source.put(
|
||||
"oauth2.resource.jwt.keyUri",
|
||||
"${vcap.services.${oauth2.resource.serviceId:resource}.credentials.keyUri:"
|
||||
+ "${vcap.services.${oauth2.sso.serviceId:sso}.credentials.keyUri:}}");
|
||||
source.put(
|
||||
"oauth2.resource.jwt.keyValue",
|
||||
"${vcap.services.${oauth2.resource.serviceId:resource}.credentials.keyValue:"
|
||||
+ "${vcap.services.${oauth2.sso.serviceId:sso}.credentials.keyValue:}}");
|
||||
source.put(
|
||||
"oauth2.client.tokenUri",
|
||||
"${vcap.services.${oauth2.sso.serviceId:sso}.credentials.tokenUri:"
|
||||
+ "${vcap.services.${oauth2.resource.serviceId:resource}.credentials.tokenUri:}}");
|
||||
source.put(
|
||||
"oauth2.client.authorizationUri",
|
||||
"${vcap.services.${oauth2.sso.serviceId:sso}.credentials.authorizationUri:"
|
||||
+ "${vcap.services.${oauth2.resource.serviceId:resource}.credentials.authorizationUri:}}");
|
||||
source.put(
|
||||
"oauth2.client.clientId",
|
||||
"${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientId:"
|
||||
+ "${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientId:}}");
|
||||
source.put(
|
||||
"oauth2.client.clientSecret",
|
||||
"${vcap.services.${oauth2.sso.serviceId:sso}.credentials.clientSecret:"
|
||||
+ "${vcap.services.${oauth2.resource.serviceId:resource}.credentials.clientSecret:}}");
|
||||
source.put(
|
||||
"oauth2.client.scope",
|
||||
"${vcap.services.${oauth2.sso.serviceId:sso}.credentials.scope:"
|
||||
+ "${vcap.services.${oauth2.resource.serviceId:resource}.credentials.scope:}}");
|
||||
event.getEnvironment().getPropertySources()
|
||||
.addLast(new MapPropertySource("cloudDefaultBindings", source));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
org.springframework.cloud.cloudfoundry.broker.configuration.ServiceBrokerAutoConfiguration
|
||||
# Application Listeners
|
||||
org.springframework.context.ApplicationListener=\
|
||||
org.springframework.cloud.cloudfoundry.environment.VcapServiceCredentialsListener
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.sample;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@Configuration
|
||||
@EnableEurekaClient
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
public class Application {
|
||||
|
||||
@RequestMapping("/")
|
||||
public Principal home(Principal principal) {
|
||||
return principal;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.cloud.cloudfoundry.broker.sample;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.boot.test.TestRestTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = Application.class)
|
||||
@WebAppConfiguration
|
||||
@IntegrationTest({ "server.port=0"})
|
||||
public class ApplicationTests {
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port = 0;
|
||||
|
||||
@Test
|
||||
public void catalogLoads() {
|
||||
@SuppressWarnings("rawtypes")
|
||||
ResponseEntity<Map> entity = new TestRestTemplate().getForEntity(
|
||||
"http://localhost:" + port + "/v2/catalog", Map.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user