|
| 1 | +--- |
| 2 | +title: 变更性准入策略 |
| 3 | +content_type: concept |
| 4 | +--- |
| 5 | +<!-- |
| 6 | +reviewers: |
| 7 | +- deads2k |
| 8 | +- sttts |
| 9 | +- cici37 |
| 10 | +title: Mutating Admission Policy |
| 11 | +content_type: concept |
| 12 | +--> |
| 13 | + |
| 14 | +<!-- overview --> |
| 15 | + |
| 16 | +{{< feature-state for_k8s_version="v1.32" state="alpha" >}} |
| 17 | +<!-- due to feature gate history, use manual version specification here --> |
| 18 | + |
| 19 | +<!-- |
| 20 | +This page provides an overview of _MutatingAdmissionPolicies_. |
| 21 | +--> |
| 22 | +本页概要介绍 **MutatingAdmissionPolicy(变更性准入策略)**。 |
| 23 | + |
| 24 | +<!-- body --> |
| 25 | + |
| 26 | +<!-- |
| 27 | +## What are MutatingAdmissionPolicies? |
| 28 | +
|
| 29 | +Mutating admission policies offer a declarative, in-process alternative to mutating admission webhooks. |
| 30 | +--> |
| 31 | +## 什么是 MutatingAdmissionPolicy? {#what-are-mutatingadmissionpolicies} |
| 32 | + |
| 33 | +变更性准入策略(Mutating Admission Policy)提供了一种声明式的、进程内的方案, |
| 34 | +可以用来替代变更性准入 Webhook。 |
| 35 | + |
| 36 | +<!-- |
| 37 | +Mutating admission policies use the Common Expression Language (CEL) to declare mutations to resources. |
| 38 | +Mutations can be defined either with an *apply configuration* that is merged using the |
| 39 | +[server side apply merge strategy](/docs/reference/using-api/server-side-apply/#merge-strategy), |
| 40 | +or a [JSON patch](https://jsonpatch.com/). |
| 41 | +
|
| 42 | +Mutating admission policies are highly configurable, enabling policy authors to define policies |
| 43 | +that can be parameterized and scoped to resources as needed by cluster administrators. |
| 44 | +--> |
| 45 | +变更性准入策略使用通用表达语言(Common Expression Language,CEL)来声明对资源的变更。 |
| 46 | +变更操作可以通过使用[服务器端应用合并策略](/zh-cn/docs/reference/using-api/server-side-apply/#merge-strategy)所合并的**应用配置**来定义, |
| 47 | +也可以使用 [JSON 补丁](https://jsonpatch.com/)来定义。 |
| 48 | + |
| 49 | +变更性准入策略的可配置能力很强,策略的编写者可以根据集群管理员的需要,定义参数化的策略以及限定到某类资源的策略。 |
| 50 | + |
| 51 | +<!-- |
| 52 | +## What resources make a policy |
| 53 | +
|
| 54 | +A policy is generally made up of three resources: |
| 55 | +
|
| 56 | +- The MutatingAdmissionPolicy describes the abstract logic of a policy |
| 57 | + (think: "this policy sets a particular label to a particular value"). |
| 58 | +--> |
| 59 | +## 策略包含哪些资源 {#what-resources-make-a-policy} |
| 60 | + |
| 61 | +策略通常由三种资源组成: |
| 62 | + |
| 63 | +- MutatingAdmissionPolicy 描述策略的抽象逻辑(可以理解为:“此策略将特定标签设置为特定值”)。 |
| 64 | + |
| 65 | +<!-- |
| 66 | +- A _parameter resource_ provides information to a MutatingAdmissionPolicy to make it a concrete |
| 67 | + statement (think "set the `owner` label to something like `company.example.com`"). |
| 68 | + Parameter resources refer to Kubernetes resources, available in the Kubernetes API. They can be built-in types or extensions, |
| 69 | + such as a {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}} (CRD). For example, you can use a ConfigMap as a parameter. |
| 70 | +- A MutatingAdmissionPolicyBinding links the above (MutatingAdmissionPolicy and parameter) resources together and provides scoping. |
| 71 | + If you only want to set an `owner` label for `Pods`, and not other API kinds, the binding is where you |
| 72 | + specify this mutation. |
| 73 | +--> |
| 74 | +- 为 MutatingAdmissionPolicy 提供信息的一个**参数资源(parameter resource)**, |
| 75 | + 有了参数之后,策略成为一条具体的语句 |
| 76 | + (假想:“将 `owner` 标签设置为类似 `company.example.com` 的值”)。 |
| 77 | + 参数资源引用 Kubernetes API 中可用的 Kubernetes 某种资源。被引用的资源可以是内置类别或类似 |
| 78 | + {{< glossary_tooltip term_id="CustomResourceDefinition" text="CustomResourceDefinition" >}}(CRD)这种扩展资源。 |
| 79 | + 例如,你可以使用 ConfigMap 作为参数。 |
| 80 | + |
| 81 | +- MutatingAdmissionPolicyBinding 将上述两种资源(MutatingAdmissionPolicy 和参数)关联在一起, |
| 82 | + 并提供作用域限定。如果你只想为 `Pods` 设置 `owner` 标签,而不想为其他 API 类别设置标签, |
| 83 | + 则绑定就是你用来限定此变更的地方。 |
| 84 | + |
| 85 | +<!-- |
| 86 | +At least a MutatingAdmissionPolicy and a corresponding MutatingAdmissionPolicyBinding |
| 87 | +must be defined for a policy to have an effect. |
| 88 | +
|
| 89 | +If a MutatingAdmissionPolicy does not need to be configured via parameters, simply leave |
| 90 | +`spec.paramKind` in MutatingAdmissionPolicy not specified. |
| 91 | +--> |
| 92 | +你必须定义至少一个 MutatingAdmissionPolicy 和一个相应的 MutatingAdmissionPolicyBinding, |
| 93 | +才能使策略生效。 |
| 94 | + |
| 95 | +如果 MutatingAdmissionPolicy 不需要通过参数进行配置,在 |
| 96 | +MutatingAdmissionPolicy 中不指定 `spec.paramKind` 即可。 |
| 97 | + |
| 98 | +<!-- |
| 99 | +## Getting Started with MutatingAdmissionPolicies |
| 100 | +
|
| 101 | +Mutating admission policy is part of the cluster control-plane. You should write |
| 102 | +and deploy them with great caution. The following describes how to quickly |
| 103 | +experiment with Mutating admission policy. |
| 104 | +--> |
| 105 | +## 开始使用 MutatingAdmissionPolicy {#getting-started-with-mutatingadmissionpolicies} |
| 106 | + |
| 107 | +变更性准入策略是集群控制平面的一部分。你在编写和部署这些策略时要非常谨慎。 |
| 108 | +下文描述如何快速试用变更性准入策略。 |
| 109 | + |
| 110 | +<!-- |
| 111 | +### Create a MutatingAdmissionPolicy |
| 112 | +
|
| 113 | +The following is an example of a MutatingAdmissionPolicy. This policy mutates newly created Pods to have a sidecar container if it does not exist. |
| 114 | +--> |
| 115 | +### 创建 MutatingAdmissionPolicy {#create-a-mutatingadmissionpolicy} |
| 116 | + |
| 117 | +以下是一个 MutatingAdmissionPolicy 的示例。 |
| 118 | +此策略会将变更新建的 Pod,为其添加一个边车容器(如果以前没有边车容器的话)。 |
| 119 | + |
| 120 | +{{% code_sample language="yaml" file="mutatingadmissionpolicy/applyconfiguration-example.yaml" %}} |
| 121 | + |
| 122 | +<!-- |
| 123 | +The `.spec.mutations` field consists of a list of expressions that evaluate to resource patches. |
| 124 | +The emitted patches may be either [apply configurations](#patch-type-apply-configuration) or [JSON Patch](#patch-type-json-patch) |
| 125 | +patches. You cannot specify an empty list of mutations. After evaluating all the |
| 126 | +expressions, the API server applies those changes to the resource that is |
| 127 | +passing through admission. |
| 128 | +--> |
| 129 | +`.spec.mutations` 字段由一系列表达式组成,这些表达式求值后将形成资源补丁。 |
| 130 | +所生成的补丁可以是[应用配置](#patch-type-apply-configuration)或 [JSON 补丁](#patch-type-json-patch)。 |
| 131 | +你不能将 mutations 设置为空列表。在对所有表达式求值后,API 服务器将所得到的变更应用到正在通过准入阶段的资源。 |
| 132 | + |
| 133 | +<!-- |
| 134 | +To configure a mutating admission policy for use in a cluster, a binding is |
| 135 | +required. The MutatingAdmissionPolicy will only be active if a corresponding |
| 136 | +binding exists with the referenced `spec.policyName` matching the `spec.name` of |
| 137 | +a policy. |
| 138 | +
|
| 139 | +Once the binding and policy are created, any resource request that matches the |
| 140 | +`spec.matchConditions` of a policy will trigger the set of mutations defined. |
| 141 | +
|
| 142 | +In the example above, creating a Pod will add the `mesh-proxy` initContainer mutation: |
| 143 | +--> |
| 144 | +要配置变更准入策略以便用于某个集群中,需要先创建绑定。 |
| 145 | +只有存在 `spec.policyName` 字段值与某策略的 `spec.name` 相匹配的绑定时,该策略才会生效。 |
| 146 | + |
| 147 | +一旦创建了绑定和策略,策略的 `spec.matchConditions` 相匹配的所有资源请求都会触发已定义的所有变更集合。 |
| 148 | + |
| 149 | +在上面的示例中,创建 Pod 将触发添加 `mesh-proxy` initContainer 这一变更: |
| 150 | + |
| 151 | +```yaml |
| 152 | +apiVersion: v1 |
| 153 | +kind: Pod |
| 154 | +metadata: |
| 155 | + name: myapp |
| 156 | + namespace: default |
| 157 | +spec: |
| 158 | + ... |
| 159 | + initContainers: |
| 160 | + - name: mesh-proxy |
| 161 | + image: mesh/proxy:v1.0.0 |
| 162 | + args: ["proxy", "sidecar"] |
| 163 | + restartPolicy: Always |
| 164 | + - name: myapp-initializer |
| 165 | + image: example/initializer:v1.0.0 |
| 166 | + ... |
| 167 | +``` |
| 168 | + |
| 169 | +<!-- |
| 170 | +#### Parameter resources |
| 171 | +
|
| 172 | +Parameter resources allow a policy configuration to be separate from its |
| 173 | +definition. A policy can define `paramKind`, which outlines GVK of the parameter |
| 174 | +resource, and then a policy binding ties a policy by name (via `policyName`) to a |
| 175 | +particular parameter resource via `paramRef`. |
| 176 | +
|
| 177 | +Please refer to [parameter resources](/docs/reference/access-authn-authz/validating-admission-policy/#parameter-resources) for more information. |
| 178 | +--> |
| 179 | +#### 参数资源 {#parameter-resources} |
| 180 | + |
| 181 | +使用参数资源,我们可以将策略配置与其定义分隔开。策略可以定义 `paramKind`,划定参数资源的 GVK, |
| 182 | +随后的策略绑定操作会通过 `paramRef` 按名称(通过 `policyName`)将某个策略绑定到特定参数资源。 |
| 183 | + |
| 184 | +有关细节参阅[参数资源](/zh-cn/docs/reference/access-authn-authz/validating-admission-policy/#parameter-resources)。 |
| 185 | + |
| 186 | +#### `ApplyConfiguration` {#patch-type-apply-configuration} |
| 187 | + |
| 188 | +<!-- |
| 189 | +MutatingAdmissionPolicy expressions are always CEL. Each apply configuration |
| 190 | +`expression` must evaluate to a CEL object (declared using `Object()` |
| 191 | +initialization). |
| 192 | +
|
| 193 | +Apply configurations may not modify atomic structs, maps or arrays due to the risk of accidental deletion of |
| 194 | +values not included in the apply configuration. |
| 195 | +--> |
| 196 | +MutatingAdmissionPolicy 表达式始终是 CEL 格式的。 |
| 197 | +每个应用配置 `expression` 必须求值为(使用 `Object()` 初始化声明的)CEL 对象。 |
| 198 | + |
| 199 | +这些应用配置不能修改原子结构、映射或数组,因为这类修改可能导致意外删除未包含在应用配置中的值。 |
| 200 | + |
| 201 | +<!-- |
| 202 | +CEL expressions have access to the object types needed to create apply configurations: |
| 203 | +
|
| 204 | +- `Object` - CEL type of the resource object. |
| 205 | +- `Object.<fieldName>` - CEL type of object field (such as `Object.spec`) |
| 206 | +- `Object.<fieldName1>.<fieldName2>...<fieldNameN>` - CEL type of nested field (such as `Object.spec.containers`) |
| 207 | +--> |
| 208 | +CEL 表达式可以访问以 CEL 变量组织起来的 API 请求内容及一些其他有用变量: |
| 209 | + |
| 210 | +- `Object` - 资源对象的 CEL 类型。 |
| 211 | +- `Object.<fieldName>` - 对象字段的 CEL 类型(例如 `Object.spec`) |
| 212 | +- `Object.<fieldName1>.<fieldName2>...<fieldNameN>` - 嵌套字段的 CEL 类型(例如 `Object.spec.containers`) |
| 213 | + |
| 214 | +<!-- |
| 215 | +CEL expressions have access to the contents of the API request, organized into CEL variables as well as some other useful variables: |
| 216 | +
|
| 217 | +- `object` - The object from the incoming request. The value is null for DELETE requests. |
| 218 | +- `oldObject` - The existing object. The value is null for CREATE requests. |
| 219 | +- `request` - Attributes of the API request. |
| 220 | +- `params` - Parameter resource referred to by the policy binding being evaluated. Only populated if the policy has a ParamKind. |
| 221 | +--> |
| 222 | +CEL 表达式可以访问以 CEL 变量组织起来的 API 请求内容及一些其他有用变量: |
| 223 | + |
| 224 | +- `object` - 来自传入请求的对象。对于 DELETE 请求,取值为 null。 |
| 225 | +- `oldObject` - 现有对象。对于 CREATE 请求,取值为 null。 |
| 226 | +- `request` - API 请求的属性。 |
| 227 | +- `params` - 正被评估的策略绑定所引用到的参数资源。仅在策略设置了 `paramKind` 时填充。 |
| 228 | +<!-- |
| 229 | +- `namespaceObject` - The namespace object that the incoming object belongs to. The value is null for cluster-scoped resources. |
| 230 | +- `variables` - Map of composited variables, from its name to its lazily evaluated value. |
| 231 | + For example, a variable named `foo` can be accessed as `variables.foo`. |
| 232 | +- `authorizer` - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. |
| 233 | + See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz |
| 234 | +- `authorizer.requestResource` - A CEL ResourceCheck constructed from the `authorizer` and configured with the |
| 235 | + request resource. |
| 236 | +--> |
| 237 | +- `namespaceObject` - 传入对象所属的命名空间对象。对于集群范围的资源,取值为 null。 |
| 238 | +- `variables` - 组合变量的映射,包含从变量名称到其惰性评估值的映射。 |
| 239 | + 例如,名为 `foo` 的变量可以以 `variables.foo` 的方式访问。 |
| 240 | +- `authorizer` - 一个 CEL 鉴权器。可用于对请求的主体(用户或服务账户)进行鉴权检查。 |
| 241 | + 参阅 https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz |
| 242 | +- `authorizer.requestResource` - 从 `authorizer` 构建并使用请求资源配置的 CEL ResourceCheck。 |
| 243 | + |
| 244 | +<!-- |
| 245 | +The `apiVersion`, `kind`, `metadata.name`, `metadata.generateName` and `metadata.labels` are always accessible from the root of the |
| 246 | +object. No other metadata properties are accessible. |
| 247 | +--> |
| 248 | +`apiVersion`、`kind`、`metadata.name`、`metadata.generateName` 和 `metadata.labels` |
| 249 | +始终可以从对象的根进行访问。其他元数据属性不可访问。 |
| 250 | + |
| 251 | +#### `JSONPatch` {#patch-type-json-patch} |
| 252 | + |
| 253 | +<!-- |
| 254 | +The same mutation can be written as a [JSON Patch](https://jsonpatch.com/) as follows: |
| 255 | +--> |
| 256 | +相同的变更可以被写成以下的 [JSON 补丁](https://jsonpatch.com/): |
| 257 | + |
| 258 | +{{% code_sample language="yaml" file="mutatingadmissionpolicy/json-patch-example.yaml" %}} |
| 259 | + |
| 260 | +<!-- |
| 261 | +The expression will be evaluated by CEL to create a [JSON patch](https://jsonpatch.com/). |
| 262 | +ref: https://github.com/google/cel-spec |
| 263 | +
|
| 264 | +Each evaluated `expression` must return an array of `JSONPatch` values. The |
| 265 | +`JSONPatch` type represents one operation from a JSON patch. |
| 266 | +
|
| 267 | +For example, this CEL expression returns a JSON patch to conditionally modify a value: |
| 268 | +--> |
| 269 | +表达式将通过 CEL 求值,以创建 [JSON 补丁](https://jsonpatch.com/)。 |
| 270 | +参阅 https://github.com/google/cel-spec |
| 271 | + |
| 272 | +每个被求值的 `expression` 必须返回 `JSONPatch` 值形成的数组。 |
| 273 | +`JSONPatch` 类型表示 JSON 补丁中的一个操作。 |
| 274 | + |
| 275 | +例如,下面的 CEL 表达式返回 JSON 补丁,用于有条件地修改某个值: |
| 276 | + |
| 277 | +``` |
| 278 | + [ |
| 279 | + JSONPatch{op: "test", path: "/spec/example", value: "Red"}, |
| 280 | + JSONPatch{op: "replace", path: "/spec/example", value: "Green"} |
| 281 | + ] |
| 282 | +``` |
| 283 | + |
| 284 | +<!-- |
| 285 | +To define a JSON object for the patch operation `value`, use CEL `Object` types. For example: |
| 286 | +--> |
| 287 | +要为补丁操作 `value` 定义 JSON 对象,可以使用 CEL `Object` 类型。例如: |
| 288 | + |
| 289 | +``` |
| 290 | + [ |
| 291 | + JSONPatch{ |
| 292 | + op: "add", |
| 293 | + path: "/spec/selector", |
| 294 | + value: Object.spec.selector{matchLabels: {"environment": "test"}} |
| 295 | + } |
| 296 | + ] |
| 297 | +``` |
| 298 | + |
| 299 | +<!-- |
| 300 | +To use strings containing '/' and '~' as JSONPatch path keys, use `jsonpatch.escapeKey()`. For example: |
| 301 | +--> |
| 302 | +要使用包含 '/' 和 '~' 的字符串作为 JSONPatch 路径键,可以使用 `jsonpatch.escapeKey()`。例如: |
| 303 | + |
| 304 | +``` |
| 305 | + [ |
| 306 | + JSONPatch{ |
| 307 | + op: "add", |
| 308 | + path: "/metadata/labels/" + jsonpatch.escapeKey("example.com/environment"), |
| 309 | + value: "test" |
| 310 | + }, |
| 311 | + ] |
| 312 | +``` |
| 313 | + |
| 314 | +<!-- |
| 315 | +CEL expressions have access to the types needed to create JSON patches and objects: |
| 316 | +
|
| 317 | +- `JSONPatch` - CEL type of JSON Patch operations. JSONPatch has the fields `op`, `from`, `path` and `value`. |
| 318 | + See [JSON patch](https://jsonpatch.com/) for more details. The `value` field may be set to any of: string, |
| 319 | + integer, array, map or object. If set, the `path` and `from` fields must be set to a |
| 320 | + [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901/) string, where the `jsonpatch.escapeKey()` CEL |
| 321 | + function may be used to escape path keys containing `/` and `~`. |
| 322 | +--> |
| 323 | +CEL 表达式可以访问创建 JSON 补丁和对象所需的类型: |
| 324 | + |
| 325 | +- `JSONPatch` - JSON 补丁操作的 CEL 类型。JSONPatch 具有 `op`、`from`、`path` 和 `value` 字段。 |
| 326 | + 有关细节参阅 [JSON 补丁](https://jsonpatch.com/)。 |
| 327 | + `value` 字段可以设置为字符串、整数、数组、映射或对象。 |
| 328 | + 如果设置,`path` 和 `from` 字段的值必须为 |
| 329 | + [JSON 指针](https://datatracker.ietf.org/doc/html/rfc6901/)字符串, |
| 330 | + 可以在指针中使用 `jsonpatch.escapeKey()` CEL 函数来转义包含 `/` 和 `~` 的路径键。 |
| 331 | +<!-- |
| 332 | +- `Object` - CEL type of the resource object. |
| 333 | +- `Object.<fieldName>` - CEL type of object field (such as `Object.spec`) |
| 334 | +- `Object.<fieldName1>.<fieldName2>...<fieldNameN>` - CEL type of nested field (such as `Object.spec.containers`) |
| 335 | +--> |
| 336 | +- `Object` - 资源对象的 CEL 类型。 |
| 337 | +- `Object.<fieldName>` - 对象字段的 CEL 类型(例如 `Object.spec`) |
| 338 | +- `Object.<fieldName1>.<fieldName2>...<fieldNameN>` - 嵌套字段的 CEL 类型(例如 `Object.spec.containers`) |
| 339 | + |
| 340 | +<!-- |
| 341 | +CEL expressions have access to the contents of the API request, organized into CEL variables as well as some other useful variables: |
| 342 | +
|
| 343 | +- `object` - The object from the incoming request. The value is null for DELETE requests. |
| 344 | +- `oldObject` - The existing object. The value is null for CREATE requests. |
| 345 | +- `request` - Attributes of the API request. |
| 346 | +- `params` - Parameter resource referred to by the policy binding being evaluated. Only populated if the policy has a ParamKind. |
| 347 | +--> |
| 348 | +CEL 表达式可以访问以 CEL 变量组织的 API 请求的内容及一些其他有用变量: |
| 349 | + |
| 350 | +- `object` - 来自传入请求的对象。对于 DELETE 请求,取值为 null。 |
| 351 | +- `oldObject` - 现有对象。对于 CREATE 请求,取值为 null。 |
| 352 | +- `request` - API 请求的属性。 |
| 353 | +- `params` - 正被评估的策略绑定所引用的参数资源。仅在策略具有 `paramKind` 时填充。 |
| 354 | +<!-- |
| 355 | +- `namespaceObject` - The namespace object that the incoming object belongs to. The value is null for cluster-scoped resources. |
| 356 | +- `variables` - Map of composited variables, from its name to its lazily evaluated value. |
| 357 | + For example, a variable named `foo` can be accessed as `variables.foo`. |
| 358 | +- `authorizer` - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request. |
| 359 | + See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz |
| 360 | +- `authorizer.requestResource` - A CEL ResourceCheck constructed from the `authorizer` and configured with the |
| 361 | + request resource. |
| 362 | +--> |
| 363 | +- `namespaceObject` - 传入对象所属的命名空间对象。对于集群范围的资源,取值为 null。 |
| 364 | +- `variables` - 组合变量的映射,包含从变量名称到其惰性评估值的映射。 |
| 365 | + 例如,名为 `foo` 的变量可以以 `variables.foo` 的形式访问。 |
| 366 | +- `authorizer` - 一个 CEL 鉴权组件。可用于对请求的主体(用户或服务账户)执行鉴权检查。 |
| 367 | + 参阅 https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz |
| 368 | +- `authorizer.requestResource` - 从 `authorizer` 构建并以请求资源配置的 CEL ResourceCheck。 |
| 369 | + |
| 370 | +<!-- |
| 371 | +CEL expressions have access to [Kubernetes CEL function libraries](/docs/reference/using-api/cel/#cel-options-language-features-and-libraries) |
| 372 | +as well as: |
| 373 | +
|
| 374 | +- `jsonpatch.escapeKey` - Performs JSONPatch key escaping. `~` and `/` are escaped as `~0` and `~1` respectively. |
| 375 | +
|
| 376 | +Only property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible. |
| 377 | +--> |
| 378 | +CEL 表达式可以访问 |
| 379 | +[Kubernetes CEL 函数库](/zh-cn/docs/reference/using-api/cel/#cel-options-language-features-and-libraries)以及: |
| 380 | + |
| 381 | +- `jsonpatch.escapeKey` - 执行 JSONPatch 键转义。`~` 和 `/` 分别被转义为 `~0` 和 `~1`。 |
| 382 | + |
| 383 | +只有格式为 `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` 的属性名称是可访问的。 |
0 commit comments