civicrm/civicrm-cxn-rpc

CiviConnect 的 RPC 库

v0.20.12.02 2022-05-10 22:59 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
    • 用例:服务器(RegistrationServerApiServer)接收到的消息无法验证或解密。服务器必须响应NACK,但它缺乏足够的信息来安全地通信。它发送一个InsecureMessage
    • 有效载荷:错误消息。
    • 加密:未加密且未签名。
  • GarbledMessage
    • 用例:客户端(RegistrationClientApiClient)接收到的响应无法解码。
      • (例如:服务器存在错误或配置不当,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:对于更新,必须同时匹配cxnIdsecret先前的注册。
    • params:无
    • 注意:RegistrationServer提供了一个标准实现。
  • Cxn.unregister(必需):销毁现有连接。
    • cxn:必须同时匹配先前的注册中的cxnIdsecret
    • params:无
    • 注意:RegistrationServer提供了一个标准实现。
  • Cxn.getlink(可选):为受认证的服务创建链接。
    • cxn:必须同时匹配先前的注册中的cxnIdsecret
    • 参数:
      • 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。