tommwq.work/aip

AIP-236 策略预览

· [tommwq@126.com]
编号 236
原文链接 https://google.aip.dev/236
状态 批准
创建日期 2023-03-30
更新日期 2023-04-27

策略是一种资源,它提供规则,许可或拒绝对其他资源的访问。通常,策略的结果可以计算为特定的结果集合。

未经充分验证就变更策略,可能会产生意外后果,严重影响客户的整体基础设施配置。为了安全的更新资源,利用策略推出API测试这些变更,是有好处的。

预览是策略资源的安全推出机制,让客户能够在变更生效之前,验证所提交的变更对生产流量的影响。针对流量的策略评估结果会记录下来,为客户提供数据,测试变更是否正确。

防火墙策略是适合预览的典型场景。使用流量评估新配置,观察哪些IP会被放行或拦截。这为客户提供了数据,作为将变更推广到生产环境的决策依据。

预览策略的流程如下:

  1. 用户创建一个实验,包含用于替换当前策略的新配置。
  2. 用户使用“startPreview”方法开始生成日志,使用生产流量对当前策略和实验策略进行评估,比对评估结果。
  3. 用户检查日志,确认实验是否达到了预期结果。
  4. 用户使用“commit”方法将实验推广到生产环境。

指南

适用范围

本提案是用于推出策略的安全机制。不涉及非策略资源的安全推出。

实验

待预览策略的新配置作为内嵌集合存储在策略中。这些内嵌集合称为实验。

假设一个名为 Policy 的策略资源。它具有下列资源名字模式:

projects/{project}/locations/{location}/policies/{policy}

资源的实验版本,用于预览或其他安全推出措施的,表示为 Policy 中的内嵌集合,使用一种新的资源类型。资源类型 必须 遵循名字约定 规范资源类型Experiment

实验集合使用以下模式:

projects/{project}/locations/{location}/policies/{policy}/experiments/{experiment}

表示实验的proto 必须 包含以下内容:

  1. 资源的顶级必须域,如 nameetag
  2. 待测试的策略消息自身。
  3. preview_metadata 域,包含预览特定类型资源实验的专属元数据。
message PolicyExperiment {

  // google.api.resource, name, and other annotations and fields

  // The policy experiment. This Policy will be used to preview the effects of
  // the change but will not affect live traffic.
  Policy policy = 2;

  // The metadata associated with this policy experiment.
  PolicyPreviewMetadata preview_metadata = 3
      [(google.api.field_behavior) = OUTPUT_ONLY];

  // Allows clients to store small amounts of arbitrary data.
  map<string, string> annotations = 4;
}
  • 实验proto 必须 具有与当前策略相同类型的顶级域。
    • 必须 按照当前策略资源类型命名。例如针对FirewallPolicy的试验,域 必须 命名为 firewall_policy
    • 内嵌的 policy 消息中的名字 必须 是当前策略的名字。
  • 如果用户准备推广实验, 必须policy 消息复制到当前策略中,再删除实验。可以手动执行,也可以使用“commit”自定义方法。
  • 产品 可以 支持同时对单一当前策略进行多个预览实验。
    • 每个实验都要生成日志,每条日志前面是 log_prefix ,方便用户可以将实验的结果与当前策略行为进行比较。
    • 可以 限制特定当前策略的实验配置不超过一定数量, 必须 在文档中记录上限。
  • 必须 采用级联删除:删除当前策略时,所有实验也 必须 删除。
  • map<string,string> 注解 必须 允许客户端存储少量数据。

元数据

preview_metadata 跟踪预览实验的所有元数据。消息 必须 遵守约定:规范资源类型PreviewMetadata 。这是为了proto可以在同一服务中为每个资源类型定义唯一的实验。

message PolicyPreviewMetadata {
  // Possible values of the state of previewing the experiment.
  enum State {
    // Default value. This value is unused.
    STATE_UNDEFINED = 0;

    // The experiment is actively previewing.
    ACTIVE = 1;

    // The previewing of the experiment has been stopped.
    SUSPENDED = 2;
  }

  // The state of previewing the experiment.
  State state = 1;

  // An identifying string common to all logs generated when previewing the
  // experiment. Searching all logs for this string will isolate the results.
  string log_prefix = 2;

  // The most recent time at which this experiment started previewing.
  google.protobuf.Timestamp start_time = 3;

  // The most recent time at which this experiment stopped previewing.
  google.protobuf.Timestamp stop_time = 4;
}
  • PolicyPreviewMetadata 必须 包含上述proto中定义的域。
    • 如果服务或资源需要 可以 包含其他域。
  • 在实验首次预览时, preview_metadata 必须 不存在。
    • 一旦使用“startPreview”方法,元数据就会出现在实验中。
  • 所有 preview_metadata必须 是只输出域。
  • 当预览开始或停止后,stateACTIVESUSPENDED 之间切换。相应的发生在调用“startPreview”或“stopPreview”自定义方法时。
  • 首次次使用“startPreview”自定义方法时,系统 必须 创建 preview_metadata ,执行下列操作:
    • 必须state 设置为 ACTIVE
    • 必须 使用当前时间设置 start_time
      • 每次 state 切换到 ACTIVE 时,*必须* 更新 start_time
    • 必须 设置系统生成的 log_prefix 字符串,这是系统开发者硬编码的预定义常量。
      • 对于同一种资源类型,预览实验使用对应的、相同的日志前缀。例如FirewallPolicy的日志前缀是“FirewallPolicyPreviewLog” 。
  • 使用“stopPreview”自定义方法时,系统 必须 执行以下操作:
    • 必须state 设置为 SUSPENDED
    • 必须 用当前时间设置 stop_time

方法

create

  • 必须 使用耗时方法创建资源, google.longrunning.operation_info.response_type 必须PolicyExperiment
  • 创建待预览的新实验时 必须 支持以下用例:
    • 预览新策略。
    • 预览对当前策略的更新。
    • 预览删除当前策略的效果。
  • 对于更新和删除用例,实验中的 policy必须 复制当前策略的完整内容,包括名字。
    • 用户 必须 将规则设置为新的预期状态,以预览更新。
    • 用户 必须 将规则设置为无操作,以预览删除。
  • 预览新策略时,系统必须执行以下操作:
    • 如果系统不允许内嵌集合缺少对应的当前策略,用户 必须 创建一个策略,将规则设置为无操作。例如,无操作策略的规则 可以 是空集合。
      • 实验作为无操作策略的下级条目创建。
  • 如果系统支持预览当前策略的多个实验,多次调用“create” 必须 创建多个实验。

update

  • 资源 必须 使用耗时更新google.longrunning.operation_info.response_type 必须PolicyExperiment
  • 不得 更改 policy 中的名字域,其他域可以更改,以便调整正在预览的实验。因为这个 policy 的目标是替换当前策略,而当前策略的名字 不得 更改。
  • 如果在更新开始时 stateACTIVE ,系统 必须 将其设置为 SUSPENDED
    • 这是为了让用户可以轻松区分正在预览的实验的不同版本。

get

list

  • PolicyExperiment 资源类型 必须 支持 标准List方法
  • PolicyPreviewMetadata 进行过滤可以发现哪些实验正在预览。
    • 例如以下过滤字符串返回正在预览的实验列表: preview_metadata.state = ACTIVE

delete

  • 资源 必须 使用耗时删除google.longrunning.operation_info.response_type 必须PolicyExperiment

startPreview

// Starts previewing a PolicyExperiment. This triggers the system to start
// generating logs to evaluate the PolicyExperiment.
rpc StartPreviewPolicyExperiment(StartPreviewPolicyExperimentRequest)
    returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{name=policies/*/experiments/*}:startPreview"
    body: "*"
  };
  option (google.longrunning.operation_info) = {
    response_type: "PolicyExperiment"
    metadata_type: "StartPreviewPolicyExperimentMetadata"
  };
}

// The request message for the startPreview custom method.
message StartPreviewPolicyExperimentRequest {
  // The name of the PolicyExperiment.
  string name = 1;
}
  • 这个自定义方法是必需的。
  • google.longrunning.Operation.metadata_type 必须 遵守耗时操作指南。
  • 方法 必须 让系统开始生成日志,以预览实验。
  • 成功调用后,系统 必须PolicyPreviewMetadata 中设置下列值:
    • 设置 log_prefix 为预定义常量。
    • 设置 start_time 为当前时间。
    • 设置 stateACTIVE
  • 如果在规则是无操作的实验上调用,系统 必须 预览删除当前策略的效果。

stopPreview

// Stops previewing a PolicyExperiment. This triggers the system to stop
// generating logs to evaluate the PolicyExperiment.
rpc StopPreviewPolicyExperiment(StopPreviewPolicyExperimentRequest)
    returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{name=policies/*/experiments/*}:stopPreview"
    body: "*"
  };
  option (google.longrunning.operation_info) = {
    response_type: "PolicyExperiment"
    metadata_type: "StopPreviewPolicyExperimentMetadata"
  };
}

// The request message for the stopPreview custom method.
message StopPreviewPolicyExperimentRequest {
  // The name of the PolicyExperiment.
  string name = 1;
}
  • 这个自定义方法是必需的。
  • google.longrunning.Operation.metadata_type 必须 遵守耗时操作指南。
  • 方法 必须 让系统停止生成预览实验日志。
  • 成功调用后,系统 必须PolicyPreviewMetadata 中设置下列值:
    • 设置 stop_time 为当前时间。
    • 设置 stateSUSPENDED

commit

资源 可以 发布自定义方法“commit”,用来推广实验。系统将 policy 从实验复制到当前策略,再删除实验。

声明式客户端 可以 手动将域从实验复制到当前策略,然后删除实验,而不是调用“commit”方法,如果更合适。

// Commits a PolicyExperiment. This copies the PolicyExperiment's policy message
// to the live policy then deletes the PolicyExperiment.
rpc CommitPolicyExperiment(CommitPolicyExperimentRequest)
    returns (google.longrunning.Operation) {
  option (google.api.http) = {
    post: "/v1/{name=policies/*/experiments/*}:commit"
    body: "*"
  };
  option (google.longrunning.operation_info) = {
    response_type: "google.protobuf.Empty"
    metadata_type: "CommitPolicyExperimentMetadata"
  };
}

// The request message for the commit custom method.
message CommitPolicyExperimentRequest {
  string name = 1;
  string etag = 2;
  string parent_etag = 3;
}
  • google.longrunning.Operation.metadata_type 必须 遵守耗时操作指南。
  • 方法 必须 原子的将 policy 从实验复制到当前策略,然后删除实验。
  • 如果一个实验“commit”失败,对它的预览 不得 停止,当前策略 不得 变更。
  • 方法可以在任何状态的实验上调用。
  • 为了保证“commit”成功, etag 必须 与实验的 etag 一致。这是为了防止用户提交错误的实验版本。
    • 如果未提供 etag ,API 不得 成功,防止用户误提交非预期的实验版本。
    • 可以提供 parent_etag ,保证实验覆盖当前策略的特定版本。
  • 方法不是幂等的,在同一个实验上第二次调用时 必须 返回 404 NOT_FOUND ,因为在第一次调用时实验已经删除。

对当前策略API方法的变更

delete

  • 删除当前策略 必须 删除所有实验。
  • 为了在消除当前策略效果的同时进行实验,当前策略 必须 更改为无操作策略,而不是进行删除。

日志

在评估能否将实验推广到生产环境时,日志对于用户至关重要。

日志 必须 包含实验评估结果、与该实验和当前策略关联的 etag ,并前导 log_prefix 前缀。

  • etag 域帮助用户识别日志中评估结果关联的当前配置和实验配置。
  • log_prefix 帮助用户将预览实验生成的日志与其他日志区分开。

总的来说,日志帮助用户决定是否将实验推广到生产环境。

修订记录

  • 2023-04-27 修改开始和停止方法名字。将状态改为枚举。添加注解。
  • 2023-03-30 初稿。