AIP-236 策略预览
编号 | 236 |
---|---|
原文链接 | https://google.aip.dev/236 |
状态 | 批准 |
创建日期 | 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 初稿。