Connector 自定义源或目标

最后更新:2021-12-13

1. 基础约束

基础约束

  1. 插件工程命名 开发插件时,首先要新建一个插件的子module,插件工程的名字统一为 sync-plugin-xxxx,名称统一小写,如果名称是2个单词,建议用中线“-”分开。例如:IDP4Scim 命名为:sync-plugin-idp4-scim;

  2. 插件包依赖 新建子模块也是maven工程,该工程的父模块为:idp4-sync ;其依赖的工程只能有:sync-engine ,不建议依赖其他工程,特别不要依赖是 sync-core-local\sync-core-web\sync-application\sync-application-console

  3. 插件包命名统一为:com.idsmanager.idp.sync.plugin.xxxx ;例如IDP4的插件包命名为:com.idsmanager.idp.sync.plugin.idp4

2. 自定义来源插件

demo地址:https://github.com/aliyun-idaas/connector-source-demo

2.1. 工程说明

插件中主要分为 “数据实体、数据映射、配置文件、同步逻辑”模块。
其中各模块中重要的类有:
DemoSourceConnectionMetadata.java
数据源连接的基础方法类,同步引擎根据数据源提供的文档实现各种查询方法。
_DemoConfiguration.java _
数据源各项页面配置,页面提交的数据源配置参数会落到该类。
DemoAccountEntity.java
DemoOrganizationEntity.java
数据源账户和组织机构的字段。
DemoSourceDataPullClient.java
** **
数据源拉取数据类,其中会实现数据源API文档中拉取数据的逻辑,包括增量全量逻辑。
DemoAttributeGetter.java
来源字段映射为目标字段的类。

2.2. 开发流程

2.2.1. 修改名称

将sync-plugin-demo工程中的demo,修改为具体业务名称。
必须修改模块名称,禁止使用demo字样
比如:pom中的 **artifactId **、包名、类名等

2.2.2. 修改类型名称

修改_DemoSourceConnectionMetadata_中的主、子类型名称,需要在对应的主子类型中添加相应的枚举,一般只允许添加子类型枚举。子类型以**_SCHEMA**结尾,前端才能获取到相应的表单json信息。
image.png

2.2.3. 修改Entity类中

修改DemoSourceAccountEntity, DemoSourceOrganizationEntity, DemoSourceBaseEntity类的属性为具体字段。
DemoSourceBaseEntity为抽象类,定义了一些默认参数,一般情况下可以不用管。
DemoSourceAccountEntity和DemoSourceOrganizationEntity为同步到目标所需要的实际字段,同时有一些同步必须的字段,实现了SourceDataItem的接口,需要返回什么值,详见相应方法上的**TODO**。
image.png

2.2.4. 修改默认字段映射字段

增加后再配置字段映射时,就能直接下拉选择,不需要手动输入
image.png

2.2.5. 修改来源管理页面参数字段

  1. 修改DemoSourceClientConfiguration和DemoConfiguration类,来定义页面上配置来源管理中所需要填写的字段。

DemoConfiguration定义来源和来源管理中,通用的字段。
DemoSourceClientConfiguration定义来源管理中,特有的字段。
image.png

  1. 修改resources下的SCHEMA模板,key与上面的字段一致,具体如何使用这个SCHEMA,会在下面进行详细说明。前端页面会获取这个json的各种信息进行渲染,前端提交参数后会转换为configuration类,在后续代码中使用。

image.png

image.png

2.2.6. 修改同步拉取数据方法

拉取数据源的数据操作实现都在**DemoSourceDataPullClient**。
image.png

  1. context 数据推送上下文对象,可以获取当前正在推送的任务、来源、目标、任务批次ID等信息,也能获取当前的同步引擎核心对象的实例(DataTransformEngine) ,里边封装了很多目标插件需要的接口,具体可查看代码注释。


  1. 数据拉取的具体业务逻辑,不同插件要求各部相同,就需要插件的实现者,根据项目需求,酌情实现。这里强调一点:**无论同步哪一种对象,目标系统一定要提供一个该对象的唯一不变字段,用于我们识别同一个对象;具体有以下4个方法

    • pullRegularData

拉取常规的指定对象类型的数据。一次性拉取数据无序。对应“经典目录模式(无序)”

  • pullFullRegularOneLevelChildren

全量拉取指定的组织和用户。
同步引擎会从根一层一层调用该方法,直至数据不再有下级数据,适用于活动目录类型的数据源。(保证数据质量,不要尾首相接,导致无限循环)
拉取人员时会先一层一层先拉组织,再同时拉取组织下的人员。对应“活动目录模式(有序)”

  • pullFullRegularChildrenByPage

分页模式拉取数据

  • pullDeletedData

拉取已删除的指定对象类型的数据。

拉取逻辑实现后最终组装成 List items 返回即可。

3. 自定义目标插件

demo地址:https://github.com/aliyun-idaas/connector-target-demo

3.1. 工程说明

插件中主要分为 “数据实体、数据映射、配置文件、同步逻辑”模块。
其中各模块中重要的类有:
DemoTargetConnectionMetadata.java
目标系统连接的基础方法类,同步引擎根据目标系统提供的文档实现各种查询方法。
_DemoConfiguration.java _
目标系统各项页面配置,页面提交的目标系统配置参数会落到该类。
DemoTargetAccountEntity.java
DemoTargetOrganizationEntity.java
目标系统账户和组织机构的字段。
DemoTargetDataPushClient.java
** **
目标系统推送数据类,其中会实现目标系统API文档中推送数据的逻辑,包括增量全量逻辑。
DemoAttributeSetter.java
把来源的属性映射为目标字段的属性。

3.2. 开发流程

3.2.1. 修改名称

将sync-plugin-demo工程中的demo,修改为具体业务名称。
必须修改模块名称,禁止使用demo字样
比如:pom中的 **artifactId **、包名、类名等

3.2.2. 修改类型名称

修改DemoTargetConnectionMetadata中的主、子类型名称,需要在对应的主子类型中添加相应的枚举,一般只允许添加子类型枚举。子类型以**_SCHEMA**结尾,前端才能获取到相应的表单json信息。
image.png

3.2.3. 修改Entity类中

修改DemoTargetAccountEntity, DemoTargetOrganizationEntity, DemoTargetBaseEntity类的属性为具体字段。
DemoTargetBaseEntity为抽象类,定义了一些默认参数,一般情况下可以不用管。
DemoTargetAccountEntity和DemoTargetOrganizationEntity为同步到目标所需要的实际字段,同时有一些同步必须的字段,实现了TargetDataItem的接口,需要返回什么值,详见相应方法上的**TODO**。
image.png

3.2.4. 修改默认字段映射字段

增加后再配置字段映射时,就能直接下拉选择,不需要手动输入
image.png

3.2.5. 修改目标管理页面参数字段

  1. 修改DemoTargetClientConfiguration和DemoConfiguration类,来定义页面上配置目标管理中所需要填写的字段。

DemoConfiguration定义来源和目标管理中,通用的字段。
DemoTargetClientConfiguration定义目标管理中,特有的字段。
1639128862085-277c1bae-fb72-43de-8d2f-6c11b750b7e3.png

  1. 修改resources下的SCHEMA模板,key与上面的字段一致,具体如何使用这个SCHEMA,会在下面进行详细说明。前端页面会获取这个json的各种信息进行渲染,前端提交参数后会转换为configuration类,在后续代码中使用。

image.png

image.png

3.2.6. 修改同步推送方法

ApiResult push(TargetDataItem item, DataTransformContext context, DataRelation relation) throws SCIMException; 该方法用于实现真正的向目标推送数据。

  1. TargetDataItem item 里边是具体需要进行推送的数据对象的实例,已经完成字段映射。

这个对象是通过newTargetDataItem方法,由引擎模块sync-engine实例化的一个对象; 如果当前推送的是用户,那么 item 就是映射后的用户的具体信息;如果是机构,那么item 就是映射后的机构的具体信息。

  1. context 数据推送上下文对象,可以获取当前正在推送的任务、来源、目标、任务批次ID等信息,也能获取当前的同步引擎核心对象的实例(DataTransformEngine) ,里边封装了很多目标插件需要的接口,具体可查看代码注释。

  2. DataRelation relation 数据映射对象。很多场景下,同一个对象(例如用户),在来源和目标两个系统里的唯一标识,并不相同,IDsConnector支持维护映射关系。如果relation 对象不为空,代表系统中已经存在了映射关系。

例如同步到钉钉的时候,组织的唯一id是钉钉自己生成的,无法使用idp的外部id,又因为id中已经创建好了组织,钉钉的唯一id无法回写到idp中。那么这个组织唯一id的关联关系,就可以使用设个对象进行维护,并写入到数据库中,这样就能在做更新或删除操作时,能正确的找到钉钉的唯一id来执行相应操作。

  1. 数据推送的具体业务逻辑,不同插件要求各部相同,就需要插件的实现者,根据项目需求,酌情实现。这里强调一点:**无论同步哪一种对象,目标系统一定要提供一个该对象的唯一不变字段,用于我们识别同一个对象;

强烈建议,目标系统要提供根据该唯一标识字段,查询用户是否存在的接口,针对新增和更新操作,我们都是优先查询对象是否存在,存在则更新,不存在则新增(无论来源传递的操作是新增还是更新)。**同步任务中有个配置叫“是否开启检查模式”【 DataTransformTask类的 boolean isCheckModel() 方法】,在demo中,有使用示例。

4. 插件schema接口说明

自定义的来源插件和目标插件,需要填写的表单,由后端提供相应的schema来实现,存储到数据库时,也是以json串的形式进行存储。

4.1. 接口定义:

4.1.1. 获取源插件schema

4.1.1.1. 基本信息

Path:/api/sync/v1/connection/source/schema/{minorType}
**Method:**GET

4.1.1.2. 请求参数:

名称

类型

是否必须

说明

minorType

String

插件名字

4.1.1.3. 返回数据

名字

类型

备注

data

object

schema内容

message

string

错误信息

success

boolean

是否成功

code

string

错误码

4.1.1.4. 返回数据示例:

{
    "status": 0,
    "message": "操作成功",
    "requestId": "FCD94521-2BBF-4345-9902-BD8C09C8E81D",
    "data": {
        "detailsData": [
            {
                "name": {
                    "en": "enterpriseId",
                    "zh": "enterpriseId"
                },
                "show": false,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "instanceId"
            },
            {
                "name": {
                    "en": "uuid",
                    "zh": "uuid"
                },
                "show": false,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "applicationUuid"
            },
            {
                "name": {
                    "en": "Application Logo",
                    "zh": "应用图标"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "logoUuid"
            },
            {
                "name": {
                    "en": "Application ID",
                    "zh": "应用ID"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "purchaseId"
            },
            {
                "name": {
                    "en": "Application Name",
                    "zh": "应用名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "name"
            },
            {
                "name": {
                    "en": "Login URL",
                    "zh": "登录 URL"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "loginPageUrl"
            },
            {
                "name": {
                    "en": "Form Submit URL",
                    "zh": "登录提交 URL"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "loginUrl"
            },
            {
                "name": {
                    "en": "Username Name Attribute",
                    "zh": "登录名属性名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "usernameField"
            },
            {
                "name": {
                    "en": "Password Name Attribute",
                    "zh": "登录密码属性名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "passwordField"
            },
            {
                "name": {
                    "en": "Logon Button Name Attribute",
                    "zh": "登录按钮属性名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "submitField"
            },
            {
                "name": {
                    "en": "Other Logon Information",
                    "zh": "登录其他信息"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "othersPageContent"
            },
            {
                "name": {
                    "en": "Logon Success Page",
                    "zh": "登录成功跳转地址"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "loginSuccessPage"
            },
            {
                "name": {
                    "en": "Application Status",
                    "zh": "应用状态"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "enabled",
                "textFormat": "enabled"
            },
            {
                "name": {
                    "en": "Account Linking Type",
                    "zh": "账户关联方式"
                },
                "show": false,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "templateDto.templateName"
            },
            {
                "name": {
                    "en": "Creator",
                    "zh": "创建人"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "creator"
            },
            {
                "name": {
                    "en": "CreateTime",
                    "zh": "创建时间"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "createTime"
            }
        ]
    },
    "success": true,
    "code": "0"
}

4.1.2. 获取目标插件schema

4.1.2.1. 基本信息

Path:/api/sync/v1/connection/target/schema/{minorType}
**Method:**GET

4.1.2.2. 请求参数:

名称

类型

是否必须

说明

minorType

String

插件名字

4.1.2.3. 返回数据

名字

类型

备注

data

object

schema内容

message

string

错误信息

success

boolean

是否成功

code

string

错误码

4.1.2.4. 返回数据示例:

{
    "status": 0,
    "message": "操作成功",
    "requestId": "FCD94521-2BBF-4345-9902-BD8C09C8E81D",
    "data": {
        "detailsData": [
            {
                "name": {
                    "en": "enterpriseId",
                    "zh": "enterpriseId"
                },
                "show": false,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "instanceId"
            },
            {
                "name": {
                    "en": "uuid",
                    "zh": "uuid"
                },
                "show": false,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "applicationUuid"
            },
            {
                "name": {
                    "en": "Application Logo",
                    "zh": "应用图标"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "logoUuid"
            },
            {
                "name": {
                    "en": "Application ID",
                    "zh": "应用ID"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "purchaseId"
            },
            {
                "name": {
                    "en": "Application Name",
                    "zh": "应用名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "name"
            },
            {
                "name": {
                    "en": "Login URL",
                    "zh": "登录 URL"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "loginPageUrl"
            },
            {
                "name": {
                    "en": "Form Submit URL",
                    "zh": "登录提交 URL"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "loginUrl"
            },
            {
                "name": {
                    "en": "Username Name Attribute",
                    "zh": "登录名属性名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "usernameField"
            },
            {
                "name": {
                    "en": "Password Name Attribute",
                    "zh": "登录密码属性名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "passwordField"
            },
            {
                "name": {
                    "en": "Logon Button Name Attribute",
                    "zh": "登录按钮属性名称"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "submitField"
            },
            {
                "name": {
                    "en": "Other Logon Information",
                    "zh": "登录其他信息"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "othersPageContent"
            },
            {
                "name": {
                    "en": "Logon Success Page",
                    "zh": "登录成功跳转地址"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "loginSuccessPage"
            },
            {
                "name": {
                    "en": "Application Status",
                    "zh": "应用状态"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "enabled",
                "textFormat": "enabled"
            },
            {
                "name": {
                    "en": "Account Linking Type",
                    "zh": "账户关联方式"
                },
                "show": false,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "templateDto.templateName"
            },
            {
                "name": {
                    "en": "Creator",
                    "zh": "创建人"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "creator"
            },
            {
                "name": {
                    "en": "CreateTime",
                    "zh": "创建时间"
                },
                "show": true,
                "description": {
                    "en": "",
                    "zh": ""
                },
                "key": "createTime"
            }
        ]
    },
    "success": true,
    "code": "0"
}

4.2. 后端插件文件说明:

在插件代码目录resources目录下,建立schema目录,按照下图所示,建立schema文件:
image.png
其中:

  • source_xxx.json 为源schema定义文件

  • target_xxx.json 为目标schema定义文件

  • xxx为插件ID,和MinorType类中定义的label一直,注意大小写

  • 注意启用了shema配置的插件,插件命名必须为插件ID_SCHEMA

  • 文件内容请参考sync-plugin-amdp项目,示例如下:

{ 
  "form":{
    "baseURL": "",
    "authType": "oauth2",
    "clientId": "",
    "clientSecret": "",
    "apiVersion":""
  },
  "template":{
    "formData": [
     {
        "key": "baseURL",
        "name": { "zh": "baseURL", "en": "baseURL" },
        "type": "input",
        "readonly": false,
        "placeholder": { "zh": "请输入Basic URL", "en": "请输入Basic URL" },
        "rules": { "required": true, "message": "请输入Basic URL", "trigger": "blur" },
        "show": true,
        "send": true
      },
      {
        "key": "authType",
        "name": { "zh": "认证方式", "en": "认证方式" },
        "type": "radio",
        "options": [
          { "label": "oauth2", "value": { "zh": "OAuth2", "en": "OAuth2" }, "disabled": false }
        ],
        "placeholder": { "zh": "请输入Basic URL", "en": "请输入Basic URL" },
        "rules": { "required": true, "message": "请输入Basic URL", "trigger": "blur" },
        "show": true,
        "send": true
      },
     {
        "key": "clientId",
        "name": { "zh": "Client ID", "en": "Client ID" },
        "type": "input",
        "readonly": false,
        "placeholder": { "zh": "请输入Client ID", "en": "请输入Client ID" },
        "rules": { "required": true, "message": "请输入Client ID", "trigger": "blur" },
        "show": true,
        "send": true
      },
      {
        "key": "clientSecret",
        "name": { "zh": "Client Secret", "en": "Client Secret" },
        "type": "input",
        "readonly": false,
        "placeholder": { "zh": "请输入Client Secret", "en": "请输入Client Secret" },
        "rules": { "required": true, "message": "请输入Client Secret", "trigger": "blur" },
        "show": true,
        "send": true
      },
      {
        "key": "apiVersion",
        "name": { "zh": "版本号", "en": "版本号" },
        "type": "input",
        "readonly": false,
        "placeholder": { "zh": "请输入IDP4版本号", "en": "请输入IDP4版本号" },
        "rules": { "required": true, "message": "请输入IDP4版本号", "trigger": "blur" },
        "show": true,
        "send": true
      }
   ]
  }
  
}