Local 本地配置

1. 功能开关

Spring Cloud Data Flow Server 提供了功能启动时的启动/禁用开关。功能包含在Spring Cloud Data Flow 中流转的所有操作以及REST的节点(服务器端以及客户端实现,包括shell和UI)如下:

  • Streams (requires Skipper)

  • Tasks

  • Task Scheduler

可以通过在启动数据流服务器时设置boolean属性来开启和关闭这些功能

  • spring.cloud.dataflow.features.streams-enabled

  • spring.cloud.dataflow.features.tasks-enabled

  • spring.cloud.dataflow.features.schedules-enabled

默认情况下,Stream(包括Skipper),Tasks 是启用状态,Task Scheduler 是关闭状态。

通过 REST /about端点可以查看功能的启用禁用信息。

2. 数据库

使用关系型数据库来存储 Stream 和 Task 的定义以及 Task 的执行状态。Spring Cloud Data Flow支持H2,HSQLDB,MySQL,Oracle,Postgresql,DB2和SqlServer数据库。服务在启动的时候会自动创建数据结构,无需手动创建。

默认情况下,Spring Cloud Data Flow 使用 H2 数据库的嵌入式实例。 H2 数据库方便在开发过程中使用,但不建议在生产环境中部署。

MySQL(通过MariaDB驱动程序),HSQLDBPostgreSQL和嵌入式H2的JDBC驱动程序无需额外配置即可使用。如果需要使用其他的数据库,则需要将相应的JDBC驱动程序放在server 对应的 classpath 目录下。

数据库的配置可以通过启动行命令的形式进行配置或者通过环境变量的形式进行配置。

以下示例展示通过环境变量定义数据库的连接:

export spring_datasource_url=jdbc:postgresql://localhost:5432/mydb
export spring_datasource_username=myuser
export spring_datasource_password=mypass
export spring_datasource_driver_class_name="org.postgresql.Driver"

以下示例显示如何使用命令行参数定义MySQL数据库连接:

java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:mysql://localhost:3306/mydb \
    --spring.datasource.username= \
    --spring.datasource.password= \
    --spring.datasource.driver-class-name=org.mariadb.jdbc.Driver &

以下示例显示如何使用命令行参数定义MariaDB数据库连接:

java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:mariadb://localhost:3306/mydb?useMysqlMetadata=true \
    --spring.datasource.username= \
    --spring.datasource.password= \
    --spring.datasource.driver-class-name=org.mariadb.jdbc.Driver &

从MariaDB v2.4.1版本开始,需要在JDBC URL 添加 useMysqlMetadata=true。这个是强制性的配置,直到MariaDB和MySQL能拆分为两个不同的数据库。

以下示例显示如何使用命令行参数定义PostgreSQL数据库连接:

java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:postgresql://localhost:5432/mydb \
    --spring.datasource.username= \
    --spring.datasource.password= \
    --spring.datasource.driver-class-name=org.postgresql.Driver &

以下示例显示如何使用命令行参数定义HSQLDB数据库连接:

java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:hsqldb://localhost:9001/mydb \
    --spring.datasource.username=SA \
    --spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver &

H2 数据库不支持外部配置

2.1 数据库创建以及迁移策略开关

在服务启动的时候,可以控制在启动是否进行数据库的创建。不过在生产环境中,由于权限问题,可能你不能直接进行限制。这个时候可以采用配置属性的方式来禁用它,如下:

spring.cloud.dataflow.rdbms.initialize.enable=false

数据库的创建脚本位于 spring-cloud-dataflow-core/src/main/resources/ 的目录下。

如果是首次安装运行的系统,请运行位于 /schemas/migrations.1.x.x 的数据库脚本,如果是版本升级到1.2.0的系统,只需/migrations.1.x.x下的数据脚本即可。

2.2 添加自定义JDBC驱动

如果需要使用其他数据库,这时需要添加自定义的驱动程序(例如,ORACLE), 您应该修改 Maven 的配置 pom.xml 文件,并重新打包 Data Flow 服务。 平台部署的服务版本不同,但是所有版本都应该修改对应 pom.xml 的文件,GitHub中有每个版本的项目源码。

为本地服器添加自定义JDBC驱动程序依赖:

  • 选择需要重新打包的服务版本,并到GitHub中获取源码

  • 编辑 spring-cloud-dataflow-server / pom.xml,并且添加数据库驱动程序的依赖项。在以下示例中,已选择Oracle驱动程序:

<dependencies>
...
  <dependency>
    <groupId>com.oracle.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>12.2.0.1</version>
  </dependency>
...
</dependencies> 

3. 部署配置

在部署Stream和Tasks时,可以使用 本地部署程序 中的配置来部署。使用Data Flow shell进行部署时,

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: myuser
    password: mypass
    driver-class-name:org.postgresql.Driver

当您使用 本地部署 的方式,部署 Streams 和 Tasks 的时,配置可以参考下表。

当您使用Data Flow shell 进行部署时,可以使用如下语法,配置可以参考下表。deployer.<appName>.local.<deployerPropertyName>

当在 Data Flow Serve 和 Skipper 中配置 Local Task 时,也会用到下表的配置。

现在创建一个名为 ticktock 的 Time Stream 程序,可以参考以下例子配置:

dataflow:> stream create --name ticktock --definition "time --server.port=9000 | log"
dataflow:> stream deploy --name ticktock --properties "deployer.time.local.javaOpts=-Xmx2048m -Dtest=foo"

可以通过简略写法,通过 deployer.memory 属性来替代 java 的 -Xmx 属性,如下示例:

dataflow:> stream deploy --name ticktock --properties "deployer.time.memory=2048m"

部署时,如果在 deployer.<app>.local.javaOpts 中指定了 -Xmx 的值,并且在配置中也使用了 deployer.<app>.local.memory 的配置,则javaOpts优先级高。 此外,部署应用程序时设置的 javaOpts 属性优先级高于 spring.cloud.deployer.local.javaOpts 的配置。

4. Logging 日志

Spring Cloud Data Flow 的 local 服务器自动配置日志,使用RollingFileAppender进行日志记录。日志的配置文件是在classpath下的logback-spring.xml

在 默认情况下,使用的日志配置为:

<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring-cloud-dataflow-server}"/>

使用 logback 配置 RollingPolicy 方式:

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_FILE}.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <!-- daily rolling -->
        <fileNamePattern>${LOG_FILE}.${LOG_FILE_ROLLING_FILE_NAME_PATTERN:-%d{yyyy-MM-dd}}.%i.gz</fileNamePattern>
        <maxFileSize>${LOG_FILE_MAX_SIZE:-100MB}</maxFileSize>
        <maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
        <totalSizeCap>${LOG_FILE_TOTAL_SIZE_CAP:-500MB}</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>${FILE_LOG_PATTERN}</pattern>
    </encoder>
</appender>

查看当前 Spring Cloud Data Flow Server local服务器配置的 java.io.tmpdir :

jinfo <pid> | grep "java.io.tmpdir"

如果你要修改或者覆盖 LOG_FILE, LOG_PATH, LOG_TEMP, LOG_FILE_MAX_SIZE, LOG_FILE_MAX_HISTORY and LOG_FILE_TOTAL_SIZE_CAP 请将它们设置为系统属性。

5. Streams

使用Data Flow Server 使用 Skipper 服务进行 Stream 的生命周期管理,将 spring.cloud.skipper.client.serverUri 属性值配置为Skipper的服务地址接口:

$ java -jar spring-cloud-dataflow-server-2.1.0.RELEASE.jar --spring.cloud.skipper.client.serverUri=https://192.51.100.1:7577/api

通过 Skipper 服务进行配置 platform accounts 可以显示 Stream 部署到哪个 Platforms。

6. Task 任务

Data Flow Server 负责部署 Task。 在 Data Flow Server 启动时,将 Task 的状态写入到相同的数据库中。当 Task 类型为 Spring Batch Jobs 时,job 和 step 的执行数据也会写入到同一个数据库中。与 Skipper 发布 Streams 一样,Task 也可以发布到多个 Platforms,如果没有指定 Platforms, LocalDeployerProperties 会创建一个名称为 default 的 Platforms,详细配置可参考 Local Deployer Properties

要配置一个新的 Local Platforms 时,只需通过添加配置 application.yaml 中的spring.cloud.dataflow.task.platform.local 即可实现。Spring Boot 提供了相应的支持。 在以下的示例中,将创建两个名为 localDev localDevDebug 的 Local Platforms。可以使用 shutdownTimeoutjavaOpts 进行属性设置。

spring:
  cloud:
    dataflow:
      task:
        platform:
          local:
            accounts:
              localDev:
                shutdownTimeout: 60
                javaOpts: "-Dtest=foo -Xmx1024m"
              localDevDebug:
                javaOpts: "-Xdebug -Xmx2048m"

启动 Task 时,可以通过启动命令 --platformName 指定 Platforms 的名称,如果没有指定,则会使用 default

当 Task 部署多个 Platforms 时,需要指定 Data Flow Server 连接同一个数据库。

你可以在本地运行 Data Flow server ,将 Tasks 部署到 Cloud Foundry 或 Kubernetes 上。 请参阅有关Cloud Foundry任务平台配置Kubernetes任务平台配置的部分。

7. Security 安全

默认情况下,Data Flow Server 是不安全的,它采用未加密的HTTP作为连接。可以通过启用HTTPS 并使用 OAuth 2.0 进行身份验证,以保证你的 REST 节点安全性。

默认情况下,REST节点(管理,运行状态)以及 Dashboard UI 界面无需身份认证。

理论上,Spring Cloud Data Flow 支持任何一个 OAuth 提供的服务,我们建议使用 CloudFoundry User Account and Authentication (UAA) Server.

UAA OpenID不仅经过认证被 Cloud Foundry 使用,而且还可以在本地独立部署方案中使用。此外,UAA不仅提供自己的用户存储,还提供全面的LDAP集成。

7.1. 开启 HTTPS

您可以通过在application.yml中的配置中添加证书来切换到HTTPS,如下例所示:

server:
  port: 8443                                          
  ssl: 
    key-alias: yourKeyAlias                 
    key-store: path/to/keystore                      
    key-store-password: yourKeyStorePassword         
    key-password: yourKeyPassword                    
    trust-store: path/to/trust-store                 
    trust-store-password: yourTrustStorePassword     

如果启动HTTPS,它讲完全替代HTTP作为 REST 端点和 Data Flow Dashboard 的交互协议。纯粹的HTTP请求将会失败,请确保配置相应的Shell。

使用 Self-Signed 证书

在开发和测试的过程中,创建 Self-Signed 证书可能会很便捷,开始创建证书,请使用以下命令:

$ keytool -genkey -alias dataflow -keyalg RSA -keystore dataflow.keystore \
          -validity 3650 -storetype JKS \
          -dname "CN=localhost, OU=Spring, O=Pivotal, L=Kailua-Kona, ST=HI, C=US"  
          -keypass dataflow -storepass dataflowa

CN 是一个重要的参数,它应该和你需要访问的域名一致。

然后将下列代码添加 application.yml 文件中:

server:
  port: 8443
  ssl:
    enabled: true
    key-alias: dataflow
    key-store: "/your/path/to/dataflow.keystore"
    key-store-type: jks
    key-store-password: dataflow
    key-password: dataflow

Data Flow Server 的证书配置到此结束,启动服务以后,可以通过 localhost:8443/ 进行访问,由于这是一个自签名的证书,浏览器会提示警告,你需要忽略它。

Shell 使用 Self-Signed

一般情况下,Shell 使用 Self-Signed 证书存在问题,需要额外的步骤才能正常在 Shell 中运行 Self-Signed 证书。可以采用一下两种方案:

  • 添加 Self-Signed 证书 到 JVM truststore 中。

  • 跳过证书认证

添加Self-Signed 证书到 JVM truststore

为了使用 JVM truststore,我们需要先将之前创建的证书导出:

$ keytool -export -alias dataflow -keystore dataflow.keystore -file dataflow_cert -storepass dataflow

接下来, 我们需要创建一个 Shell 可以使用的 truststore

$ keytool -importcert -keystore dataflow.truststore -alias dataflow -storepass dataflow -file dataflow_cert -noprompt

现在,使用已经创建好的配置,来启动 Data Flow Shell:

$ java -Djavax.net.ssl.trustStorePassword=dataflow \
       -Djavax.net.ssl.trustStore=/path/to/dataflow.truststore \
       -Djavax.net.ssl.trustStoreType=jks \
       -jar spring-cloud-dataflow-shell-2.1.0.RELEASE.jar

如果您在创建SSL的连接过程中遇到问题,可以设置 javax.net.debug 的 JVM 参数记录 SSL 的日志。

最后别忘记配置 Data Flow Server 地址

dataflow:> dataflow config server https://localhost:8443/

Skipping Certificate Validation

您可以通过命令行参数来绕过认证验证--dataflow.skip-ssl-validation=true

如果设置此命令行参数,则shell将接受任何(自签名)SSL证书。

您应该避免使用此选项。禁用 trust manager 违背了 SSL 的初衷,会是您更容易受到 man-in-the-middle (中间人) 攻击。

7.2. 使用 OAuth 2.0 进行身份验证

Spring Cloud Data Flow 使用 OAuth 2.0OpenID Connect 来支持身份验证和授权,它允许您将 Spring Cloud Data Flow 集成到单点登录(SSO)环境中。

从 Spring Cloud Data Flow 2.0 开始,OAuth2 是授权和身份验证的唯一方式。

使用以下OAuth2授权类型:

  • Authorization Code:用于GUI(浏览器)集成。访问者将重定向到您的OAuth服务以进行身份​​验证

  • Password:由shell(以及REST集成)使用,因此访问者可以使用用户名和密码登录

  • Client Credentials:直接从 OAuth 提供程序检索访问令牌,并使用Authorization HTTP标头将其传递给 Data Flow server

目前,Spring Cloud Data Flow 使用 opaque tokens 而不是 transparent tokens(JWT)。

REST端点可以通过两种方式访问:

  • Basic authentication, 使用 Password Grant Type 对您的OAuth2服务进行身份验证

  • Access token,使用 Credentials Grant Type 进行用户凭证验证

在设置身份认证时,强烈建议开启HTTPS,尤其是在生产环境中

你可以通过配置 application.yml 或者通过环境变量来启用 OAuth2 身份验证:

security:
  oauth2:
    client:
      client-id: myclient                                             
      client-secret: mysecret
      access-token-uri: http://127.0.0.1:9999/oauth/token
      user-authorization-uri: http://127.0.0.1:9999/oauth/authorize
    resource:
      user-info-uri: http://127.0.0.1:9999/me                         
      token-info-uri: https://dataflow.local:8080/uaa/check_token   

您可以使用 curl 命令,验证 basic authentication 是否正常工作,如下所示:

$ curl -u myusername:mypassword http://localhost:9393/ -H 'Accept: application/json'

执行完成,您应该可以看到REST端点的列表

请注意,使用Web浏览器访问 Root URL 并启用 security 时,您将被重定向到Dashboard UI。要查看REST端点列表,请指定application/jsonAccept标头。另外,使用Postman(Chrome)或RESTClient(Firefox)等工具请务必添加 Accept

除了 Basic Authentication 外,您还可以使用 Access Token 来访问 REST Api。为了实现这一点,您首先要从 OAuth2 提供程序中找到 OAuth2 的访问令牌,然后在 REST Api 中添加Authorization header:

$ curl -H "Authorization: Bearer <ACCESS_TOKEN>" http://localhost:9393/ -H 'Accept: application/json'

7.3. 自定义授权

前面的内容主要涉及身份验证,即如何认证用户的身份。在本节中,我们将讨论 authorization 选项 - that is, who can do what

authorization rules 在dataflow-server-defaults.yml(Spring Cloud Data Flow Core模块的一部分)中定义。

由于 security roles 的分配是在特定环境中,因此 Spring Cloud Data Flow 会默认将所有roles分配给 authenticated OAuth2 的认证用户。DefaultDataflowAuthoritiesExtractor class 就是具体的实现。

或者,通过 Spring Cloud Data Flow 设置spring.cloud.dataflow.security.authorization.map-oauth-scopes 设置为 true 将 OAuth2 映射到 Data Flow roles 。有关更多详细信息,请参阅角色映射一章。

最后,您可以通过扩展Spring Security OAuth AuthoritiesExtractor接口,来实现自定义的角色权限关联。在这种情况下,自定义 bean 优先于Spring Cloud Data Flow提供的默认定义。

默认方案使用七种 roles 来控制 REST端点 Spring Cloud Data Flow的访问:

  • ROLE_CREATE 用于涉及创建的任何内容,例如创建 streams 或 tasks

  • ROLE_DEPLOY 用于部署 streams 或启动tasks

  • ROLE_DESTROY 用于涉及删除streams,tasks等的任何内容。

  • ROLE_MANAGE 用于启动管理端点

  • ROLE_MODIFY 用于涉及改变系统状态的任何事情

  • ROLE_SCHEDULE 用于调度相关操作(例如,安排 tasks 执行)

  • ROLE_VIEW 用于检索状态的任何内容

如上所述,所有与授权相关的默认设置都在dataflow-server-defaults.yml其中指定,它是 Spring Cloud 数据流核心模块的一部分。如果需要,您可以覆盖这些设置。例如:在application.yml

请始终参考您的application.yml文件版本,因为以下代码段可能已过时。

默认规则如下:

spring:
  cloud:
    dataflow:
      security:
        authorization:
          enabled: true
          rules:
            # About

            - GET    /about                          => hasRole('ROLE_VIEW')

            # Audit

            - GET /audit-records                     => hasRole('ROLE_VIEW')
            - GET /audit-records/**                  => hasRole('ROLE_VIEW')

            # Boot Endpoints

            - GET /management/**                  => hasRole('ROLE_MANAGE')

            # Apps

            - GET    /apps                           => hasRole('ROLE_VIEW')
            - GET    /apps/**                        => hasRole('ROLE_VIEW')
            - DELETE /apps/**                        => hasRole('ROLE_DESTROY')
            - POST   /apps                           => hasRole('ROLE_CREATE')
            - POST   /apps/**                        => hasRole('ROLE_CREATE')
            - PUT    /apps/**                        => hasRole('ROLE_MODIFY')

            # Completions

            - GET /completions/**                    => hasRole('ROLE_VIEW')

            # Job Executions & Batch Job Execution Steps && Job Step Execution Progress

            - GET    /jobs/executions                => hasRole('ROLE_VIEW')
            - PUT    /jobs/executions/**             => hasRole('ROLE_MODIFY')
            - GET    /jobs/executions/**             => hasRole('ROLE_VIEW')

            # Batch Job Instances

            - GET    /jobs/instances                 => hasRole('ROLE_VIEW')
            - GET    /jobs/instances/*               => hasRole('ROLE_VIEW')

            # Running Applications

            - GET    /runtime/streams                => hasRole('ROLE_VIEW')
            - GET    /runtime/apps                   => hasRole('ROLE_VIEW')
            - GET    /runtime/apps/**                => hasRole('ROLE_VIEW')

            # Stream Definitions

            - GET    /streams/definitions            => hasRole('ROLE_VIEW')
            - GET    /streams/definitions/*          => hasRole('ROLE_VIEW')
            - GET    /streams/definitions/*/related  => hasRole('ROLE_VIEW')
            - POST   /streams/definitions            => hasRole('ROLE_CREATE')
            - DELETE /streams/definitions/*          => hasRole('ROLE_DESTROY')
            - DELETE /streams/definitions            => hasRole('ROLE_DESTROY')

            # Stream Deployments

            - DELETE /streams/deployments/*          => hasRole('ROLE_DEPLOY')
            - DELETE /streams/deployments            => hasRole('ROLE_DEPLOY')
            - POST   /streams/deployments/**         => hasRole('ROLE_MODIFY')
            - GET    /streams/deployments/**         => hasRole('ROLE_VIEW')

            # Stream Validations

            - GET /streams/validation/               => hasRole('ROLE_VIEW')
            - GET /streams/validation/*              => hasRole('ROLE_VIEW')

            # Task Definitions

            - POST   /tasks/definitions              => hasRole('ROLE_CREATE')
            - DELETE /tasks/definitions/*            => hasRole('ROLE_DESTROY')
            - GET    /tasks/definitions              => hasRole('ROLE_VIEW')
            - GET    /tasks/definitions/*            => hasRole('ROLE_VIEW')

            # Task Executions

            - GET    /tasks/executions               => hasRole('ROLE_VIEW')
            - GET    /tasks/executions/*             => hasRole('ROLE_VIEW')
            - POST   /tasks/executions               => hasRole('ROLE_DEPLOY')
            - DELETE /tasks/executions/*             => hasRole('ROLE_DESTROY')

            # Task Schedules

            - GET    /tasks/schedules                => hasRole('ROLE_VIEW')
            - GET    /tasks/schedules/*              => hasRole('ROLE_VIEW')
            - GET    /tasks/schedules/instances      => hasRole('ROLE_VIEW')
            - GET    /tasks/schedules/instances/*    => hasRole('ROLE_VIEW')
            - POST   /tasks/schedules                => hasRole('ROLE_SCHEDULE')
            - DELETE /tasks/schedules/*              => hasRole('ROLE_SCHEDULE')

            # Task Validations

            - GET    /tasks/validation/               => hasRole('ROLE_VIEW')
            - GET    /tasks/validation/*              => hasRole('ROLE_VIEW')

            # Tools

            - POST   /tools/**                       => hasRole('ROLE_VIEW')

每行的格式如下:

HTTP_METHOD URL_PATTERN'=>'SECURITY_ATTRIBUTE
  • HTTP_METHOD, HTTP Request Method 共15种,采用大写方式

  • URL_PATTERN,采用 Ant 风格的 URL 路径

  • SECURITY_ATTRIBUTE,SpEL表达式。请参阅基于表达式的访问控制

  • 每个由一个或多个空白字符(空格,制表符等)分隔的字符串

请注意,上面配置的是 YAML 中的一个 List ,而不是一个 Map(因此在每一行的开头使用 ' - ' 破折号)配置到spring.cloud.dataflow.security.authorization.rules 下方。

授权 - Shell和Dashboard

启用 security 后,Dashboard 和 Shell 将会按照角色展示对应的功能。所以,对于不同的角色,并非所有功能都可见。

例如,Shell 命令可以知道用户角色有哪些命令可用。

如果,shell 的 help 命令列出了不可用的命令。请参考以下问题:github.com/spring-projects/spring-shell/issues/115

同样,对于 Dashboard ,UI 不会显示用户未授权的页面或页面元素。

保护Spring Boot Management端点

启用 security 后, Spring Boot HTTP Management端点 的 security 与其他REST端点的security 相同。管理REST端点可以使用MANAGEMENT角色访问/management进行管理。

默认配置dataflow-server-defaults.yml

management:
  endpoints:
    web:
      base-path: /management
  security:
    roles: MANAGE

请不要自定义管理路径。

7.4. 设置UAA身份验证

对于本地部署场景,我们建议使用 CloudFoundry用户帐户和身份验证(UAA)服务器 ,采用 OpenID的认证。虽然 UAA 使用的是 Cloud Foundry ,但它也是一个功能齐全的独立OAuth2服务器,具有 LDAP集成 等企业功能 。

Checkout, Build 和 Run UAA :

$ git clone https://github.com/cloudfoundry/uaa.git
$ cd uaa/
$ ./gradlew  run

UAA 支持的 Java 版本是 jdk1.8。

UAA的配置由 uaa.yml 文件控制 ,您可以自定义配置,在这中情况下,我们将采用嵌入式的方案进行配置,并且提供默认用户。

curl -v -d "username=marissa&password=koala&client_id=app&grant_type=password" -u "app:appclientsecret" http://localhost:8080/uaa/oauth/token -d 'token_format=opaque'

会产生类似于以下的输出:

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
* Server auth using Basic with user 'app'
> POST /uaa/oauth/token HTTP/1.1
> Host: localhost:8080
> Authorization: Basic YXBwOmFwcGNsaWVudHNlY3JldA==
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 85
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 85 out of 85 bytes
< HTTP/1.1 200
< Cache-Control: no-store
< Pragma: no-cache
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: DENY
< X-Content-Type-Options: nosniff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Mon, 03 Dec 2018 23:58:41 GMT
<
* Connection #0 to host localhost left intact
{"access_token":"0f935cea42fd4516bb36e4088f6d7c44","token_type":"bearer","id_token":"eyJhbGciOiJIUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvdWFhL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.eyJzdWIiOiI1ODExMWNlNC02NGRlLTQ3ZDYtYjZiZi0wZDRhNDFhNGFlMDAiLCJhdWQiOlsiYXBwIl0sImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC91YWEvb2F1dGgvdG9rZW4iLCJleHAiOjE1NDM5MjQ3MjEsImlhdCI6MTU0Mzg4MTUyMSwiYW1yIjpbInB3ZCJdLCJhenAiOiJhcHAiLCJzY29wZSI6WyJvcGVuaWQiXSwiZW1haWwiOiJtYXJpc3NhQHRlc3Qub3JnIiwiemlkIjoidWFhIiwib3JpZ2luIjoidWFhIiwianRpIjoiMGY5MzVjZWE0MmZkNDUxNmJiMzZlNDA4OGY2ZDdjNDQiLCJwcmV2aW91c19sb2dvbl90aW1lIjoxNTQzODgxMTk1NzU2LCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiY2xpZW50X2lkIjoiYXBwIiwiY2lkIjoiYXBwIiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9uYW1lIjoibWFyaXNzYSIsInJldl9zaWciOiI1ZmI4N2M1NiIsInVzZXJfaWQiOiI1ODExMWNlNC02NGRlLTQ3ZDYtYjZiZi0wZDRhNDFhNGFlMDAiLCJhdXRoX3RpbWUiOjE1NDM4ODE1MjF9.qSxoygd7LUUJSEN0wGI3-U0x2tYZzHnTDuzk6AJUfBk","refresh_token":"d106513b98804a508c35d3f7b656a7fe-r","expires_in":43199,"scope":"scim.userids openid cloud_controller.read password.write cloud_controller.write","jti":"0f935cea42fd4516bb36e4088f6d7c44"}

token_format的参数,可以设置为:

  • opaque

  • jwt

配置UAA,建议使用uaac命令行工具,配置 UAA 服务器:

$ gem install cf-uaac
$ uaac target http://localhost:8080/uaa

查询marissa用户的详细信息:

$ uaac token owner get cf marissa -s "" -p koala
$ uaac contexts

获取 admin 用户对用的 token (密码是adminsecret

$ uaac token client get admin -s adminsecret

获取所有已配置的 client 列表:

$ uaac clients

它会返回应用程序可用的 client


  app
    scope: cloud_controller.read cloud_controller.write openid password.write scim.userids organizations.acme
    resource_ids: none
    authorized_grant_types: password implicit authorization_code client_credentials refresh_token
    redirect_uri: http://localhost:8080/** http://localhost:8080/app/
    autoapprove: openid
    authorities: uaa.resource
    name: The Ultimate Oauth App
    signup_redirect_url: http://localhost:8080/app/
    change_email_redirect_url: http://localhost:8080/app/
    lastmodified: 1543879731285

我们将在Spring Cloud Data Flow中使用 app ,不过,还需要更新 redirect_uri 和客户端密码:

$ uaac client update app --redirect_uri http://localhost:9393/login
$ uaac secret set app --secret dataflow

现在我们可以更新 Spring Cloud Data Flow 中相关OAuth的配置:

security:
  oauth2:
    client:
      client-id: app
      client-secret: dataflow
      scope: openid                                                     
      access-token-uri: http://localhost:8080/uaa/oauth/token
      user-authorization-uri: http://localhost:8080/uaa/oauth/authorize
    resource:
      user-info-uri: http://localhost:8080/uaa/userinfo                 
      token-info-uri: http://localhost:8080/uaa/check_token             

token-info-uri配置非常重要,它会通过外部服务查询到 OAuth 的 Access Token 并传给Spring Cloud Data Flow。在这种情况下,Spring Cloud Data Flow将通过TokenValidatingUserInfoTokenServices 获取 OAuth 的 Access Token ,并使用UAA的 Check Token Endpoint 检查令牌的有效性,并从 UAA 中查询相关联的OAuth scopes并将认证成功的用户 authentication 存储到 Spring Cloud Data Flow的 TokenStore 中。

角色映射

默认情况下,Spring Cloud Data Flow 的用户拥有所有权限。但是,您可以通过配置:

spring.cloud.dataflow.security.authorization.map-oauth-scopes: true

通过 DefaultAuthoritiesExtractor 方法配置 OAuth 相应权限。范围参考如下:

  • 范围dataflow.create 对应 CREATE role

  • 范围dataflow.deploy 对应 DEPLOY role

  • 范围dataflow.destroy 对应 DESTROY role

  • 范围dataflow.manage 对应 MANAGE role

  • 范围dataflow.modify 对应 MODIFY role

  • 范围dataflow.schedule 对应 SCHEDULE role

  • 范围dataflow.view 对应 VIEW role

此外,还可以将任意范围映射到每个数据流角色:

spring:
  cloud:
    deployer:
      local:
        free-disk-space-percentage: 0
    dataflow:
      security:
        authorization:
          map-oauth-scopes: true                                    
          role-mappings:
            ROLE_CREATE: dataflow.create                            
            ROLE_DEPLOY: dataflow.deploy
            ROLE_DESTROY: dataflow.destoy
            ROLE_MANAGE: dataflow.manage
            ROLE_MODIFY: dataflow.modify
            ROLE_SCHEDULE: dataflow.schedule
            ROLE_VIEW: dataflow.view

您可以将 OAuth scope 分配给不同的 Spring Cloud Data Flow 角色,使您可以更灵活的配置。

7.5. LDAP 身份认证

Spring Cloud Data Flow 可以使用 UAA 搭建 LDAP Authentication(轻量级目录访问协议)。UAA 自身提 完整的LDAP支持

虽然您可以使用自己搭建的 OAuth2 Authentication服务,但 LDAP Support 要求使用 UAA 作为 Authentication 服务。对于其他的提供商,请参阅提供商的文档。

UAA 支持使用以下模式服务进行 LDAP(轻量级目录访问协议)的身份验证:

与 LDAP 等外部 Authentication 服务集成时,UAA 中的身份验证会与之关联。UAA 在使用外部 Authenticate 服务认证之前,会先尝试使用用户的 credentials 对 UAA 用户进行身份验证。有关更多信息,请参阅 Chained Authentication 中的 User Account and Authentication LDAP Integration

LDAP Role Mapping

OAuth2 Authentication 服务(UAA)将 LDAP Role 映射到 OAuth Scopes 提供完整支持。

存在以下选项时:

  • ldap/ldap-groups-null.xml 不会映射任何组

  • ldap/ldap-groups-as-scopes.xml将从LDAP Attribute 中检索 Group 名称。例如CN

  • ldap/ldap-groups-map-to-scopes.xml 使用external_group_mapping表将组映射到UAA Groups

在 Spring XML 的配置文件中通过配置ldap.groups.file controls属性指定。

在测试和开发的过程中,可能需要频繁更改 LDAP 的 groups 和 users ,并查看UAA 中的最新内容。但是,用户信息在登录期间被缓存。以下脚本有助于快速检索更新的信息:

#!/bin/bash
uaac token delete --all
uaac target http://localhost:8080/uaa
uaac token owner get cf <username> -s "" -p  <password>
uaac token client get admin -s adminsecret
uaac user get <username>

LDAP Security 和 UAAD 示例应用程序

为了帮助您快速启动运行程序,并了解 LDAP Security 的体系结构,我们在GitHub上提供了 LDAP Security and UAA Example

这只是一个演示/示例应用程序,请勿用于生产。

设置包括:

  • Spring Cloud Data Flow Server

  • Skipper Server

  • CloudFoundry User Account and Authentication (UAA) Server

  • Lightweight Directory Access Protocol (LDAP) Server (provided by Apache Directory Server(ApacheDS))

最后,作为此示例的一部分,您将学习如何使用此安全设置配置和启动组合任务。

7.6. Spring Security OAuth2 Resource/Authorization 服务示例

在进行本地测试和开发时,您可以使用 Spring Security OAuth 提供的Resource/Authorization 服务 。它允许您使用以下简单注释轻松创建自己的(非常基本的)OAuth2服务器:

  • @EnableResourceServer

  • @EnableAuthorizationServer

实际上,UAA 使用了 Spring Security OAuth2 ,因此 basic endpoints 是相同的。

可以在以下网址找到一个工作示例应用程序:

https://github.com/ghillert/oauth-test-server/

克隆项目并使用相应的 Client ID 和 Client Secret 配置Spring Cloud数据流:

security:
  oauth2:
    client:
      client-id: myclient
      client-secret: mysecret
      access-token-uri: http://127.0.0.1:9999/oauth/token
      user-authorization-uri: http://127.0.0.1:9999/oauth/authorize
    resource:
      user-info-uri: http://127.0.0.1:9999/me
      token-info-uri: http://127.0.0.1:9999/oauth/check_token

此示例应用程序不适用于生产用途

7.7. Data Flow Shell 身份验证

使用 Shell 管理程序时,您可以通过用户名和密码或通过 credentials-provider命令来提供凭证。如果您的 OAuth2 服务支持 Password 授予类型,则可以使用以下命令启动 Data Flow Shell

$ java -jar spring-cloud-dataflow-shell-2.1.0.RELEASE.jar         \
  --dataflow.uri=http://localhost:9393                                \   
  --dataflow.username=my_username                                     \   
  --dataflow.password=my_password                                     \   
  --skip-ssl-validation  true                                         \   

请谨记,在启用 Spring Cloud Data Flow 身份验证时,使用 Shell 时,如果要通过用户名/密码进行身份验证 ,则底层 OAuth2 提供程序必须支持 Password OAuth2 Grant Type。

在 Data Flow Shell中,您还可以使用以下命令提供凭据:

server-unknown:>dataflow config server                                \
  --uri  http://localhost:9393                                        \   
  --username myuser                                                   \   
  --password mysecret                                                 \   
  --skip-ssl-validation  true                                         \   

下图显示了连接和验证 Data Flow Server 的 shell 命令:

成功执行后,您应该看到以下输出:

dataflow:>dataflow config info
dataflow config info

╔═══════════╤═══════════════════════════════════════╗
║Credentials│[username='my_username, password=****']║
╠═══════════╪═══════════════════════════════════════╣
║Result                                            
║Target     │http://localhost:9393                  
╚═══════════╧═══════════════════════════════════════╝

或者,您可以指定 credentials-provider 命令以直接传入令牌,而不是提供用户名和密码。这可以在 shell 中运行,也可以在启动Shell时指定--dataflow.credentials-provider-command命令行参数。

使用credentials-provider命令时,请注意您的指定命令必须返回 Bearer token(以Bearer为前缀的token)。例如,在Unix环境中,可以使用以下简单命令:

$ java -jar spring-cloud-dataflow-shell-2.1.0.RELEASE.jar \
  --dataflow.uri=http://localhost:9393 \
  --dataflow.credentials-provider-command="echo Bearer 123456789"

8. 关于配置

Spring Cloud Data Flow 的 相关 Restful API 包含显示名称,版本,包含name, version, 和Spring Cloud Data Flow 的 依赖项URL(如果指定了)。 shell dependency 还包括 sha1 或 sha256 的值的校验(如果启用)。通过设置以下属性,可以配置为每个依赖项返回的信息:

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-core.name:用于核心的名称。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-core.version:用于核心的版本。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-dashboard.name:用于仪表板的名称。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-dashboard.version:用于仪表板的版本。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-implementation.name:用于实现的名称。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-implementation.version:用于实现的版本。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.name:用于shell的名称。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.version:用于shell的版本。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.url:用于下载shell依赖项的URL。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha1:与shell依赖关系信息一起返回的sha1校验和值。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha256:与shell依赖关系信息一起返回的sha256校验和值。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha1-url:如果spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha1 未指定,则SCDF使用此URL指定的文件内容作为校验和。

  • spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha256-url:如果spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha256 未指定,则SCDF使用此URL指定的文件内容作为校验和。

8.1. 启用 Shell Checksum values

默认情况下,不会进行 shell dependency 的值的校验。如果需要启用此功能,请将该spring.cloud.dataflow.version-info.dependency-fetch.enabled属性设置为true。

8.2. URL的 Reserved Values

您可以在URL中插入 Reserved Values(用花括号括起来),以确保链接是最新的:

  • repository :如果使用 Data Flow 的构建快照,里程碑或候选发布版,则使用repo-spring-io存储库。否则,它指的是Maven Central。

  • version:jar 的 pom的版本。

例如, 如果您用的是Spring Cloud Data Shell 的1.2.3.RELEASE版本,则会myrepository/org/springframework/cloud/spring-cloud-dataflow-shell/{version}/spring-cloud-dataflow-shell-{version}.jar 生成 myrepository/org/springframework/cloud/spring-cloud-dataflow-shell/1.2.3.RELEASE/spring-cloud-dataflow-shell-1.2.3.RELEASE.jar

Last updated