UAA 是一个多租户身份管理服务,用于 Cloud Foundry,但也可以作为独立的 OAuth2 服务器使用。它的主要角色是作为 OAuth2 提供者,为客户端应用程序在代表 Cloud Foundry 用户执行操作时颁发令牌。 它还可以使用用户的 Cloud Foundry 凭证对用户进行认证, 并且可以作为使用这些凭证(或其他凭证)的 SSO 服务。它 具有用于管理用户账户和注册 OAuth2 客户端的端点,以及各种其他管理功能。
要求:
如果以下操作成功,你就进入正轨了:
$ git clone git://github.com/cloudfoundry/uaa.git
$ cd uaa
$ ./gradlew run
这些应用协同工作,所有应用都运行在同一个端口
(8080)上,路径分别为 /uaa、/app 和 /api。
UAA 会将日志写入名为 uaa.log 的文件,可以使用以下命令找到它:-
$ sudo find / -name uaa.log
你应该会在类似以下路径下找到它:-
/private/var/folders/7v/518b18d97_3f4c8fzxphy6f8zcm51c/T/cargo/conf/logs/
你也可以构建该应用并将其推送到 Cloud Foundry,例如: 我们推荐使用清单文件,但你也可以在命令行上完成所有操作。
$ ./gradlew :cloudfoundry-identity-uaa:war
$ cf push myuaa --no-start -m 512M -p uaa/build/libs/cloudfoundry-identity-uaa-2.3.2-SNAPSHOT.war
$ cf set-env myuaa SPRING_PROFILES_ACTIVE default,hsqldb
$ cf set-env myuaa UAA_URL http://myuaa.<domain>
$ cf set-env myuaa LOGIN_URL http://myuaa.<domain>
$ cf set-env myuaa JBP_CONFIG_SPRING_AUTO_RECONFIGURATION '[enabled: false]'
$ cf set-env myuaa JBP_CONFIG_TOMCAT '{tomcat: { version: 7.0.+ }}'
$ cf start myuaa
在上述步骤中,请替换:
myuaa 为唯一的应用程序名称2.3.2-SNAPSHOT 为你构建中相应的版本标签<domain> 为你的应用程序域。我们将来会从系统环境中解析该值首先按照上述说明运行 UAA 服务器:
$ ./gradlew run
然后打开另一个终端,在项目基础目录下,请求登录端点以获取系统信息:
$ curl -H "Accept: application/json" localhost:8080/uaa/login
{
"timestamp":"2012-03-28T18:25:49+0100",
"commit_id":"111274e",
"prompts":{"username":["text","Username"],
"password":["password","Password"]
}
}
然后你可以尝试使用 UAA ruby gem 登录。请确保你已安装 ruby 1.9,然后执行
$ gem install cf-uaac
$ uaac target http://localhost:8080/uaa
$ uaac token get marissa koala
(或者省略用户名/密码以提示输入)。
这会使用 OAuth2 隐式授权进行认证并从服务器获取访问令牌,与 CF 等客户端所采用的方式类似。令牌存储在 ~/.uaac.yml 中,因此可以查看该文件并为你的 cf 目标提取访问令牌(或者在上面的登录命令行中使用 --verbose 查看其记录到控制台)。
然后你可以作为资源服务器登录并检索令牌详细信息:
$ uaac target http://localhost:8080/uaa
$ uaac token decode
你应在 stdout 中看到你的用户名和原始令牌授权的客户端 ID,例如:
exp: 1355348409
user_name: marissa
scope: cloud_controller.read openid password.write scim.userids tokens.read tokens.write
email: [email protected]
aud: scim tokens openid cloud_controller password
jti: ea2fac72-3f51-4c8f-a7a6-5ffc117af542
user_id: ba14fea0-9d87-4f0c-b59e-32aaa8eb1434
client_id: cf
$ ./gradlew -Dspring.profiles.active=default,mysql run
此命令将假定有一个 MySQL 数据库可用,并使用默认访问设置,并响应以下 JDBC 设置。
driver = 'org.mariadb.jdbc.Driver'
url = 'jdbc:mysql://localhost:3306/uaa'
user = 'root'
password = 'changeme'
schemas = ['uaa']
类似地,如果你执行命令
$ ./gradlew -Dspring.profiles.active=default,postgresql run
它将使用定义为
driver = 'org.postgresql.Driver'
url = 'jdbc:postgresql:uaa'
user = 'root'
password = 'changeme'
的设置。
这些设置在 Gradle 集成的两个地方重复出现。 它们被定义为 Spring XML 配置文件中的默认值,同时也定义在主 build.gradle 文件中。它们放在 Gradle 构建文件中的原因是,在启动 UAA 应用程序之前,Gradle 总是执行 flywayClean 任务。如果你不希望清理数据库,可以在命令行中定义变量
-Dflyway.clean=false
这会禁用 gradle 脚本中的 flywayClean 任务。 另一种禁用 flywayClean 的方法是不在命令行中指定 spring profiles,而是在 uaa.yml 和 login.yml 文件中设置 profiles。
相同的命令行示例应该可以在 run.pivotal.io 上运行的 UAA 上工作(除了令牌解码部分,因为你没有客户端密钥)。在这种情况下,无需运行本地 uaa 服务器,只需请求外部登录端点以获取系统信息:
$ curl -H "Accept: application/json" login.run.pivotal.io
{
"prompts":{"username":["text","Username"],
"password":["password","Password"]
}
}
然后你可以尝试使用 UAA ruby gem 登录。请确保你已安装 ruby 1.9,然后执行
$ gem install cf-uaac
$ uaac target uaa.run.pivotal.io
$ uaac token get [yourusername] [yourpassword]
(或者省略用户名/密码以提示输入)。
这会使用 OAuth2 隐式授权进行认证并从服务器获取访问令牌,与 CF 等客户端所使用的授权方式相同。
你可以使用以下命令运行集成测试
$ ./gradlew integrationTest
该命令将针对运行在本地 Apache Tomcat 实例中的 uaa 服务器运行集成测试,例如服务 URL 设置为 http://localhost:8080/uaa(默认情况下)。
你可以设置 CLOUD_FOUNDRY_CONFIG_PATH 以使用 uaa.yml,在其中可以更改 URL,
并(如果适用)设置运行服务器的上下文根(更多细节见下文)。
要修改运行时参数,你可以提供 uaa.yml,例如:
$ cat > /tmp/config/uaa.yml
uaa:
host: uaa.appcloud21.dev.mozycloud
test:
username: [email protected] # defaults to [email protected]
password: changeme
email: [email protected]
然后从 uaa/uaa 目录执行
$ CLOUD_FOUNDRY_CONFIG_PATH=/tmp/config ./gradlew test
Web 应用在启动时会从以下位置查找 Yaml 内容 (后面的条目会覆盖前面的条目):
classpath:uaa.yml
file:${CLOUD_FOUNDRY_CONFIG_PATH}/uaa.yml
file:${UAA_CONFIG_FILE}
${UAA_CONFIG_URL}
System.getEnv('UAA_CONFIG_YAML') -> environment variable, if set must contain valid Yaml
例如,要将 UAA 部署为 Cloud Foundry 应用程序,你可以提供应用清单,例如:
---
applications:
- name: standalone-uaa-cf-war
memory: 512M
instances: 1
host: standalone-uaa
path: cloudfoundry-identity-uaa-3.0.0-SNAPSHOT.war
env:
JBP_CONFIG_SPRING_AUTO_RECONFIGURATION: '[enabled: false]'
JBP_CONFIG_TOMCAT: '{tomcat: { version: 7.0.+ }}'
SPRING_PROFILES_ACTIVE: hsqldb,default
UAA_CONFIG_YAML: |
uaa.url: http://standalone-uaa.cfapps.io
login.url: http://standalone-uaa.cfapps.io
smtp:
host: mail.server.host
port: 3535
或者,也可以使用 set-env 命令将 yaml 配置作为环境变量的字符串进行设置
cf set-env sample-uaa-cf-war UAA_CONFIG_YAML '{ uaa.url: http://standalone-uaa.myapp.com, login.url: http://standalone-uaa.myapp.com, smtp: { host: mail.server.host, port: 3535 } }'
此外,UAA 读取的任何简单类型属性也可以被完全展开并作为系统环境变量本身读取。 请注意,uaa.url 可以转换为名为 UAA_URL 的环境变量
---
applications:
- name: standalone-uaa-cf-war
memory: 512M
instances: 1
host: standalone-uaa
path: cloudfoundry-identity-uaa-3.0.0-SNAPSHOT.war
env:
JBP_CONFIG_SPRING_AUTO_RECONFIGURATION: '[enabled: false]'
JBP_CONFIG_TOMCAT: '{tomcat: { version: 7.0.+ }}'
SPRING_PROFILES_ACTIVE: hsqldb,default
UAA_URL: http://standalone-uaa.cfapps.io
LOGIN_URL: http://standalone-uaa.cfapps.io
UAA_CONFIG_YAML: |
smtp:
host: mail.server.host
port: 3535
默认的 uaa 单元测试(./gradlew test integrationTest)使用 hsqldb。
要使用 postgresql 运行单元测试:
$ ./gradlew -Dspring.profiles.active=default,postgresql test integrationTest
可选地,Spring profile 可以在 uaa.yml 文件中配置
$ echo "spring_profiles: default,postgresql" > src/main/resources/uaa.yml
要使用 mysql 运行单元测试:
$ ./gradlew -Dspring.profiles.active=default,mysql test integrationTest
common 和 scim 模块的数据库配置默认在
Spring XML 配置文件 中设置。
你可以通过在 uaa.yml 中配置它们来更改。
默认值为
PostgreSQL: 用户:root 密码:changeme 数据库:uaa 主机:localhost 端口:5432
MySQL: 用户:root 密码:changeme 数据库:uaa 主机:localhost 端口:3306
这里实际上有多个项目:主要的 uaa 服务器应用程序、一个客户端库和一些示例:
uaa 一个 WAR 项目,便于部署
server 一个 JAR 项目,包含 UAA REST API(包括 SCIM)和 UI 的实现
model 一个 JAR 项目,供客户端库和服务器共同使用
client-lib 一个 JAR 项目,提供 Java 客户端 API
api(示例)是一个 OAuth2 资源服务,返回已部署应用的模拟列表
app(示例)是一个用户应用程序,使用了上述两者
在 Cloud Foundry 术语中
uaa 提供认证服务,以及为后端服务和应用程序授权的委托(通过颁发 OAuth2 访问令牌)。
api 是一个服务,提供其他应用程序可能希望代表资源所有者(最终用户)访问的资源。
app 是一个 Web 应用,需要单点登录,并代表用户访问 api 服务。
这些项目按水平层次组织;客户端、模型、服务器等。在所有这些项目中,Java 包围绕我们的内部服务垂直组织;区域(zones)、提供者(providers)、客户端(clients)等。
认证服务是 uaa。它是一个普通的 Spring MVC Web 应用。
按照正常方式部署在 Tomcat 或你选择的容器中,或者执行
./gradlew run 直接从源代码树中的 uaa 目录运行它。当使用 gradle 运行时,它监听 8080 端口,URL 为
http://localhost:8080/uaa
UAA 服务器支持 UAA-APIs 文档中定义的 API。总结如下:
OAuth2 /oauth/authorize 和 /oauth/token 端点
一个 /login_info 端点,用于查询所需的登录提示
一个 /check_token 端点,允许资源服务器获取关于 OAuth2 客户端提交的访问令牌的信息。
一个 /token_key 端点,允许资源服务器获取验证密钥以验证令牌签名
SCIM 用户配置端点
OpenID connect 端点,以支持认证 /userinfo。部分 OpenID 支持。
认证可以由命令行客户端通过直接将凭证提交到 /oauth/authorize 端点来执行(如
UAA-API 文档中所述)。 如果你的客户端是 Java,Spring
Security OAuth 中有一个 ImplicitAccessTokenProvider 可以处理繁重的工作。
默认情况下,uaa 将以上下文根 /uaa 启动。
认证
GET /login
一个基本的表单登录界面。
批准 OAuth2 令牌授予
GET /oauth/authorize?client_id=app&response_type=code...
标准 OAuth2 授权端点。
获取访问令牌
POST /oauth/token
标准 OAuth2 授权端点。
应用程序中有两个配置文件 uaa.yml 和 login.yml,它们为 Spring XML 中的占位符提供默认值。
无论你在 XML 中的何处看到 ${placeholder.name},都可以通过提供同名系统属性(-D 给 JVM)或自定义的 uaa.yml 或 login.yml(如上所述)来覆盖它。
uaa.yml 和 login.yml 在启动时会合并为一个配置。
配置文件中的所有密码和客户端密钥都是明文, 但它们会以 BCrypt 加密的方式插入到 UAA 数据库中。
将来,你将能够以 bcrypt 格式提供密码,以避免指定明文密码。
默认情况下使用内存 RDBMS 用户存储,其中预先填充了一个测试用户:marissa 的密码为 koala。
要对用户数据使用 Postgresql,请激活 Spring profile postgresql。
可以使用以下方式在 uaa.yml 中配置活动 profiles:
spring_profiles: postgresql,default
或者在命令行中指定 PostgreSQL:
$ ./gradlew -Dspring.profiles.active=default,postgresql run
UAA 附带了两个示例应用程序:/api 和 /app
使用 ./gradlew run 从 uaa 根目录运行它。
所有三个应用,/uaa、/api 和 /app 会同时部署。
这是一个用户界面应用程序(主要面向浏览器),使用 OpenId Connect 进行认证(即 SSO)和使用 OAuth2 进行访问授权。它与认证服务进行认证,然后访问 API 服务中的资源。使用 ./gradlew run 从 uaa 根目录运行它。
该应用程序可以根据 UAA 服务器和 Login 应用程序的位置(以及是否存在)在多种不同的 profiles 下运行。默认情况下,它会在 localhost:8080/uaa 上查找 UAA,但你可以通过设置名为 UAA_PROFILE 的环境变量(或系统属性)来更改此设置。在应用程序源代码(samples/app/src/main/resources)中,你会找到多个预先配置了这些服务器不同可能位置的 properties 文件。它们都采用 application-<UAA_PROFILE>.properties 的形式,采用的命名约定是:UAA_PROFILE 对于 localhost 部署为 local,对于 vcap.me 部署为 vcap,对于暂存部署为 staging(在 VMware VPN 内部)等。profile 名称是双段的(例如,当登录服务器与 UAA 服务器位于不同位置时,使用 local-vcap)。
查看所有应用
GET /app/apps
浏览器会经历一系列认证和访问授权步骤(这些步骤将来可能会精简为不需要用户参与的隐式步骤),然后显示应用列表。
查看当前登录用户的详细信息,即从 open id 提供者获取的一包属性
GET /app
以下是一些让你参与社区的方式:
