1. Overview
1.概述
In this tutorial, we’ll introduce the Spring Cloud Open Service Broker project and learn how to implement the Open Service Broker API.
在本教程中,我们将介绍Spring Cloud Open Service Broker项目,并学习如何实现Open Service Broker API。
First, we’ll dive into the specification of the Open Service Broker API. Then, we’ll learn how to use Spring Cloud Open Service Broker to build applications that implement the API specs.
首先,我们将深入了解Open Service Broker API的规范。然后,我们将学习如何使用Spring Cloud Open Service Broker来构建实现API规范的应用程序。
Finally, we’ll explore what security mechanisms we can use to protect our service broker endpoints.
最后,我们将探讨我们可以使用哪些安全机制来保护我们的服务代理端点。
2. Open Service Broker API
2.开放式服务经纪人API
The Open Service Broker API project allows us to quickly provide backing services to our applications running on cloud-native platforms such as Cloud Foundry and Kubernetes. In essence, the API specification describes a set of REST endpoints through which we can provision and connect to these services.
开放服务代理API项目允许我们快速为运行在Cloud Foundry和Kubernetes等云原生平台上的应用程序提供支持服务。实质上,该API规范描述了一组REST端点,我们可以通过这些端点提供并连接到这些服务。
In particular, we can use service brokers within a cloud-native platform to:
特别是,我们可以在云原生平台中使用服务经纪人来。
- Advertise a catalog of backing services
- Provision service instances
- Create and delete bindings between a backing service and a client application
- Deprovision service instances
Spring Cloud Open Service Broker creates the base for an Open Service Broker API compliant implementation by providing the required web controllers, domain objects, and configuration. Additionally, we’ll need to come up with our business logic by implementing the appropriate service broker interfaces.
Spring Cloud Open Service Broker 通过提供所需的 Web 控制器、域对象和配置,为符合 Open Service Broker API 的实施创建了基础。此外,我们还需要通过实现适当的服务代理接口来制定我们的业务逻辑。
3. Auto Configuration
3.自动配置
In order to use Spring Cloud Open Service Broker in our application, we need to add the associated starter artifact. We can use Maven Central to search for the latest version of the open-service-broker starter.
为了在我们的应用程序中使用Spring Cloud Open Service Broker,我们需要添加相关的starter构件。我们可以使用Maven Central来搜索最新版本的open-service-broker starter。
Besides the cloud starter, we’ll also need to include a Spring Boot web starter, and either Spring WebFlux or Spring MVC, to activate the auto-configuration:
除了云启动器,我们还需要包括一个Spring Boot网络启动器,以及Spring WebFlux或Spring MVC,以激活自动配置。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-open-service-broker</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
The auto-configuration mechanism configures default implementations for most of the components that we need for a service broker. If we want, we can override the default behavior by providing our own implementation of the open-service-broker Spring-related beans.
自动配置机制为我们的服务代理所需的大多数组件配置了默认的实现。如果我们愿意,我们可以通过提供我们自己的open-service-broker Spring相关Bean的实现来覆盖默认行为。
3.1. Service Broker Endpoints Path Configuration
3.1.服务经纪商端点路径配置
By default, the context path under which the service broker endpoints are registered is “/”.
默认情况下,服务代理端点注册的上下文路径是”/”。
If that’s not ideal and we want to change it, the most straightforward way is to set the property spring.cloud.openservicebroker.base-path in our application properties or YAML file:
如果这不理想,我们想改变它,最直接的方法是在我们的应用程序属性或YAML文件中设置属性spring.cloud.openservicebroker.base-path。
spring:
cloud:
openservicebroker:
base-path: /broker
In this case, to query the service broker endpoints, we’ll first need to prefix our requests with the /broker/ base-path.
在这种情况下,为了查询服务代理端点,我们首先需要在请求前加上/broker/基路径。
4. A Service Broker Example
4.一个服务经纪人的例子
Let’s create a service broker application using the Spring Cloud Open Service Broker library and explore how the API works.
让我们使用Spring Cloud Open Service Broker库创建一个服务代理应用程序,并探索API的工作原理。
Through our example, we’ll use the service broker to provision and connect to a backing mail system. For simplicity, we’ll use a dummy mail API provided within our code examples.
通过我们的例子,我们将使用服务代理来提供并连接到一个支持的邮件系统。为了简单起见,我们将使用我们的代码示例中提供的一个假的邮件API。
4.1. Service Catalog
4.1.服务目录
First, to control which services our service broker offers, we’ll need to define a service catalog. To quickly initialize the service catalog, in our example we’ll provide a Spring bean of type Catalog:
首先,为了控制我们的服务代理提供哪些服务,我们需要定义一个服务目录。为了快速初始化服务目录,在我们的例子中,我们将提供一个Catalog类型的Spring Bean。
@Bean
public Catalog catalog() {
Plan mailFreePlan = Plan.builder()
.id("fd81196c-a414-43e5-bd81-1dbb082a3c55")
.name("mail-free-plan")
.description("Mail Service Free Plan")
.free(true)
.build();
ServiceDefinition serviceDefinition = ServiceDefinition.builder()
.id("b92c0ca7-c162-4029-b567-0d92978c0a97")
.name("mail-service")
.description("Mail Service")
.bindable(true)
.tags("mail", "service")
.plans(mailFreePlan)
.build();
return Catalog.builder()
.serviceDefinitions(serviceDefinition)
.build();
}
As shown above, the service catalog contains metadata describing all available services that our service broker can offer. Moreover, the definition of a service is intentionally broad as it could refer to a database, a messaging queue, or, in our case, a mail service.
如上所示,服务目录包含描述我们的服务代理所能提供的所有可用服务的元数据。此外,服务的定义是有意宽泛的,因为它可以指一个数据库、一个消息传递队列,或者在我们的案例中指一个邮件服务。
Another key point is that each service is built up from plans, which is another general term. In essence, each plan can offer different features and cost different amounts.
另一个关键点是,每项服务都是由计划建立起来的,这是另一个通用术语。从本质上讲,每个计划可以提供不同的功能,花费不同的金额。
In the end, the service catalog is made available to the cloud-native platforms through the service broker /v2/catalog endpoint:
最后,服务目录通过服务代理/v2/catalog端点被提供给云原生平台。
curl http://localhost:8080/broker/v2/catalog
{
"services": [
{
"bindable": true,
"description": "Mail Service",
"id": "b92c0ca7-c162-4029-b567-0d92978c0a97",
"name": "mail-service",
"plans": [
{
"description": "Mail Service Free Plan",
"free": true,
"id": "fd81196c-a414-43e5-bd81-1dbb082a3c55",
"name": "mail-free-plan"
}
],
"tags": [
"mail",
"service"
]
}
]
}
Consequently, cloud-native platforms will query the service broker catalog endpoint from all service brokers to present an aggregated view of the service catalogs.
因此,云原生平台将从所有服务经纪商处查询服务经纪商目录端点,以呈现服务目录的聚合视图。
4.2. Service Provisioning
4.2.服务提供
Once we start advertising services, we also need to provide the mechanisms in our broker to provision and manage the lifecycle of them within the cloud platform.
一旦我们开始宣传服务,我们也需要在我们的经纪人中提供机制,以便在云平台内提供和管理它们的生命周期。
Furthermore, what provisioning represents varies from broker to broker. In some cases, provisioning may involve spinning up empty databases, creating a message broker, or simply providing an account to access external APIs.
此外,供应所代表的内容因经纪商而异。在某些情况下,供应可能涉及启动空的数据库、创建一个消息代理,或者仅仅是提供一个访问外部API的账户。
In terms of terminology, the services created by a service broker will be referred to as service instances.
在术语方面,由服务中介创建的服务将被称为服务实例。
With Spring Cloud Open Service Broker, we can manage the service lifecycle by implementing the ServiceInstanceService interface. For example, to manage the service provisioning requests in our service broker we must provide an implementation for the createServiceInstance method:
通过Spring Cloud Open Service Broker,我们可以通过实现ServiceInstanceService接口来管理服务生命周期。例如,为了在我们的服务代理中管理服务供应请求,我们必须为createServiceInstance方法提供一个实现。
@Override
public Mono<CreateServiceInstanceResponse> createServiceInstance(
CreateServiceInstanceRequest request) {
return Mono.just(request.getServiceInstanceId())
.flatMap(instanceId -> Mono.just(CreateServiceInstanceResponse.builder())
.flatMap(responseBuilder -> mailService.serviceInstanceExists(instanceId)
.flatMap(exists -> {
if (exists) {
return mailService.getServiceInstance(instanceId)
.flatMap(mailServiceInstance -> Mono.just(responseBuilder
.instanceExisted(true)
.dashboardUrl(mailServiceInstance.getDashboardUrl())
.build()));
} else {
return mailService.createServiceInstance(
instanceId, request.getServiceDefinitionId(), request.getPlanId())
.flatMap(mailServiceInstance -> Mono.just(responseBuilder
.instanceExisted(false)
.dashboardUrl(mailServiceInstance.getDashboardUrl())
.build()));
}
})));
}
Here, we allocate a new mail service in our internal mappings, if one with the same service instance id doesn’t exist, and provide a dashboard URL. We can consider the dashboard as a web management interface for our service instance.
在这里,我们在内部映射中分配一个新的邮件服务,如果有一个相同的服务实例ID不存在的话,并提供一个仪表板的URL。我们可以把仪表盘看作是我们服务实例的一个网络管理界面。
Service provisioning is made available to the cloud-native platforms through the /v2/service_instances/{instance_id} endpoint:
服务供应是通过/v2/service_instances/{instance_id}端点提供给云原生平台的。
curl -X PUT http://localhost:8080/broker/v2/service_instances/newsletter@baeldung.com
-H 'Content-Type: application/json'
-d '{
"service_id": "b92c0ca7-c162-4029-b567-0d92978c0a97",
"plan_id": "fd81196c-a414-43e5-bd81-1dbb082a3c55"
}'
{"dashboard_url":"http://localhost:8080/mail-dashboard/newsletter@baeldung.com"}
In short, when we provision a new service, we need to pass the service_id and the plan_id advertised in the service catalog. Additionally, we need to provide a unique instance_id, which our service broker will use in future binding and de-provisioning requests.
简而言之,当我们提供一个新的服务时,我们需要传递service_id和plan_id在服务目录中公布的。此外,我们还需要提供一个唯一的instance_id,我们的服务代理将在未来的绑定和取消配置请求中使用该id。
4.3. Service Binding
4.3.服务绑定
After we provision a service, we’ll want our client application to start communicating with it. From a service broker’s perspective, this is called service binding.
在我们提供一个服务之后,我们希望我们的客户应用能够开始与它进行通信。从服务代理的角度来看,这被称为服务绑定。
Similar to service instances and plans, we should consider a binding as another flexible abstraction that we can use within our service broker. In general, we’ll provide service bindings to expose credentials used to access a service instance.
与服务实例和计划类似,我们应该将绑定视为另一个灵活的抽象,我们可以在服务代理中使用。一般来说,我们将提供服务绑定以公开用于访问服务实例的凭证。
In our example, if the advertised service has the bindable field set to true, our service broker must provide an implementation of the ServiceInstanceBindingService interface. Otherwise, the cloud platforms won’t call the service binding methods from our service broker.
在我们的例子中,如果广告服务的bindable字段设置为true,我们的服务代理必须提供ServiceInstanceBindingService接口的实现。否则,云平台将不会从我们的服务代理处调用服务绑定方法。
Let’s handle the service binding creation requests by providing an implementation to the createServiceInstanceBinding method:
让我们通过为createServiceInstanceBinding方法提供一个实现来处理服务绑定创建请求。
@Override
public Mono<CreateServiceInstanceBindingResponse> createServiceInstanceBinding(
CreateServiceInstanceBindingRequest request) {
return Mono.just(CreateServiceInstanceAppBindingResponse.builder())
.flatMap(responseBuilder -> mailService.serviceBindingExists(
request.getServiceInstanceId(), request.getBindingId())
.flatMap(exists -> {
if (exists) {
return mailService.getServiceBinding(
request.getServiceInstanceId(), request.getBindingId())
.flatMap(serviceBinding -> Mono.just(responseBuilder
.bindingExisted(true)
.credentials(serviceBinding.getCredentials())
.build()));
} else {
return mailService.createServiceBinding(
request.getServiceInstanceId(), request.getBindingId())
.switchIfEmpty(Mono.error(
new ServiceInstanceDoesNotExistException(
request.getServiceInstanceId())))
.flatMap(mailServiceBinding -> Mono.just(responseBuilder
.bindingExisted(false)
.credentials(mailServiceBinding.getCredentials())
.build()));
}
}));
}
The above code generates a unique set of credentials – username, password, and a URI – through which we can connect and authenticate to our new mail service instance.
上面的代码生成了一套独特的证书–用户名、密码和URI–通过它我们可以连接并验证我们的新邮件服务实例。
Spring Cloud Open Service Broker framework exposes service binding operations through the /v2/service_instances/{instance_id}/service_bindings/{binding_id} endpoint:
Spring Cloud Open Service Broker框架通过/v2/service_instances/{instance_id}/service_bindings/{binding_id}端点公开服务绑定操作。
curl -X PUT
http://localhost:8080/broker/v2/service_instances/newsletter@baeldung.com/service_bindings/admin
-H 'Content-Type: application/json'
-d '{
"service_id": "b92c0ca7-c162-4029-b567-0d92978c0a97",
"plan_id": "fd81196c-a414-43e5-bd81-1dbb082a3c55"
}'
{
"credentials": {
"password": "bea65996-3871-4319-a6bb-a75df06c2a4d",
"uri": "http://localhost:8080/mail-system/newsletter@baeldung.com",
"username": "admin"
}
}
Just like service instance provisioning, we are using the service_id and the plan_id advertised in the service catalog within our binding request. Furthermore, we also pass a unique binding_id, which the broker uses as a username for our credentials set.
就像服务实例供应一样,我们在绑定请求中使用服务目录中公布的service_id和plan_id。此外,我们还传递一个唯一的binding_id,经纪人将其作为我们证书集的用户名。
5. Service Broker API Security
5.服务经纪人API安全
Usually, when service brokers and cloud-native platforms communicate with each other, an authentication mechanism is required.
通常情况下,当服务中介和云原生平台相互通信时,需要一个认证机制。
Unfortunately, the Open Service Broker API specification doesn’t currently cover the authentication part for the service broker endpoints. Because of this, also the Spring Cloud Open Service Broker library doesn’t implement any security configuration.
不幸的是,开放服务代理API规范目前并不包括服务代理端点的认证部分。正因为如此,Spring Cloud开放服务代理库也没有实现任何安全配置。
Luckily, if we need to protect our service broker endpoints, we could quickly use Spring Security to put in place Basic authentication or an OAuth 2.0 mechanism. In this case, we should authenticate all service broker requests using our chosen authentication mechanism and return a 401 Unauthorized response when the authentication fails.
幸运的是,如果我们需要保护我们的服务代理端点,我们可以快速使用Spring Security来实施Basic authentication或OAuth 2.0机制。在这种情况下,我们应该使用我们选择的认证机制来认证所有的服务代理请求,并在认证失败时返回一个401 Unauthorized响应。
6. Conclusion
6.结论
In this article, we explored the Spring Cloud Open Service Broker project.
在这篇文章中,我们探讨了Spring Cloud开放服务代理项目。
First, we learned what the Open Service Broker API is, and how it allows us to provision and connect to backing services. Subsequently, we saw how to quickly build a Service Broker API compliant project using the Spring Cloud Open Service Broker library.
首先,我们了解了什么是Open Service Broker API,以及它如何让我们提供和连接到支持服务。随后,我们看到如何使用Spring Cloud开放服务代理库快速建立一个符合服务代理API的项目。
Finally, we discussed how we can secure our service broker endpoints with Spring Security.
最后,我们讨论了如何用Spring Security保护我们的服务代理端点。
As always, the source code for this tutorial is available over on GitHub.
像往常一样,本教程的源代码可在GitHub上获得over。