AIP-236 策略预览
| 编号 | 236 | 
|---|---|
| 原文链接 | AIP-236: Policy preview | 
| 状态 | 批准 | 
| 创建日期 | 2023-03-30 | 
| 更新日期 | 2023-04-27 | 
策略是一种资源,它提供规则,许可或拒绝对其他资源的访问。通常,策略的结果可以计算为特定的结果集合。
未经充分验证就变更策略,可能会产生意外后果,严重影响客户的整体基础设施配置。为了安全的更新资源,利用策略推出API测试这些变更,是有好处的。
预览是策略资源的安全推出机制,让客户能够在变更生效之前,验证所提交的变更对生产流量的影响。针对流量的策略评估结果会记录下来,为客户提供数据,测试变更是否正确。
防火墙策略是适合预览的典型场景。使用流量评估新配置,观察哪些IP会被放行或拦截。这为客户提供了数据,作为将变更推广到生产环境的决策依据。
预览策略的流程如下:
- 用户创建一个实验,包含用于替换当前策略的新配置。
- 用户使用“startPreview”方法开始生成日志,使用生产流量对当前策略和实验策略进行评估,比对评估结果。
- 用户检查日志,确认实验是否达到了预期结果。
- 用户使用“commit”方法将实验推广到生产环境。
指南
适用范围
本提案是用于推出策略的安全机制。不涉及非策略资源的安全推出。
实验
待预览策略的新配置作为内嵌集合存储在策略中。这些内嵌集合称为实验。
假设一个名为 Policy 的策略资源。它具有下列资源名字模式:
projects/{project}/locations/{location}/policies/{policy}
资源的实验版本,用于预览或其他安全推出措施的,表示为 Policy 中的内嵌集合,使用一种新的资源类型。资源类型 必须 遵循名字约定 规范资源类型Experiment 。
实验集合使用以下模式:
projects/{project}/locations/{location}/policies/{policy}/experiments/{experiment}
表示实验的proto 必须 包含以下内容:
- 资源的顶级必须域,如 name和etag。
- 待测试的策略消息自身。
- 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消息中的名字 必须 是当前策略的名字。
 
- 必须 按照当前策略资源类型命名。例如针对FirewallPolicy的试验,域 必须 命名为 
- 如果用户准备推广实验, 必须 将 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域 必须 是只输出域。
- 当预览开始或停止后,state 在 ACTIVE和SUSPENDED之间切换。相应的发生在调用“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的目标是替换当前策略,而当前策略的名字 不得 更改。
- 如果在更新开始时 state是ACTIVE,系统 必须 将其设置为SUSPENDED。- 这是为了让用户可以轻松区分正在预览的实验的不同版本。
 
get
- PolicyExperiment资源类型 必须 支持 标准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为当前时间。
- 设置 state为ACTIVE。
 
- 设置 
- 如果在规则是无操作的实验上调用,系统 必须 预览删除当前策略的效果。
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为当前时间。
- 设置 state为SUSPENDED。
 
- 设置 
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 初稿。
