变更概述
Edge for Private Cloud 4.53.01 引入了多项变更,通过纳入更新版本的软件/库来增强平台的安全态势。这些更改会影响:
- OAS(OpenAPI 规范)验证政策
- 支持 JSONPath 查询的政策
- 依赖于已弃用库的 Java callout 政策
- OpenLDAP
本部分介绍了版本 4.53.01 中引入的各种可能会在升级期间或升级后中断工作流的更改。本文还介绍了如何识别潜在的问题领域,以及缓解或解决问题的方法。
OAS(OpenAPI 规范)验证政策
上下文
OAS 验证政策可根据 OpenAPI 3.0 规范(JSON 或 YAML)中定义的规则验证传入的请求或响应。Edge for Private Cloud 4.53.01 增强了 OAS(OpenAPI 规范)政策,重点在于对 API 响应正文进行更严格、更准确的验证。
变更
Edge for Private Cloud 4.53.01 在 OAS 政策验证 API 响应的方式方面引入了两项重要变更,可确保与您的 OpenAPI 规范更加一致:
- 场景 1:
- 之前的行为:如果您的 OpenAPI 规范要求包含响应正文,但目标或上游政策的实际响应未包含响应正文,则该政策不会将其标记为验证错误。
- 当前行为:在此场景中,政策现在会正确返回验证错误(例如:
defines a response schema but no response body found
),表明预期响应与实际响应不匹配。
- 场景 2:
- 之前的行为:如果您的 OpenAPI 规范明确指出不应有响应正文,但目标或上游政策的实际响应包含正文,则该政策不会导致失败。
- 当前行为:在此场景中,该政策现在会导致失败(例如:
No response body is expected but one was found
),从而确保回答严格遵循指定的架构。
应对措施
确定任何将 OAS 验证政策配置为 Source 标记设置为 response
的代理或共享流,或者验证来自生成响应的任何其他政策的响应的代理或共享流。
确定代理/共享流后,确保响应与 OAS 规范保持一致。响应必须严格遵循 OpenAPI 规范,确保响应正文的存在与否符合规范。您可以使用标准 Apigee 跟踪来查看流量模式。如果目标间歇性地返回响应,请使用其他政策在 OAS 政策之前对其进行验证
- 如果您的 OAS 规范文件定义了响应正文,则目标政策或上游政策的响应必须始终提供一个响应正文。
- 如果您的 OAS 规范文件未定义响应正文,则目标或上游政策不得发送响应正文。
在尝试升级到 Private Cloud 4.53.01 之前,请根据需要更新 OAS 验证政策或目标行为。您应先在非生产环境中验证此类已识别的工作流,以最大限度地降低在生产集群升级期间发生中断的风险。
JSON 路径
上下文
Edge for Private Cloud 4.53.01 针对各种政策中 JSON 路径表达式的使用方式引入了更改。JSONPath 表达式可用于 ExtractVariable 政策、RegularExpressionProtection 政策、数据遮盖等政策,以解析 JSON 内容或将值存储在变量中。JSONPath 表达式还可用于常规消息模板,以便在代理执行期间动态地将变量替换为值。新的 JSONPath 表达式和格式遵循最新的 JSON 表达式标准。
变更
请务必检查现有 API 代理/共享流中是否包含使用 JSONPath 表达式的政策。这包括但不限于 ExtractVariables 政策、RegularExpressionProtection 政策或任何使用 JSONPath 的消息模板政策。
以下 JSON 输入用于说明更改:
{ "store": { "book": [ {"category": "reference", "author": "Nigel Rees", "price": 8.95}, {"category": "fiction", "author": "Evelyn Waugh", "price": 12.99}, {"category": "fiction", "author": "Herman Melville", "price": 8.99} ], "bicycle": { "color": "red", "book": [ {"author": "Abc"} ] } } }
- 针对对象值的 JSONPath 通配符
[*]
行为变更当使用
[*]
通配符访问 JSON 对象的所有直接值时,其行为已发生变化。之前,$.object[*]
会返回封装在单个 JSON 对象中的立即值。使用更新后的库,输出现在是一个包含这些值的数组。例如
之前的行为:$.store[*]
: 当前行为:{ "bicycle": { "color": "red", "book": [{"author": "Abc"}] }, "book": [ {"price": 8.95, "category": "reference", "author": "Nigel Rees"}, {"price": 12.99, "category": "fiction", "author": "Evelyn Waugh"}, {"price": 8.99, "category": "fiction", "author": "Herman Melville"} ] }
操作:[ [ {"category": "reference", "author": "Nigel Rees", "price": 8.95}, {"category": "fiction", "author": "Evelyn Waugh", "price": 12.99}, {"category": "fiction", "author": "Herman Melville", "price": 8.99} ], { "color": "red", "book": [{"author": "Abc"}] } ]
将 JSONPath 表达式更改为仅定位父对象(例如:
$.store
),以直接定位之前检索到的项。 - 路径中的 JSONPath 尾随点
(.)
会导致错误JSONPath 表达式的验证更加严格。之前,如果路径以无效的尾随点结尾(例如
$.path.to.element.
),系统会默默忽略该路径,并且如果前面的有效路径段匹配,查询仍会返回结果。在新版本中,此类格式错误的路径现在可以正确识别为无效,并会导致错误。例如
之前的行为:$.store.book.
。 当前行为:[ {"price":8.95,"category":"reference","author":"Nigel Rees"}, {"price":12.99,"category":"fiction","author":"Evelyn Waugh"}, {"price":8.99,"category":"fiction","author":"Herman Melville"} ]
ERROR: com.jayway.jsonpath.InvalidPathException - Path must not end with a '.' or '..'
任何使用带有意外尾随句点的 JSONPath 表达式的现有政策现在都会失败,并显示
操作:InvalidPathException
。移除以句点结尾的所有 JSONPath 表达式中的末尾句点。例如,将
$.store.book.
更改为$.store.book
。 - JSONPath 递归下降
(..)
输出结构变更使用
(..)
(递归下降)运算符查找命名元素的所有出现位置时,结果的返回方式发生了变化。以前,所有找到的元素都会扁平化为单个列表。更新后的库现在会返回列表的列表,从而保留找到元素的原始分组结构,而不是返回单个扁平列表。例如
之前的行为:$..book
。 当前行为:[ {"price":8.95,"category":"reference","author":"Nigel Rees"}, {"price":12.99,"category":"fiction","author":"Evelyn Waugh"}, {"price":8.99,"category":"fiction","author":"Herman Melville"}, {"author":"Abc"} ]
操作:[ [ {"category":"reference","author":"Nigel Rees","price":8.95}, {"category":"fiction","author":"Evelyn Waugh","price":12.99}, {"category":"fiction","author":"Herman Melville","price":8.99} ], [ {"author":"Abc"} ] ]
更新下游处理逻辑,以适应新的嵌套数组结构。您可能需要遍历外部 JSONArray,然后遍历每个内部 JSONArray 才能访问各个元素。
- 在多项选择或过滤后,JSONPath 索引返回空数组
当在多项选择器(例如
[*]
)或过滤器 ([?(condition)]
) 之后立即应用索引(例如[0]
)时,行为会发生变化。以前,此类表达式会尝试从合并结果中选择指定索引处的项。在新版本中,这些表达式现在将返回一个空数组 ([]
)。例如
之前的行为:$.store.book[*][0]
。 当前行为:{"category": "reference", "price": 8.95, "author": "Nigel Rees"}
操作:[]
如果需要先过滤,然后从过滤后的集合中获取特定项,请处理 JSONPath 返回的过滤后的数组(例如
$..book[?(@.category == 'fiction')]
),然后从上一个结果中获取[0]
。 - JSONPath 负数组切片输出更改
新版本修改了负数组切片的行为(例如:
[-2:], [-1:]
)。以前,当对数组应用负切片(表示数组末尾的元素)时,旧版本会错误地仅返回该切片中的单个项。新版本现在可以正确返回一个列表(数组),其中包含指定负范围内的所有元素。例如
之前的行为:$.store.book[-2:]
当前行为:{"price":12.99,"category":"fiction","author":"Evelyn Waugh"}
操作:[ {"category":"fiction","author":"Evelyn Waugh","price":12.99}, {"category":"fiction","author":"Herman Melville","price":8.99} ]
现在,必须更新下游处理逻辑,以遍历返回的 JSON 数组来获取所需的输出。
- JSONPath 更严格的前导点
对于直接从根访问的元素,语法执行更加严格。当直接从根访问元素而不带前导点(例如:
$propertyelement
)时,此类语法现在会被视为错误,并会阻止代理部署。例如
$store
,{ "bicycle": { "color": "red", "book": [{"author": "Abc"}] }, "book": [ {"price": 8.95, "category": "reference", "author": "Nigel Rees"}, {"price": 12.99, "category": "fiction", "author": "Evelyn Waugh"}, {"price": 8.99, "category": "fiction", "author": "Herman Melville"} ] }
当前行为:
Proxy will fail to deploy.
操作:
将 JSONPath 更改为包含点:
$.propertyName
(例如:$.store
)。这样便可正确定位并检索相应值。 - 动态 JSONPath 表达式
请密切关注 JSONPath 表达式本身由变量(例如
或{myJsonPathVariable}
)提供的政策。这些变量的值也必须根据上述潜在的行为变更进行检查。{dynamicPath}
应对措施
为了缓解这种情况,我们需要制定全面的策略。此过程包括确定合适的更新路径,并应用必要的修复来解决 JSONPath 表达式中断的问题。
选择最适合您的升级途径方法:
- 零停机时间迁移
此策略涉及获取一个或多个新环境,以便您可以将单独的消息处理器节点连接到这些环境。此类消息处理器节点可以设置为安装 4.53.01,并具有采用新式 JSONPath 表达式的代理。这些节点可在升级期间使用,并在升级完成后停用。此策略可实现无缝升级,但需要临时购置额外的消息处理器节点,以支持平稳升级。详情如下:
- 创建新环境,并向此新环境添加版本为 4.53.01 的新消息处理器节点。
- 将受影响代理的代理软件包上传到新环境,应用补救措施部分中说明的必要修复,并将更新后的代理软件包部署到新环境。
- 将流量重定向到新环境,并从旧环境中取消部署受影响的代理。
- 将原始消息处理器节点升级到 4.53.01。在原始环境中部署包含 JSONPath 修复的代理。
- 将流量切换回旧环境,该环境现在具有 4.53.01 版本的消息处理器和已针对新的 JSONPath 表达式进行现代化的代理。
- 删除并停用新环境和关联的节点。
- 停机时间和升级
此策略涉及使用有缺陷的 JSON 路径表达式来获取 API 代理的停机时间。它不需要购买额外的消息处理器节点,但会导致受影响的代理的 API 流量中断。
- 确定受影响的代理(具有受影响的政策),并为所有受影响的代理生成新的修订版本。
- 通过在代理的新修订版本中实现“补救”部分中说明的修复,应用必要的修复。暂时不要部署。
- 为受影响的代理安排停机时间。
- 将所有消息处理器升级到 Edge Private Cloud 版本 4.53.01。请注意,现有代理可能会在新升级的消息处理器上失败。
- 所有消息处理器都升级到 Edge Private Cloud 版本 4.53.01 后,部署新创建的包含已修复 JSONPath 表达式的代理修订版本。
- 恢复此类代理上的流量。
- 在升级之前重新设计代理
您可以在升级到 Edge for Private Cloud 4.53.01 之前重新设计代理本身。您可以使用其他方法来获得相同的结果,而不必依赖特定的 JSON 路径表达式。
例如,如果您使用的是带有 JSON 路径的“提取变量”政策,则可以在升级到较新版本之前,将该政策替换为提取类似数据的 JavaScript 政策。升级完成后,您可以将代理更改回使用 JSON 路径和较新格式。
JavaCallout 变更
上下文
Edge for Private Cloud 4.53.00 及更早版本包含一个名为 deprecated ($APIGEE_ROOT/edge-message-processor/lib/deprecated
) 的目录,其中包含大量 JAR 库。这些库可用于 JavaCallout 政策中的 Java 代码,并且可由您的自定义 Java 代码直接或间接使用。
变更
在 Edge Private Cloud 版本 4.53.01 中,已移除已弃用的目录。如果您的 Java 代码依赖于此类库,那么当消息处理器升级到版本 4.53.01 时,使用此类 Java 调用的代理将失败。为避免此类故障,请在将消息处理器升级到版本 4.53.01 之前,按照以下缓解步骤操作。
应对措施
- 检查您的 Java-Callout 政策和关联的 JAR,确定其中是否有任何政策引用或使用当前消息处理器的“deprecated”目录中的任何库。请注意,Java 标注可能正在使用作为组织或环境级资源上传的 JAR。您也可以考虑使用以下库。
- 确定此类已弃用的库后,您可以按照以下方法之一来缓解问题。
- 资源放置(如果您有少量 Java-Callout jar 引用的已弃用目录中的 jar / 库,建议采用此方法)
- 在所需级别(API 代理修订版本、环境或组织)将已标识的已弃用 JAR 上传为资源。
- 照常继续进行 Apigee 软件升级。
- 手动放置(如果您有大量 Java-Callout JAR 引用的 JAR / 库,建议使用此方法)
- 在每个消息处理器节点上,在路径
$APIGEE_ROOT/data/edge-message-processor/
下创建一个名为 external-lib 的新目录。 - 将已识别的 JAR 从已弃用的目录复制到此 external-lib 目录:
cp $APIGEE_ROOT/edge-message-processor/lib/deprecated/some.jar
$APIGEE_ROOT/data/edge-message-processor/external-lib/some.jar
- 确保 Apigee 用户可以读取目录和底层 JAR:
chown -R apigee:apigee
$APIGEE_ROOT/data/edge-message-processor/external-lib
- 照常继续进行 Apigee 软件升级。
- 在每个消息处理器节点上,在路径
- 资源放置(如果您有少量 Java-Callout jar 引用的已弃用目录中的 jar / 库,建议采用此方法)
OpenLDAP 变更
上下文
在 Edge Private Cloud 中,OpenLDAP 可用于身份验证和授权。在 Edge for Private Cloud 4.53.01 中,Apigee 随附的 OpenLDAP 软件已从版本 2.4 升级到 2.6。
变更
在 OpenLDAP 2.6 中,相对专有名称 (RDN) 的长度限制为大约 241 字节/字符。此限制是强制执行的硬性上限,无法修改。
影响- 对于 RDN 过大的条目,会发生复制或导入失败。
- 尝试创建组织、环境、自定义角色、权限等实体可能会导致错误消息:
"message": "[LDAP: error code 80 - Other]"
。 - Apigee 的 LDAP 中任何长度超过 241 字节的 DN 都会受到影响。此类 DN 会阻止 Apigee OpenLDAP 软件成功升级,您必须先针对此类项采取缓解策略,然后才能继续升级。
一般来说,在 Apigee 的 LDAP 中,长 DN 与权限相关,因为它们是通过连接多个实体创建的。此类权限条目尤其容易出现升级问题。
例如,
dn: cn=@@@environments@@@*@@@applications@@@*@@@revisions@@@*@@@debugsessions,ou=resources,cn=businessuser,ou=userroles,o=orgname,ou=organizations,dc=apigee,dc=com
通常,您会使用长度合适的组织、环境和角色名称,以便 LDAP 中的 RDN 最终小于 241 字节。
应对措施
升级到 4.53.01 之前:
以下步骤将帮助您验证现有 LDAP 2.4 集群中是否存在较长的 RDN。
#1 - 提取 LDAP 数据
使用 ldapsearch 命令查找标识名 (dn),并将输出重定向到文件:
ldapsearch -o ldif-wrap=no -b "dc=apigee,dc=com" -D "cn=manager,dc=apigee,dc=com" -H ldap://:10389 -LLL -x -w LDAP_PASSWORD dn > /tmp/DN.ldif
确保上述 DN.ldif 文件包含 LDAP 条目。
#2 - 识别较长的 RDN
从上述 DN.ldif 文件中找到超过 241 字节/字符的 RDN:
cat /tmp/DN.ldif | grep '^dn:' | gawk -F',|dn: ' '{ rdn = $2; char_count = length(rdn); cmd = "echo -n \"" rdn "\" | wc -c"; cmd | getline byte_count; close(cmd); if (char_count > 241 || byte_count > 241) { print rdn, "(chars: " char_count ") (bytes: " byte_count ")"; }}' o=VeryLongOrgNameWithMoreThan241Chars.... (chars: 245) (bytes: 245) cn=VeryLongCustomRoleNameWithMoreThan241Chars.... (chars: 258) (bytes: 258)
如果上述命令未产生任何输出,则现有 LDAP 设置中没有 RDN 超过 241 字节/字符。您可以像往常一样继续升级。
如果上述命令生成输出,则表示存在超过 241 字节/字符的 RDN。对于此类问题,请按照第 3 步中所述的缓解步骤操作,然后再继续升级到 Edge for Private Cloud 4.53.01。
#3 - 处理较长的 RDN
如果收到第 2 步的输出,则表示存在超过 241 字节/字符的 RDN,请按照以下缓解步骤操作:
查看超过 241 字节的 LDAP 条目。
- 如果 RDN 过长主要是因为自定义角色名称、应用、API 产品或其他实体的名称过长,请改用名称较短的替代实体。
- 如果组织名称或环境名称是导致 RDN 过长的主要因素,您将必须迁移到名称较短的其他组织或环境。
继续重复上述步骤,直到您的 LDAP 中没有长度超过 241 字节的 RDN 为止。达到此状态后,请照常继续进行私有云版本升级。
加密提供程序更改
上下文
此变更沿袭自 Edge for Private Cloud 4.53.00。在 Edge for Private Cloud 4.53.00 中,内部加密提供程序已从 Bouncy Castle (BC) 更新为 Bouncy Castle FIPS (BCFIPS),以启用 FIPS 支持。
变更
如果 JavaCallout 政策依赖于使用原始 BC 提供程序,尤其是在使用 BCFIPS 提供程序中已加强的安全功能时(例如,使用通用密钥对进行加密和签名),则需要对这些 JavaCallout 政策进行现代化改造。尝试使用名称 BC 加载 Bouncy Castle 加密提供程序的 JavaCallout 政策可能会失败,因为默认提供程序已更改。使用 BC 提供程序的此类政策随后可能会中断。依赖于旧版 BC 提供程序的任何自定义实现都将无法再访问,需要进行审核并重新实现。
应对措施
建议的解决方法是使用 BCFIPS 提供程序。依赖于旧提供程序的自定义 JavaCallout 实现需要使用 Bouncy Castle FIPS 提供程序(可通过字符串“BCFIPS”访问)进行检查和重新实现。
自动化更改检测工具
我们计划很快发布一款变更检测工具。此工具将能够扫描并识别可能受到本文中所述各种更改影响的 API 代理、共享流、资源和 LDAP RDN。此工具应有助于识别在升级到 Edge for Private Cloud 4.53.01 期间或之后容易发生故障的各种实体。