civicrm / civicrm-cxn-rpc
CiviConnect 的 RPC 库
v0.20.12.02
2022-05-10 22:59 UTC
Requires
- phpseclib/phpseclib: ~2.0
- psr/log: ~1.1 || ~2.0 || ~3.0
This package is auto-updated.
Last update: 2024-09-11 03:52:50 UTC
README
Civi\Cxn\Rpc 实现了一种基于 X.509 和 JSON 的 RPC 机制。通常,它基于三方之间的非对称业务关系
- "站点"是最终用户组织拥有的在线属性。它们代表了一个组织的规范数据存储。有多个站点。在测试和评论中,我们将参考一个名为
SaveTheWhales.org
的示例站点。 - "应用程序"是具有增值服务的在线属性。它们补充了站点。只有少数应用程序,并且它们必须经过认证才能上线。在测试和评论中,我们将参考一个名为
AddressCleanup.com
的示例服务。 - 一个仲裁者("目录服务"和"证书授权中心")发布和认证可用应用程序的列表。在评论中,我们将参考一个名为
cxn.civicrm.org
的服务。
站点和应用程序之间没有预先存在的信任,并且只有在站点通过注册与应用程序关联后才能建立数据交换。仲裁者通过广告和认证应用程序的公钥来促进注册(撤销应用程序的公钥)但不能参与任何其他数据交换。
测试套件
civicrm-cxn-rpc
的测试套件是用 PHPUnit 实现的。它通常与 PHPUnit 4 一起执行,例如。
git clone https://github.com/civicrm/civicrm-cxn-rpc
cd civicrm-cxn-rpc
composer install
phpunit4
协议 v0.2
CiviConnect 协议 v0.2 定义了站点、应用程序和仲裁者之间的主要使用场景和消息交换。使用场景包括
- 注册使用场景:一个站点(
SaveTheWhales.org
)通过 POST 一个RegistrationMessage
来创建到应用程序(AddressCleanup.com
)的新连接。AddressCleanup.com
使用一个StdMessage
进行响应。 - CiviCRM API 使用场景:一个应用程序(
AddressCleanup.com
)通过 POST 一个StdMessage
来读取或写入 CiviCRM 站点(SaveTheWhales.org
)上的记录。SaveTheWhales.org
使用一个StdMessage
进行响应。 - 服务发现使用场景:一个站点(
SaveTheWhales.org
)通过向仲裁者的目录服务(https://cxn.civicrm.org/cxn/apps
)发送一个基本的 HTTP GET 请求来获取可用应用程序的列表。仲裁者响应一个AppMetasMessage
。
最重要的消息类型包括
RegistrationMessage
(《SaveTheWhales.org》=>《AddressCleanup.com》)- 使用场景:注册使用场景
- 负载:注册包括连接的唯一标识符、共享密钥和回调 URL。(更多讨论见下文。)
- 加密:生成一个临时密钥并使用应用程序的公钥(RSA-2048)进行加密。负载被加密(AES-CBC)、日期化(ttl)并使用密钥进行签名(HMAC-SHA256)。(另见:AesHelper、StdMessage)
- 注意:注册 请求 使用 RegistrationMessage,但 确认 使用 StdMessage。
StdMessage
(《AddressCleanup.com》=>《SaveTheWhales.org》)- 使用场景:注册使用场景,CiviCRM API 使用场景
- 负载:各种
- 负载(CiviCRM API 请求):一个实体+操作+参数三元组(如 Civi APIv3 所示)。
- 加密:共享密钥用于生成AES加密密钥和HMAC签名密钥。有效载荷和ttl使用AES-CBC(256位)加密,密文使用HMAC-SHA256签名。(参见:AesHelper)请求和响应使用相同的方案。
- 注意:当应用程序通过POST发送
StdMessage
时,它包含最新证书的副本。接收方将对其进行验证以确保应用程序仍然受仲裁者的信任。
AppMetasMessage
(cxn.civicrm.org
=>SaveTheWhales.org
)- 用例:服务发现用例
- 有效载荷:应用程序列表包括每个应用程序的标题、描述、注册URL和X.509证书。
- 加密:有效载荷和ttl由
cxn.civicrm.org
(RSA,2048位密钥)签名并以明文形式传输。
此外,还有两种非实质性消息类型。它们不应用于主要活动,但可能有助于顾问错误报告。
InsecureMessage
- 用例:服务器(
RegistrationServer
或ApiServer
)接收到的消息无法验证或解密。服务器必须响应NACK,但它缺乏足够的信息来安全地通信。它发送一个InsecureMessage
。 - 有效载荷:错误消息。
- 加密:未加密且未签名。
- 用例:服务器(
GarbledMessage
- 用例:客户端(
RegistrationClient
或ApiClient
)接收到的响应无法解码。- (例如:服务器存在错误或配置不当,PHP错误消息被写入密文。)
- (例如:中间人干扰了消息传输。)
- 有效载荷:未知
- 加密:未知
- 用例:客户端(
一些考虑事项
- 消息可以通过HTTP、HTTPS或其他任何介质传递。通过HTTPS传递消息更可取(因为HTTPS支持更复杂的加密),但即使在HTTP上,所有交互都将被加密。
- 应用程序证书使用CiviCRM CA进行验证。这似乎比信任世界各地的数百个随机CA要好——有一个故障点而不是数百个故障点。
- 如果CA被破坏,并且攻击者可以对网站或应用程序执行中间人攻击,那么它可能会破坏新连接。但是,它无法破坏现有连接,因为CA缺乏知识或手段来操纵共享密钥。
- 网站不需要证书。只有应用程序需要证书,并且应用程序的数量相对较小。因此,我们不需要自动证书注册。这显著简化了操作CA的技术和风险。
协议v0.2:注册消息
当网站(SaveTheWhales.org
)向应用程序(AddressCleanup.com
)发送消息时,使用RegistrationMessage
格式。最常见的情况是发送Cxn.register
请求。
消息数据包括以下键
entity
:字符串。目前,只有"Cxn"被使用。action
:字符串。cxn
:数组。见Cxn.php
。params
:数组。根据实体/动作而变化。
以下实体/动作受支持
Cxn
.register
(必需):建立新的连接或更新现有连接。cxn
:对于更新,必须同时匹配cxnId
和secret
先前的注册。params
:无- 注意:
RegistrationServer
提供了一个标准实现。
Cxn
.unregister
(必需):销毁现有连接。cxn
:必须同时匹配先前的注册中的cxnId
和secret
。params
:无- 注意:
RegistrationServer
提供了一个标准实现。
Cxn
.getlink
(可选):为受认证的服务创建链接。cxn
:必须同时匹配先前的注册中的cxnId
和secret
。参数
:page
:字符串。要加载的页面名称(例如:"settings")。
- 注意:应用程序有权在AppMeta中定义链接。如果 AppMeta中存在链接,它们将使用
getlink
进行解析。为了支持这一点,可以扩展RegistrationServer
并定义function onCxnGetlink(...)
。
协议v0.1
从未发布或完成。总体而言,v0.1协议依赖于客户端和服务器端证书,并使用RSA加密所有消息。v0.1存在一些问题
- 如果证书颁发机构受到损害,那么对CA的高度信任可能会被滥用以破坏现有连接。
- 对所有内容使用RSA意味着加密在典型的API调用中较慢。
基本类
在创建新代理时,应使用以下四个辅助类之一
- RegistrationClient:网站使用此类建立与应用程序的连接。
- RegistrationServer:应用程序使用此类接受来自网站的注册。
- ApiClient:应用程序使用此类向网站发送API调用。
- ApiServer:网站使用此类接受来自应用程序的API调用。
策略建议
- 应用程序应接受新的注册。如果尝试使用现有的cxnId进行注册,则使用共享密钥作为客户端身份验证--如果共享密钥匹配,则接受更新注册;否则,拒绝。
- 应用程序应定期验证其连接--即发出“System.get”的API调用,以确保连接与运行兼容版本的活跃Civi安装相对应。
- 应用程序应部署在HTTPS上以提供额外的安全性(例如前向安全性)。然而,这可能会影响兼容性/可达性,并且协议加密所有消息,因此仍然可以使用HTTP。