1.管理员控制台
部署完Syncope后,访问protocol://host:port/syncope-console
即可打开管理页面。比如使用docker部署如下
test@root:~$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
890432da5eec apache/syncope-console:2.1.8 "/sbin/startup.sh" 2 weeks ago Up 30 hours 0.0.0.0:28080->8080/tcp syncope_syncope-console_1
98770264f19f apache/syncope-enduser:2.1.8 "/sbin/startup.sh" 2 weeks ago Up 30 hours 0.0.0.0:38080->8080/tcp syncope_syncope-enduser_1
0bf035b6869e apache/syncope:2.1.8 "/sbin/startup.sh" 2 weeks ago Up 30 hours 0.0.0.0:18080->8080/tcp syncope_syncope_1
可以访问http://localhost:28080/syncope-console/
1.1.页面
仪表盘
仪表盘提供了syncope全局的总揽。
域
Realm页面为管理员提供了管理域以及用户、群组和对象的能力。
拓扑
Totology页面提供了连接对象和外部资源之间的映射视图。
点击不同的节点时,会有不同的操作。
报告
Reports页面展示了一系列报告的配置。也允许管理员创建和修改报告配置。
配置
配置页允许管理员根据组织需要定义配置项。
Audit
审计配置
Logs
可以动态调整日志级别
Notifications
管理通知。也允许创建或编辑通知模板
Parameters
展示一系列的配置参数,比如token.expireTime、password.cipher.algorithm等。也可以添加新的参数。
Policies
管理账户、密码以及拉取政策
Roles
展示、编辑角色功能
Security Questions
用于设置一系列的安全问题共用户选择,用于用户忘记密码的情况。
批准
下图展示了自主注册的批准样例以及典型的批准流程:
批准通知
批准申请
批准管理
批准表单
审查修改
批准修改
拓展
拓展配置动态的报告导航菜单:每项拓展生成一页或多页页面以及多个组件。
2.用户终端
访问protocol://host:port/syncope-enduser/
即可使用用户终端。
比如这里用docker部署,即可访问 http://192.168.50.113:38080/syncope-enduser/
。
终端用户应用提供基于web的自主注册、自主服务以及密码重置应用。
通常,组织会深度定制用户系统,不仅在外观上,而且往往在后端的实际机制上,以便最适合其流程和流程。
所以用户终端的前端采用AngularJS编写,便于拓展和定制。
3.命令行工具
略
4.RESTful 服务
Syncope所有的Core服务都可以同多RESTful服务访问。
基本路由:
protocol://host:port/syncope/rest/
4.1.REST认证和授权
Core 服务的认证和授权基于Spring Security。
初始化时,认证使用HTTP头部:X-Syncope-Token获取JSON Web Token用于后续的请求。
使用初始交换的Token即可基于权限认证请求。
用户可以通过X-Syncope-Entitlements头部值查看授权,通过X-Syncope-Privileges头查看权限。
SecurityContext.xml中定义了相关的安全配置。
默认可以使用HTTP Basic Authentication
JWTSSOProvider
除了可以接受和认证JWB,Syncope还提供了JWTSSOProvider接口以处理第三方生成的JWT。
4.2.REST 头部
除了常用的Accept\Contetn-Type等,Syncope支持一些额外的HTTP头部。
X-Syncope-Token:认证成功后,在响应头返回,返回值是全局唯一的JWT,用于标记认证的用户。
X-Syncope-Token的值必须在之后的请求作为标注的Bear Authorization请求头的一部分携带,用于请求的认证。
例:
curl -I -u admin:password -X POST http://localhost:9080/syncope/rest/accessTokens/login
returns
HTTP/1.1 204
X-Syncope-Token: eyJ0e..
which can then be used to make a call to the REST API
curl -I -H "Authorization: Bearer eyJ0e.." http://localhost:9080/syncope/rest/users/self
token的有效期可以通过jwt.lifetime.minutes配置。
X-Syncope-Domain:可以在请求头中携带,用于选择目标域名,如果没有则默认为Master。所有的响应中都会返回这一头部。
X-Syncope-Key and Location:创建实体(用户、群组、模型、外部资源…)时,这两个头部会分别返回,并标识新REST资源的绝对URI。
X-Application-Error-Code and X-Application-Error-Info:如果请求的操作有错,则会通过这两个头部返回错误码或错误详情。
X-Syncope-Null-Priority-Async:如果请求头中设置这个值为true,则,该请求在与未设置优先级的外部资源通信时,不会等待完成。
Prefer and Preference-Applied:某些REST终端允许通过Prefer头部请求明确的行为。当指定了Prefer头部,响应头将包含Preference-Applied,并把值设置为有效的首选项。
return-content/return-no-content:REST终端在创建、更新或删除用户、群组以及其他对象时默认在相应中返回实体信息。
如果不需要这些信息,可以设置Prefer请求头为return-no-content。
在需要避免响应非必要数据的场景中使用 Prefer: return-no-content请求头。
respond-async:Batch终端可以请求异步处理。
ETag, If-Match and If-None-Match:当响应中有用户、群组以及其他对象时,会包含ETag相应头,标记对象最后一次修改时间。
如果后续请求需要更新相同的实体,可以通过If-Match或If-None-Match头部携带ETag的值。
ETag和If-Match的组合使用可用于乐观并发。
X-Syncope-Entitlements:使用GET方法和/user/self端点交互时,会返回X-Syncope-Entitlements响应头展现当前用户所有的授权。
X-Syncope-Privileges:使用GET方法和/user/self端点交互时,会返回X-Syncope-Privileges响应头展现当前用户所有的权限。
4.3.Batch
Batch请求将多个操作组合在一个请求中。
批处理请求指 Multipart MIME v1.0 message,一种标准格式,允许在单个请求中表示多个部分,每个部分可能具有不同的内容类型(比如JSON、YAML或XML)。
批处理请求通过POST方法向/batch端点请求,通过GET方法获取异步响应。
批处理请求:批处理请求必须携带Content-Type请求头指定值为multipart/mixed并指定boundary。
批处理请求体由一组独立的请求组成,每个请求表示一种MIME部分(通过Content-Type请求头中的boundary分割)。
核心层将依次处理批处理请求中的请求。
但个请求必须包含application/http的Content-Type请求头,和包含binary的Content-Transfer-Encoding请求头。
例:
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652 <1>
Content-Type: application/http
Content-Transfer-Encoding: binary
^M <2>
POST /users HTTP/1.1 <3>
Accept: application/json
Content-Length: 1157
Content-Type: application/json
^M
{"@class":“org.apache.syncope.common.lib.to.UserTO”,“key”:null,“type”:“USER”,“realm”:"/"}
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652
Content-Type: application/http
Content-Transfer-Encoding: binary
^M
POST /groups HTTP/1.1 <4>
Accept: application/xml
Content-Length: 628
Content-Type: application/xml
^M
</syncope21:group>
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652
Content-Type: application/http
Content-Transfer-Encoding: binary
^M
PATCH /users/[email protected] HTTP/1.1 <5>
Accept: application/json
Content-Length: 362
Content-Type: application/json
Prefer: return-no-content
^M
{"@class":“org.apache.syncope.common.lib.patch.UserPatch”,“key”:“[email protected]”}
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652
Content-Type: application/http
Content-Transfer-Encoding: binary
^M
DELETE /groups/287ede7c-98eb-44e8-979d-8777fa077e12 HTTP/1.1 <6>
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652–
<1>message boundary
<2>represents CR LF
<3>使用JSON创建用户
<4>使用XML创建群组
<5>使用JSON更新用户
<6>删除群组
批处理响应:批处理中的请求将根据请求出现在批处理上下文之外时使用的相同语义进行评估。
批处理请求中每个请求的顺序很重要。
如果批处理请求的请求头是正确的,则会响应200 OK表示请求被接受,以及相应的执行结果。
如果请求头不正确,则会响应400 Bad Request。
批处理请求的响应一定会返回包含multipart/mixed的Content-Type响应头。
在结构上,批处理响应主体必须与相应的批处理请求主体一一匹配,以便为请求定义的相同的多部分MIME消息结构用于响应。
例:
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652 <1>
Content-Type: application/http
Content-Transfer-Encoding: binary
^M <2>
HTTP/1.1 201 Created <3>
Content-Type: application/json
Date: Thu, 09 Aug 2018 09:55:46 GMT
ETag: “1533808545975”
Location: http://localhost:9080/syncope/rest/users/d399ba84-12e3-43d0-99ba-8412e303d083
X-Syncope-Domain: Master
X-Syncope-Key: d399ba84-12e3-43d0-99ba-8412e303d083
^M
{“entity”:{"@class":“org.apache.syncope.common.lib.to.UserTO”}
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652
Content-Type: application/http
Content-Transfer-Encoding: binary
^M
HTTP/1.1 201 Created <4>
Content-Type: application/xml
Date: Thu, 09 Aug 2018 09:55:46 GMT
ETag: “1533808546342”
Location: http://localhost:9080/syncope/rest/groups/843b2fc3-b8a8-4a8b-bb2f-c3b8a87a8b2e
X-Syncope-Domain: Master
X-Syncope-Key: 843b2fc3-b8a8-4a8b-bb2f-c3b8a87a8b2e
^M
<syncope21:provisioningResult xmlns:syncope21=“http://syncope.apache.org/2.1”></syncope21:provisioningResult>
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652
Content-Type: application/http
Content-Transfer-Encoding: binary
^M
HTTP/1.1 204 No Content <5>
Content-Length: 0
Date: Thu, 09 Aug 2018 09:55:47 GMT
Preference-Applied: return-no-content
X-Syncope-Domain: Master
^M
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652
Content-Type: application/http
Content-Transfer-Encoding: binary
^M
HTTP/1.1 200 OK <6>
Content-Type: application/json
Date: Thu, 09 Aug 2018 09:55:47 GMT
X-Syncope-Domain: Master
^M
{“entity”:{"@class":“org.apache.syncope.common.lib.to.GroupTO”}
–batch_61bfef8d-0a00-41aa-b775-7b6efff37652–
<1>message boundary (same as request)
<2>represents CR LF
<3>使用JSON响应用户创建
<4>使用XML相应群组创建
<5>用户更新响应,因为设置了Prefer: return-no-content请求头,所以没有相应内容
<6>使用JSON相应群组删除
异步批处理过程:
通过携带包含response-async的Prefer请求头可以执行异步批处理操作。
Core服务会返回202 Accept响应。
客户端可以使用GET方法携带相同的boundary轮询 /batch端点查询处理结果。
如果返回202 Accepted则表示还在构建中,如果处理成功,则返回200 OK并返回批处理结果。
批处理结果只能查询一次。
4.4.搜索
用户、群组以及其他符合FIQL条件的对象都可以搜索。FIQL是一种简洁、灵活且URI友好的语法,用于筛选实体。
例:
- GET /users?fiql=query
- GET /groups?fiql=query
- GET /anyObjects?fiql=query
- GET /resources/{resource}/{anytype}?fiql=query
其中: - query是URL编码的字符串、
- resource是任意定义好的外部资源
- anytype是任意定义好的类型
例,简单的属性查询: - musernamerossini
通配符匹配
username*ini - 大小写敏感的匹配
username==~rOsSiNi - 大小写敏感的通配符匹配
username==~*iNi - 空属性匹配:
loginDate==$null - 日期对比:
lastLoginDate=ge=2016-03-02 15:21:22 - 资源匹配:
$resources==resource-ldap - 群组成员匹配(不适用群组对象)
$groups==root - 角色成员关系匹配(仅适合用户)
$roles==Other - 类型匹配(仅使用其他对象)
$type==PRINTER - 复杂关系匹配
username=~*iNi;(loginDate== n u l l , null, null,roles==Other)
查询结果排序
查询结果可以通过orderBy查询参数排序,例: - GET /users?fiql=query&orderBy=sort
- GET /groups?fiql=query&orderBy=sort
- GET /anyObjects?fiql=query&orderBy=sort
- GET /resources/{resource}/{anytype}?orderBy=sort
其中,sort是URL编码的字符串
例: - 单属性分类,默认升序
username - 制定顺序的但属性分类
username DESC - 多属性分类
email DESC, username ASC
4.5.客户端库
Java客户端通过隐藏潜在的HTTP通信细节和提供本地化方法和副在对象,简化了Core服务的接口。
这些库可以作为Maven使用:
<dependency>
<groupId>org.apache.syncope.client</groupId>
<artifactId>syncope-client-lib</artifactId>
<version>2.1.8</version>
</dependency>
初始化
首先使用项目URL构建SyncopeClientFactoryBean实例:
SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean().
setAddress("http://localhost:9080/syncope/rest/");
也可以指定域名(默认Master),选择XML负载(默认JSON),选择HTTP压缩方案,以及设置TLS客户端配置:
TLSClientParameters tlsClientParameters = ...;
SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean().
setAddress("http://localhost:9080/syncope/rest/").
setDomain("Two").
setContentType(SyncopeClientFactoryBean.ContentType.XML).
setUseCompression(true).
setTlsClientParameters(tlsClientParameters);
SyncopeClient实例可以通过传递登陆凭证获取:
SyncopeClient client = clientFactory.create("admin", "password");
或者通过组合语法申明:
SyncopeClient client = new SyncopeClientFactoryBean().
setAddress("http://localhost:9080/syncope/rest/").
create("admin", "password");
使用
选择一个REST服务并交互:
LoggerService loggerService = client.getService(LoggerService.class);
LoggerTO loggerTO = loggerService.read(LoggerType.LOG, "org.apache.syncope.core.connid");
loggerTO.setLevel(LoggerLevel.DEBUG);
loggerService.update(LoggerType.LOG, loggerTO);
例,查询用户、群组或对象:
所有搜索操作都返回分页结果处理程序,可以利用这些处理程序获取实际结果和外推分页坐标。
UserService userService = client.getService(UserService.class);
int count = userService.search(new AnyQuery.Builder().page(0).size(0).build()).getTotalCount(); <1>
PagedResult<UserTO> matchingUsers = userService.search(
new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("ros*ini").query()).
build()); <2>
PagedResult<UserTO> matchingUsers = userService.search(
new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
fiql(SyncopeClient.getUserSearchConditionBuilder().isNull("loginDate").query()).
build()); <3>
PagedResult<UserTO> matchingUsers = userService.search(
new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
fiql(SyncopeClient.getUserSearchConditionBuilder().inRoles("Other").query()).
build()); <4>
AnyObjectService anyObjectService = client.getService(AnyObjectService.class);
PagedResult<AnyObjectTO> matchingAnyObjects = anyObjectService.search(
new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM).
fiql(SyncopeClient.getAnyObjectSearchConditionBuilder("PRINTER").query()).
build()); <5>
GroupService groupService = client.getService(GroupService.class);
PagedResult<GroupTO> matchingGroups = groupService.search(
new AnyQuery.Builder().realm("/even/two").page(3).size(150).
fiql(SyncopeClient.getGroupSearchConditionBuilder().isAssignable().
and("name").equalTo("palo*").query()).
build()); <6>
<1>get the total number of users available in the given deployment (and domain)
<2>get users in the root realm with username matching the provided wildcard expression
<3>get users in the root realm with no values for loginDate, i.e. that have never authenticated to the given deployment
<4>get users in the root realm with role Other assigned
<5>get all any objects in the root realm with type PRINTER
<6>get all groups that can be assigned to users or any objects in the /even/two realm - third page of the result, where each page contains 150 items
例,一次性删除多名用户:
BatchRequest batchRequest = client.batch(); <1>
UserService batchUserService = batchRequest.getService(UserService.class);
final int pageSize = 100;
final int count = userService.search(
new AnyQuery.Builder().page(0).size(0).build()).getTotalCount(); <2>
for (int page = 1; page <= (count / pageSize) + 1; page++) {
for (UserTO user : userService.search(
new AnyQuery.Builder().page(page).size(pageSize).build()).getResult()) { <3>
batchUserService.delete(user.getKey()); <4>
}
}
BatchResponse batchResponse = batchRequest.commit(); <5>
List<BatchResponseItem> batchResponseItems = batchResponse.getItems(); <6>
<1>开始请求
<2>获取服务内用户总数
<3>轮询所有用户,分页查询
<4>把每名用户的删除添加到批处理请求中
<5>发送批处理请求
<6>检查批处理结果
例,读取自己的配置文件信息
Pair<Map<String, Set<String>>, UserTO> self = client.self();
UserTO userTO = self.getRight(); <1>
Map<String, Set<String>> realm2entitlements = self.getLeft(); <2>
<1>UserTO of the requesting user
<2>for each realm, the owned entitlements
例,修改用户的状态
String key = ...; <1>
StatusPatch statusPatch = new StatusPatch();
statusPatch.setKey(key);
statusPatch.setType(StatusPatchType.SUSPEND); <2>
UserTO userTO = userService.status(statusPatch).
readEntity(new GenericType<ProvisioningResult<UserTO>>() {
}).getEntity(); <3>
<1>assume the key of the user to be suspended is known in advance
<2>ACTIVATE, SUSPEND, REACTIVATE values are accepted, and honoured depending on the actual status of the user being updated
<3>request for user update and read back the updated entity
4.定制
使用Syncope的Maven项目时,可以定制开发。
为了满足不同环境的需要,Syncope被设计的尽可能灵活。所有的功能和组件都是可插拔的。
一旦从提供的Maven原型创建了项目,生成的源代码树就可以用于添加新特性或替换现有组件。
基本原则就是本地项目的任何文件都将优先于Syncope的同一目录中具有相同名称的文件。比如,如果有core/spring/src/main/java/org/apache/syncope/core/spring/security/SyncopeAuthenticationProvider.java
放置在本地项目中,这个文件将会代替SyncopeAuthenticationProvider。
图片和HTML文件也一样,如果有文件console/src/main/resources/org/apache/syncope/client/console/pages/BasePage.html
放置在项目中,则会替代控制台的基本页面。
但也有一些可能的异常需要注意。如果要定制某项Spring的上下文,比如securityContext.xml,那么也需要把core/src/main/webapp/WEB-INF/web.xml中的内容:
classpath*:/coreContext.xml
classpath*:/securityContext.xml
classpath*:/logicContext.xml
classpath*:/restCXFContext.xml
classpath*:/persistenceContext.xml
classpath*:/provisioning*Context.xml
classpath*:/workflow*Context.xml
替换为:
classpath*:/coreContext.xml
classpath:/securityContext.xml
classpath*:/logicContext.xml
classpath*:/restCXFContext.xml
classpath*:/persistenceContext.xml
classpath*:/provisioning*Context.xml
classpath*:/workflow*Context.xml
一般情况下,嵌入式模块允许用户在但个工作站点完成所有工作。使用所有的Maven组件可以达到这一效果。
当采用JavaEE 容器化部署时,则需要指明需求的组件和拓展,如下文展示:
部署目录
Syncope需要三个基本目录:
- bundles: 用于存储链接组件
- log: 用于写入所有的系统日志
- conf(可选): 防放置配置文件
推荐使用如下结构
$ mkdir /opt/syncope
$ mkdir /opt/syncope/bundles
$ mkdir /opt/syncope/log
$ mkdir /opt/syncope/conf
运行Maven 命令即可生成WAR项目:
$ mvn clean verify \
-Dconf.directory=/opt/syncope/conf \
-Dbundles.directory=/opt/syncope/bundles \
-Dlog.directory=/opt/syncope/log
$ cp core/target/classes/*properties /opt/syncope/conf
$ cp console/target/classes/*properties /opt/syncope/conf
$ cp enduser/target/classes/*properties /opt/syncope/conf
$ cp enduser/target/classes/customFormAttributes.json /opt/syncope/conf
$ cp enduser/target/classes/customTemplate.json /opt/syncope/conf
下载完所有需要的依赖后,会生成三个WAR文件:
core/target/syncope.war
console/target/syncope-console.war
enduser/target/syncope-enduser.war
5.1.Core
5.2.Console
5.3.Enduser
6.系统管理
6.1.DBMS
PostgreSQL
在provisioning.properties中,替换如下内容:
quartz.jobstore=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
quartz.sql=tables_postgres.sql
在domains/Master.properties中,替换如下内容:
Master.driverClassName=org.postgresql.Driver
Master.url=jdbc:postgresql://localhost:5432/syncope
Master.schema=
Master.username=syncope
Master.password=syncope
Master.databasePlatform=org.apache.openjpa.jdbc.sql.PostgresDictionary
Master.orm=META-INF/spring-orm.xml
PostgreSQL (JSONB)
在core/pom.xml中添加如下内容:
<dependency>
<groupId>org.apache.syncope.core</groupId>
<artifactId>syncope-core-persistence-jpa-json</artifactId>
<version>${syncope.version}</version>
</dependency>
在persistence.properties中,替换如下内容:
entity.factory=org.apache.syncope.core.persistence.jpa.entity.PGJPAJSONEntityFactory
plainSchema.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONPlainSchemaDAO
plainAttr.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONPlainAttrDAO
plainAttrValue.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONPlainAttrValueDAO
any.search.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONAnySearchDAO
any.search.visitor=org.apache.syncope.core.persistence.api.search.SearchCondVisitor
user.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONUserDAO
group.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONGroupDAO
anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONAnyObjectDAO
conf.dao=org.apache.syncope.core.persistence.jpa.dao.JPAJSONConfDAO
logger.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAJSONLoggerDAO
在provisioning.properties中,添加如下内容:
quartz.jobstore=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
quartz.sql=tables_postgres.sql
在domains/Master.properties中替换如下内容:
Master.driverClassName=org.postgresql.Driver
Master.url=jdbc:postgresql://localhost:5432/syncope?stringtype=unspecified
Master.schema=
Master.username=syncope
Master.password=syncope
Master.databasePlatform=org.apache.openjpa.jdbc.sql.PostgresDictionary
Master.orm=META-INF/spring-orm-pgjsonb.xml
Master.audit.sql=audit_pgjsonb.sql
MySQL
在provisioning.properties中,添加如下内容:
quartz.jobstore=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
quartz.sql=tables_mysql_innodb.sql
在domains/Master.properties中,替换如下内容:
Master.driverClassName=com.mysql.cj.jdbc.Driver
Master.url=jdbc:mysql://localhost:3306/syncope?useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=UTF-8
Master.schema=
Master.username=syncope
Master.password=syncope
Master.databasePlatform=org.apache.openjpa.jdbc.sql.MySQLDictionary(blobTypeName=LONGBLOB,dateFractionDigits=3)
Master.orm=META-INF/spring-orm.xml
Master.audit.sql=audit_mysql_innodb.sql
其他数据库配置可以参考Syncope。
6.2.数据库连接池
内部存储是为Core服务提供数据存储的中心。
选择好DBMS后,提供一个数据库连接池的配置非常必要。
数据库连接池可以是:
- 应用管理;基于HikariCP,相关参数可以在domains/Master.properties中设置
- JavaEE 容器管理;通过JNDI匹配制定的名称,比如java:comp/env/jdbc/syncopeMasterDataSource,每个JavaEE容器都提供独立的完成这类工作的方法。
6.3.JavaEE容器
参考Syncope。
6.4.高可用
6.5.域名管理
6.6.设置管理凭证
在security.properties文件中设置凭证:
- adminUser: 管理员名称
- adminPassword: 管理员密码
- adminPasswordAlgorithm: hash算法
6.7.配置ConnId地址
Syncope既可以使用本地连接器也可以使用远程连接器。
在connid.properties文件中配置ConnId的地址。
格式如下:
connid.locations=location1,\
location2,\
...
locationN
每个location都代表一条URI,本地格式为file:/path/to/directory/
,远程格式为connid://key@host:port
或者connids://key@host:port[?trustAllcerts=true]
例:
connid.locations=file:/opt/syncope/bundles/,\
file:/var/tmp/bundles/,\
connid://sampleKey@windows2008:4554,\
connids://anotherKey@windows2008:4559,\
connids://aThirdKey@linuxbox:9001?trustAllCerts=true
6.8.内部存储的导出、导入
几乎所有的配置都包含在内部存储中:模型,连接,资源,映射,角色,群组,任务以及别的参数。
部署Syncope项目,可能需要把一个服务的配置复制给另一个服务。
导出
通过命令行、管理员控制台或REST接口都可以导出,例:
curl -X GET -u admin:password -o MasterContent.xml \
http://localhost:9080/syncope/rest/configurations/stream
导入
替换本地的MasterContent.xml即可
$TOMCAT_HOME/webapps/syncope/WEB-INF/classes/domains/MasterContent.xml for Standalone
/usr/share/tomcat8/webapps/syncope/WEB-INF/classes/domains/MasterContent.xml for Debian packages
core/src/test/resources/domains/MasterContent.xml for Maven projects in embedded mode
core/src/main/resources/domains/MasterContent.xml for Maven projects
6.9.安装连接器
6.10.E-mail配置
mail.properties文件中可以配置通知邮件:
-
smtpHost - 邮件SMTP域名;
-
smtpPort - 邮件服务端口;
-
smtpUser - (optional) 邮件账户的用户名;
-
smtpPassword - (optional) 邮件账户的密码;
-
smtpProtocol - 信息传输协议: 默认是smtp, 支持smtps;
-
smtpEncoding - 媒体信息编码方式;
-
mail.smtp.starttls.enable - 设为 true时, 允许使用 STARTTLS 命令在登录前切换为TLS保护的连接;
-
mail.smtp.connectiontimeout - 以 milliseconds为单位的链接超时时间;
-
mail.debug - 设为 true时, 启用电子邮件处理的调试,包括握手、身份验证、传递和断开连接; 为了使设置生效, 需要在log4j2.xml 配置文件中添加一下参数:
<asyncLogger name="org.apache.syncope.core.provisioning.java.job.notification"
additivity="false" level="DEBUG">
<appender-ref ref="mainFile"/>
<appender-ref ref="main"/>
</asyncLogger>
<asyncLogger name="javax.mail" additivity="false" level="DEBUG">
<appender-ref ref="mainFile"/>
<appender-ref ref="main"/>
</asyncLogger>
例,基本配置,不包含认证:
conf.directory=${conf.directory}
smtpHost=your.local.smtp.server
smtpPort=25
smtpUser=
smtpPassword=
smtpProtocol=smtp
smtpEncoding=UTF-8
mail.debug=false
mail.smtp.connectiontimeout=3000
mail.smtp.starttls.enable=false
例,STARTTLS配置,包含认证:
conf.directory=${conf.directory}
smtpHost=smtp.gmail.com
smtpPort=587
[email protected]
smtpPassword=your_password
smtpProtocol=smtp
smtpEncoding=UTF-8
mail.debug=false
mail.smtp.connectiontimeout=3000
mail.smtp.starttls.enable=true
需要重启JavaEE容器使配置生效。
6.11.密钥库
Java密钥库是存储认证凭证或共要凭证的容器。常用于基于Java的应用加密、认证以及HTTPS服务。他的入口由密钥库密码保护。密钥存储库条目由别名标识,它由密钥和证书组成信任链。
SAML2.0服务扩展需要密钥库,以便对生成的SAML2.0请求进行签名加密。
虽然提供了一个示例密钥存储库,但强烈建议设置一个生产密钥存储库;下面展示了参考过程:
创建新的密钥库
keytool -genkey \
-keyalg RSA \
-keysize 2048 \
-alias saml2sp \
-dname "CN=SAML2SP,OU=Apache Syncope, O=The ASF, L=Wilmington, ST=Delaware, C=US" \
-keypass akyepass \
-storepass astorepass \
-storetype JKS \
-keystore saml2sp.jks
上面的命令会生成名为saml2sp.jks
的密钥库文件,包含一个新的2048-bit的RSA键对,同时设置了keypass和storepass的密码值。
创建新的CSR
keytool -certreq \
-alias saml2sp \
-keyalg RSA \
-file certreq.pem \
-keypass akyepass \
-storepass astorepass \
-storetype JKS \
-keystore saml2sp.jks
上面的命令会创建名为certreq.pem的CSR文件,包含上面生成的密钥库。
生成的CSR文件可以发送给CA服务请求CA-签名证书。
把凭证导入密钥库
keytool -import \
-alias root \
-file cacert.pem \
-keypass akyepass \
-storepass astorepass \
-storetype JKS \
-keystore saml2sp.jks
上面的命令会从cacert.pem文件中导入root/intermediaCA凭证到密钥库中
keytool -import \
-alias saml2sp \
-file cert.pem \
-keypass akyepass \
-storepass astorepass \
-storetype JKS \
-keystore saml2sp.jks
上面的命令会从cert.pem中导入签名凭证到密钥库
密钥库文件saml2sp.jks现在必须放在配置目录中;saml2sp-logic-properties文件中的相关部分应为:
keystore.name=saml2sp.jks
keystore.type=jks
keystore.storepass=astorepass
keystore.keypass=akyepass
sp.cert.alias=saml2sp
signature.algorithm=RSA_SHA1
6.12.控制JWT签名
如果认证成功会生成唯一的JWT,由Syncope根据JWS规范生成。
基于散列的消息验证代码
这是默认配置,其中Core服务和客户端拥有一个共享密钥,在security.properties的jwsKey属性中配置:
jwsAlgorithm=HS512 <1>
jwsKey=ZW7pRixehFuNUtnY5Se47IemgMryTzazPPJ9CGX5LTCmsOJpOgHAQEuPQeV9A28f <2>
<1>可选值为 HS256, HS384 和 HS512
<2>可以使用满足长度要求的任何字母数字值
Rsa公钥密码
需要密钥对,私钥保存在Core服务中,公钥共享给客户端。
下面的命令通过OpenSSL生成密钥对,并使用security.properties格式化他们的值:
$ openssl genrsa -out private_key.pem 2048
$ openssl pkcs8 -topk8 -in private_key.pem -inform pem -out jws.privateKey -outform pem -nocrypt
$ openssl rsa -pubout -in private_key.pem -out jws.publicKey
$ echo `sed '1d;$d' jws.privateKey | awk '{printf "%s", $0}'`:`sed '1d;$d' jws.publicKey | awk '{printf "%s", $0}'`