diff --git a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts index 1a00b8e49..72c74f85e 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -21,6 +21,8 @@ export interface CraftingSchema { annotations: Annotation[]; /** Policies to apply to this schema */ policies?: Policies; + /** Policy groups to apply to this schema */ + policyGroups: PolicyGroupAttachment[]; } export interface CraftingSchema_Runner { @@ -357,6 +359,29 @@ export interface PolicySpecV2 { kind: CraftingSchema_Material_MaterialType; } +/** Represents a group attachment in a contract */ +export interface PolicyGroupAttachment { + /** Group reference, it might be an URL or a provider reference */ + ref: string; +} + +/** Represents a group or policies */ +export interface PolicyGroup { + apiVersion: string; + kind: string; + metadata?: Metadata; + spec?: PolicyGroup_PolicyGroupSpec; +} + +export interface PolicyGroup_PolicyGroupSpec { + policies?: PolicyGroup_PolicyGroupPolicies; +} + +export interface PolicyGroup_PolicyGroupPolicies { + materials: PolicyAttachment[]; + attestation: PolicyAttachment[]; +} + function createBaseCraftingSchema(): CraftingSchema { return { schemaVersion: "", @@ -365,6 +390,7 @@ function createBaseCraftingSchema(): CraftingSchema { runner: undefined, annotations: [], policies: undefined, + policyGroups: [], }; } @@ -388,6 +414,9 @@ export const CraftingSchema = { if (message.policies !== undefined) { Policies.encode(message.policies, writer.uint32(50).fork()).ldelim(); } + for (const v of message.policyGroups) { + PolicyGroupAttachment.encode(v!, writer.uint32(58).fork()).ldelim(); + } return writer; }, @@ -440,6 +469,13 @@ export const CraftingSchema = { message.policies = Policies.decode(reader, reader.uint32()); continue; + case 7: + if (tag !== 58) { + break; + } + + message.policyGroups.push(PolicyGroupAttachment.decode(reader, reader.uint32())); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -459,6 +495,9 @@ export const CraftingSchema = { runner: isSet(object.runner) ? CraftingSchema_Runner.fromJSON(object.runner) : undefined, annotations: Array.isArray(object?.annotations) ? object.annotations.map((e: any) => Annotation.fromJSON(e)) : [], policies: isSet(object.policies) ? Policies.fromJSON(object.policies) : undefined, + policyGroups: Array.isArray(object?.policyGroups) + ? object.policyGroups.map((e: any) => PolicyGroupAttachment.fromJSON(e)) + : [], }; }, @@ -483,6 +522,11 @@ export const CraftingSchema = { obj.annotations = []; } message.policies !== undefined && (obj.policies = message.policies ? Policies.toJSON(message.policies) : undefined); + if (message.policyGroups) { + obj.policyGroups = message.policyGroups.map((e) => e ? PolicyGroupAttachment.toJSON(e) : undefined); + } else { + obj.policyGroups = []; + } return obj; }, @@ -502,6 +546,7 @@ export const CraftingSchema = { message.policies = (object.policies !== undefined && object.policies !== null) ? Policies.fromPartial(object.policies) : undefined; + message.policyGroups = object.policyGroups?.map((e) => PolicyGroupAttachment.fromPartial(e)) || []; return message; }, }; @@ -1548,6 +1593,306 @@ export const PolicySpecV2 = { }, }; +function createBasePolicyGroupAttachment(): PolicyGroupAttachment { + return { ref: "" }; +} + +export const PolicyGroupAttachment = { + encode(message: PolicyGroupAttachment, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.ref !== "") { + writer.uint32(10).string(message.ref); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PolicyGroupAttachment { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicyGroupAttachment(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.ref = reader.string(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): PolicyGroupAttachment { + return { ref: isSet(object.ref) ? String(object.ref) : "" }; + }, + + toJSON(message: PolicyGroupAttachment): unknown { + const obj: any = {}; + message.ref !== undefined && (obj.ref = message.ref); + return obj; + }, + + create, I>>(base?: I): PolicyGroupAttachment { + return PolicyGroupAttachment.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): PolicyGroupAttachment { + const message = createBasePolicyGroupAttachment(); + message.ref = object.ref ?? ""; + return message; + }, +}; + +function createBasePolicyGroup(): PolicyGroup { + return { apiVersion: "", kind: "", metadata: undefined, spec: undefined }; +} + +export const PolicyGroup = { + encode(message: PolicyGroup, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.apiVersion !== "") { + writer.uint32(10).string(message.apiVersion); + } + if (message.kind !== "") { + writer.uint32(18).string(message.kind); + } + if (message.metadata !== undefined) { + Metadata.encode(message.metadata, writer.uint32(26).fork()).ldelim(); + } + if (message.spec !== undefined) { + PolicyGroup_PolicyGroupSpec.encode(message.spec, writer.uint32(34).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PolicyGroup { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicyGroup(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.apiVersion = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.kind = reader.string(); + continue; + case 3: + if (tag !== 26) { + break; + } + + message.metadata = Metadata.decode(reader, reader.uint32()); + continue; + case 4: + if (tag !== 34) { + break; + } + + message.spec = PolicyGroup_PolicyGroupSpec.decode(reader, reader.uint32()); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): PolicyGroup { + return { + apiVersion: isSet(object.apiVersion) ? String(object.apiVersion) : "", + kind: isSet(object.kind) ? String(object.kind) : "", + metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined, + spec: isSet(object.spec) ? PolicyGroup_PolicyGroupSpec.fromJSON(object.spec) : undefined, + }; + }, + + toJSON(message: PolicyGroup): unknown { + const obj: any = {}; + message.apiVersion !== undefined && (obj.apiVersion = message.apiVersion); + message.kind !== undefined && (obj.kind = message.kind); + message.metadata !== undefined && (obj.metadata = message.metadata ? Metadata.toJSON(message.metadata) : undefined); + message.spec !== undefined && + (obj.spec = message.spec ? PolicyGroup_PolicyGroupSpec.toJSON(message.spec) : undefined); + return obj; + }, + + create, I>>(base?: I): PolicyGroup { + return PolicyGroup.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): PolicyGroup { + const message = createBasePolicyGroup(); + message.apiVersion = object.apiVersion ?? ""; + message.kind = object.kind ?? ""; + message.metadata = (object.metadata !== undefined && object.metadata !== null) + ? Metadata.fromPartial(object.metadata) + : undefined; + message.spec = (object.spec !== undefined && object.spec !== null) + ? PolicyGroup_PolicyGroupSpec.fromPartial(object.spec) + : undefined; + return message; + }, +}; + +function createBasePolicyGroup_PolicyGroupSpec(): PolicyGroup_PolicyGroupSpec { + return { policies: undefined }; +} + +export const PolicyGroup_PolicyGroupSpec = { + encode(message: PolicyGroup_PolicyGroupSpec, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.policies !== undefined) { + PolicyGroup_PolicyGroupPolicies.encode(message.policies, writer.uint32(10).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PolicyGroup_PolicyGroupSpec { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicyGroup_PolicyGroupSpec(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.policies = PolicyGroup_PolicyGroupPolicies.decode(reader, reader.uint32()); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): PolicyGroup_PolicyGroupSpec { + return { policies: isSet(object.policies) ? PolicyGroup_PolicyGroupPolicies.fromJSON(object.policies) : undefined }; + }, + + toJSON(message: PolicyGroup_PolicyGroupSpec): unknown { + const obj: any = {}; + message.policies !== undefined && + (obj.policies = message.policies ? PolicyGroup_PolicyGroupPolicies.toJSON(message.policies) : undefined); + return obj; + }, + + create, I>>(base?: I): PolicyGroup_PolicyGroupSpec { + return PolicyGroup_PolicyGroupSpec.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): PolicyGroup_PolicyGroupSpec { + const message = createBasePolicyGroup_PolicyGroupSpec(); + message.policies = (object.policies !== undefined && object.policies !== null) + ? PolicyGroup_PolicyGroupPolicies.fromPartial(object.policies) + : undefined; + return message; + }, +}; + +function createBasePolicyGroup_PolicyGroupPolicies(): PolicyGroup_PolicyGroupPolicies { + return { materials: [], attestation: [] }; +} + +export const PolicyGroup_PolicyGroupPolicies = { + encode(message: PolicyGroup_PolicyGroupPolicies, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + for (const v of message.materials) { + PolicyAttachment.encode(v!, writer.uint32(10).fork()).ldelim(); + } + for (const v of message.attestation) { + PolicyAttachment.encode(v!, writer.uint32(18).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PolicyGroup_PolicyGroupPolicies { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicyGroup_PolicyGroupPolicies(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.materials.push(PolicyAttachment.decode(reader, reader.uint32())); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.attestation.push(PolicyAttachment.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): PolicyGroup_PolicyGroupPolicies { + return { + materials: Array.isArray(object?.materials) ? object.materials.map((e: any) => PolicyAttachment.fromJSON(e)) : [], + attestation: Array.isArray(object?.attestation) + ? object.attestation.map((e: any) => PolicyAttachment.fromJSON(e)) + : [], + }; + }, + + toJSON(message: PolicyGroup_PolicyGroupPolicies): unknown { + const obj: any = {}; + if (message.materials) { + obj.materials = message.materials.map((e) => e ? PolicyAttachment.toJSON(e) : undefined); + } else { + obj.materials = []; + } + if (message.attestation) { + obj.attestation = message.attestation.map((e) => e ? PolicyAttachment.toJSON(e) : undefined); + } else { + obj.attestation = []; + } + return obj; + }, + + create, I>>(base?: I): PolicyGroup_PolicyGroupPolicies { + return PolicyGroup_PolicyGroupPolicies.fromPartial(base ?? {}); + }, + + fromPartial, I>>( + object: I, + ): PolicyGroup_PolicyGroupPolicies { + const message = createBasePolicyGroup_PolicyGroupPolicies(); + message.materials = object.materials?.map((e) => PolicyAttachment.fromPartial(e)) || []; + message.attestation = object.attestation?.map((e) => PolicyAttachment.fromPartial(e)) || []; + return message; + }, +}; + type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; export type DeepPartial = T extends Builtin ? T diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.jsonschema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.jsonschema.json index b9d7b3076..c5cbac416 100644 --- a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.jsonschema.json +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.jsonschema.json @@ -10,6 +10,13 @@ }, "type": "array" }, + "^(policy_groups)$": { + "description": "Policy groups to apply to this schema", + "items": { + "$ref": "workflowcontract.v1.PolicyGroupAttachment.jsonschema.json" + }, + "type": "array" + }, "^(schema_version)$": { "description": "Version of the schema, do not confuse with the revision of the content", "type": "string" @@ -39,6 +46,13 @@ "$ref": "workflowcontract.v1.Policies.jsonschema.json", "description": "Policies to apply to this schema" }, + "policyGroups": { + "description": "Policy groups to apply to this schema", + "items": { + "$ref": "workflowcontract.v1.PolicyGroupAttachment.jsonschema.json" + }, + "type": "array" + }, "runner": { "$ref": "workflowcontract.v1.CraftingSchema.Runner.jsonschema.json" }, diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.schema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.schema.json index 7e4f08cef..eb88b6640 100644 --- a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.schema.json +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.CraftingSchema.schema.json @@ -10,6 +10,13 @@ }, "type": "array" }, + "^(policyGroups)$": { + "description": "Policy groups to apply to this schema", + "items": { + "$ref": "workflowcontract.v1.PolicyGroupAttachment.schema.json" + }, + "type": "array" + }, "^(schemaVersion)$": { "description": "Version of the schema, do not confuse with the revision of the content", "type": "string" @@ -39,6 +46,13 @@ "$ref": "workflowcontract.v1.Policies.schema.json", "description": "Policies to apply to this schema" }, + "policy_groups": { + "description": "Policy groups to apply to this schema", + "items": { + "$ref": "workflowcontract.v1.PolicyGroupAttachment.schema.json" + }, + "type": "array" + }, "runner": { "$ref": "workflowcontract.v1.CraftingSchema.Runner.schema.json" }, diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.GroupPolicyReference.jsonschema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.GroupPolicyReference.jsonschema.json new file mode 100644 index 000000000..e423fd964 --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.GroupPolicyReference.jsonschema.json @@ -0,0 +1,22 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.GroupPolicyReference.jsonschema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "ref": { + "type": "string" + }, + "with": { + "additionalProperties": { + "type": "string" + }, + "description": "optional arguments for policy. They will be overriden by any argument with the same name applied to the group attachment", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "title": "Group Policy Reference", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.GroupPolicyReference.schema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.GroupPolicyReference.schema.json new file mode 100644 index 000000000..3da9bb34b --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.GroupPolicyReference.schema.json @@ -0,0 +1,22 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.GroupPolicyReference.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "ref": { + "type": "string" + }, + "with": { + "additionalProperties": { + "type": "string" + }, + "description": "optional arguments for policy. They will be overriden by any argument with the same name applied to the group attachment", + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "title": "Group Policy Reference", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.jsonschema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.jsonschema.json new file mode 100644 index 000000000..b4f70e041 --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.jsonschema.json @@ -0,0 +1,21 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.jsonschema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "attestation": { + "items": { + "$ref": "workflowcontract.v1.PolicyAttachment.jsonschema.json" + }, + "type": "array" + }, + "materials": { + "items": { + "$ref": "workflowcontract.v1.PolicyAttachment.jsonschema.json" + }, + "type": "array" + } + }, + "title": "Policy Group Policies", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.schema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.schema.json new file mode 100644 index 000000000..5ff479d2f --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.schema.json @@ -0,0 +1,21 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "attestation": { + "items": { + "$ref": "workflowcontract.v1.PolicyAttachment.schema.json" + }, + "type": "array" + }, + "materials": { + "items": { + "$ref": "workflowcontract.v1.PolicyAttachment.schema.json" + }, + "type": "array" + } + }, + "title": "Policy Group Policies", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupSpec.jsonschema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupSpec.jsonschema.json new file mode 100644 index 000000000..bf5bade8c --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupSpec.jsonschema.json @@ -0,0 +1,12 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.PolicyGroupSpec.jsonschema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "policies": { + "$ref": "workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.jsonschema.json" + } + }, + "title": "Policy Group Spec", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupSpec.schema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupSpec.schema.json new file mode 100644 index 000000000..4a48bea22 --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.PolicyGroupSpec.schema.json @@ -0,0 +1,12 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.PolicyGroupSpec.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "policies": { + "$ref": "workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.schema.json" + } + }, + "title": "Policy Group Spec", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.jsonschema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.jsonschema.json new file mode 100644 index 000000000..c033a8f02 --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.jsonschema.json @@ -0,0 +1,27 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.jsonschema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "Represents a group or policies", + "patternProperties": { + "^(api_version)$": { + "type": "string" + } + }, + "properties": { + "apiVersion": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "metadata": { + "$ref": "workflowcontract.v1.Metadata.jsonschema.json" + }, + "spec": { + "$ref": "workflowcontract.v1.PolicyGroup.PolicyGroupSpec.jsonschema.json" + } + }, + "title": "Policy Group", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.schema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.schema.json new file mode 100644 index 000000000..361041b7d --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroup.schema.json @@ -0,0 +1,27 @@ +{ + "$id": "workflowcontract.v1.PolicyGroup.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "Represents a group or policies", + "patternProperties": { + "^(apiVersion)$": { + "type": "string" + } + }, + "properties": { + "api_version": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "metadata": { + "$ref": "workflowcontract.v1.Metadata.schema.json" + }, + "spec": { + "$ref": "workflowcontract.v1.PolicyGroup.PolicyGroupSpec.schema.json" + } + }, + "title": "Policy Group", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroupAttachment.jsonschema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroupAttachment.jsonschema.json new file mode 100644 index 000000000..8e8ec8221 --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroupAttachment.jsonschema.json @@ -0,0 +1,14 @@ +{ + "$id": "workflowcontract.v1.PolicyGroupAttachment.jsonschema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "Represents a group attachment in a contract", + "properties": { + "ref": { + "description": "Group reference, it might be an URL or a provider reference", + "type": "string" + } + }, + "title": "Policy Group Attachment", + "type": "object" +} diff --git a/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroupAttachment.schema.json b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroupAttachment.schema.json new file mode 100644 index 000000000..bc6ecc28d --- /dev/null +++ b/app/controlplane/api/gen/jsonschema/workflowcontract.v1.PolicyGroupAttachment.schema.json @@ -0,0 +1,14 @@ +{ + "$id": "workflowcontract.v1.PolicyGroupAttachment.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "description": "Represents a group attachment in a contract", + "properties": { + "ref": { + "description": "Group reference, it might be an URL or a provider reference", + "type": "string" + } + }, + "title": "Policy Group Attachment", + "type": "object" +} diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index 0150d3d42..9581caf04 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -214,6 +214,8 @@ type CraftingSchema struct { Annotations []*Annotation `protobuf:"bytes,5,rep,name=annotations,proto3" json:"annotations,omitempty"` // Policies to apply to this schema Policies *Policies `protobuf:"bytes,6,opt,name=policies,proto3" json:"policies,omitempty"` + // Policy groups to apply to this schema + PolicyGroups []*PolicyGroupAttachment `protobuf:"bytes,7,rep,name=policy_groups,json=policyGroups,proto3" json:"policy_groups,omitempty"` } func (x *CraftingSchema) Reset() { @@ -290,6 +292,13 @@ func (x *CraftingSchema) GetPolicies() *Policies { return nil } +func (x *CraftingSchema) GetPolicyGroups() []*PolicyGroupAttachment { + if x != nil { + return x.PolicyGroups + } + return nil +} + type Annotation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -864,6 +873,127 @@ func (*PolicySpecV2_Path) isPolicySpecV2_Source() {} func (*PolicySpecV2_Embedded) isPolicySpecV2_Source() {} +// Represents a group attachment in a contract +type PolicyGroupAttachment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Group reference, it might be an URL or a provider reference + Ref string `protobuf:"bytes,1,opt,name=ref,proto3" json:"ref,omitempty"` +} + +func (x *PolicyGroupAttachment) Reset() { + *x = PolicyGroupAttachment{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyGroupAttachment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyGroupAttachment) ProtoMessage() {} + +func (x *PolicyGroupAttachment) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PolicyGroupAttachment.ProtoReflect.Descriptor instead. +func (*PolicyGroupAttachment) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{8} +} + +func (x *PolicyGroupAttachment) GetRef() string { + if x != nil { + return x.Ref + } + return "" +} + +// Represents a group or policies +type PolicyGroup struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ApiVersion string `protobuf:"bytes,1,opt,name=api_version,json=apiVersion,proto3" json:"api_version,omitempty"` + Kind string `protobuf:"bytes,2,opt,name=kind,proto3" json:"kind,omitempty"` + Metadata *Metadata `protobuf:"bytes,3,opt,name=metadata,proto3" json:"metadata,omitempty"` + Spec *PolicyGroup_PolicyGroupSpec `protobuf:"bytes,4,opt,name=spec,proto3" json:"spec,omitempty"` +} + +func (x *PolicyGroup) Reset() { + *x = PolicyGroup{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyGroup) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyGroup) ProtoMessage() {} + +func (x *PolicyGroup) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PolicyGroup.ProtoReflect.Descriptor instead. +func (*PolicyGroup) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{9} +} + +func (x *PolicyGroup) GetApiVersion() string { + if x != nil { + return x.ApiVersion + } + return "" +} + +func (x *PolicyGroup) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *PolicyGroup) GetMetadata() *Metadata { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *PolicyGroup) GetSpec() *PolicyGroup_PolicyGroupSpec { + if x != nil { + return x.Spec + } + return nil +} + type CraftingSchema_Runner struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -875,7 +1005,7 @@ type CraftingSchema_Runner struct { func (x *CraftingSchema_Runner) Reset() { *x = CraftingSchema_Runner{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[8] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -888,7 +1018,7 @@ func (x *CraftingSchema_Runner) String() string { func (*CraftingSchema_Runner) ProtoMessage() {} func (x *CraftingSchema_Runner) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[8] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -929,7 +1059,7 @@ type CraftingSchema_Material struct { func (x *CraftingSchema_Material) Reset() { *x = CraftingSchema_Material{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -942,7 +1072,7 @@ func (x *CraftingSchema_Material) String() string { func (*CraftingSchema_Material) ProtoMessage() {} func (x *CraftingSchema_Material) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1005,7 +1135,7 @@ type PolicyAttachment_MaterialSelector struct { func (x *PolicyAttachment_MaterialSelector) Reset() { *x = PolicyAttachment_MaterialSelector{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[11] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1018,7 +1148,7 @@ func (x *PolicyAttachment_MaterialSelector) String() string { func (*PolicyAttachment_MaterialSelector) ProtoMessage() {} func (x *PolicyAttachment_MaterialSelector) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[11] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1041,6 +1171,108 @@ func (x *PolicyAttachment_MaterialSelector) GetName() string { return "" } +type PolicyGroup_PolicyGroupSpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policies *PolicyGroup_PolicyGroupPolicies `protobuf:"bytes,1,opt,name=policies,proto3" json:"policies,omitempty"` +} + +func (x *PolicyGroup_PolicyGroupSpec) Reset() { + *x = PolicyGroup_PolicyGroupSpec{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyGroup_PolicyGroupSpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyGroup_PolicyGroupSpec) ProtoMessage() {} + +func (x *PolicyGroup_PolicyGroupSpec) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PolicyGroup_PolicyGroupSpec.ProtoReflect.Descriptor instead. +func (*PolicyGroup_PolicyGroupSpec) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{9, 0} +} + +func (x *PolicyGroup_PolicyGroupSpec) GetPolicies() *PolicyGroup_PolicyGroupPolicies { + if x != nil { + return x.Policies + } + return nil +} + +type PolicyGroup_PolicyGroupPolicies struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Materials []*PolicyAttachment `protobuf:"bytes,1,rep,name=materials,proto3" json:"materials,omitempty"` + Attestation []*PolicyAttachment `protobuf:"bytes,2,rep,name=attestation,proto3" json:"attestation,omitempty"` +} + +func (x *PolicyGroup_PolicyGroupPolicies) Reset() { + *x = PolicyGroup_PolicyGroupPolicies{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyGroup_PolicyGroupPolicies) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyGroup_PolicyGroupPolicies) ProtoMessage() {} + +func (x *PolicyGroup_PolicyGroupPolicies) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PolicyGroup_PolicyGroupPolicies.ProtoReflect.Descriptor instead. +func (*PolicyGroup_PolicyGroupPolicies) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{9, 1} +} + +func (x *PolicyGroup_PolicyGroupPolicies) GetMaterials() []*PolicyAttachment { + if x != nil { + return x.Materials + } + return nil +} + +func (x *PolicyGroup_PolicyGroupPolicies) GetAttestation() []*PolicyAttachment { + if x != nil { + return x.Attestation + } + return nil +} + var File_workflowcontract_v1_crafting_schema_proto protoreflect.FileDescriptor var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ @@ -1049,7 +1281,7 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x1a, 0x1b, 0x62, 0x75, 0x66, 0x2f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe3, 0x0a, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xb4, 0x0b, 0x0a, 0x0e, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x30, 0x0a, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x09, 0xba, 0x48, 0x06, 0x72, 0x04, 0x0a, @@ -1073,187 +1305,229 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x08, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x1a, 0x82, 0x02, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, 0x65, - 0x72, 0x12, 0x56, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x35, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x75, 0x6e, 0x6e, - 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x42, 0x0b, 0xba, 0x48, 0x08, 0x82, 0x01, 0x05, 0x10, 0x01, - 0x22, 0x01, 0x00, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x0a, 0x52, 0x75, - 0x6e, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x55, 0x4e, 0x4e, - 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, - 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x49, 0x54, 0x4c, - 0x41, 0x42, 0x5f, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x12, 0x0a, - 0x0e, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49, 0x4e, 0x45, 0x10, - 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x4a, 0x45, 0x4e, 0x4b, 0x49, 0x4e, 0x53, 0x5f, 0x4a, 0x4f, 0x42, - 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x5f, 0x42, - 0x55, 0x49, 0x4c, 0x44, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x41, 0x47, 0x47, 0x45, 0x52, - 0x5f, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x06, 0x1a, 0xe5, 0x05, 0x0a, 0x08, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x5a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, - 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, - 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, - 0x65, 0x42, 0x0b, 0xba, 0x48, 0x08, 0x82, 0x01, 0x05, 0x10, 0x01, 0x22, 0x01, 0x00, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, - 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, - 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, - 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, - 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, - 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, - 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, - 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, - 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, - 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, - 0x75, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xeb, 0x02, 0x0a, 0x0c, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x41, 0x54, 0x45, 0x52, 0x49, - 0x41, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, - 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, - 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, 0x49, - 0x4d, 0x41, 0x47, 0x45, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52, 0x54, 0x49, 0x46, 0x41, - 0x43, 0x54, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x43, 0x59, 0x43, - 0x4c, 0x4f, 0x4e, 0x45, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x12, 0x0a, - 0x0e, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x53, 0x50, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, - 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x55, 0x4e, 0x49, 0x54, 0x5f, 0x58, 0x4d, 0x4c, 0x10, 0x06, - 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, 0x45, 0x4e, 0x56, 0x45, 0x58, 0x10, 0x07, 0x12, 0x0e, 0x0a, - 0x0a, 0x48, 0x45, 0x4c, 0x4d, 0x5f, 0x43, 0x48, 0x41, 0x52, 0x54, 0x10, 0x0a, 0x12, 0x09, 0x0a, - 0x05, 0x53, 0x41, 0x52, 0x49, 0x46, 0x10, 0x09, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x56, 0x49, 0x44, - 0x45, 0x4e, 0x43, 0x45, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x54, 0x54, 0x45, 0x53, 0x54, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0c, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x53, 0x41, 0x46, 0x5f, - 0x56, 0x45, 0x58, 0x10, 0x08, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x53, 0x41, 0x46, 0x5f, 0x49, 0x4e, - 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x41, 0x44, 0x56, 0x49, - 0x53, 0x4f, 0x52, 0x59, 0x10, 0x0d, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x53, 0x41, 0x46, 0x5f, 0x53, - 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, 0x59, - 0x10, 0x0e, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x53, 0x41, 0x46, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, - 0x49, 0x54, 0x59, 0x5f, 0x49, 0x4e, 0x43, 0x49, 0x44, 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, 0x53, - 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x0f, 0x12, 0x1a, 0x0a, 0x16, 0x47, 0x49, 0x54, 0x4c, 0x41, - 0x42, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x52, 0x45, 0x50, 0x4f, 0x52, - 0x54, 0x10, 0x10, 0x22, 0x46, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x22, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x0e, 0xba, 0x48, 0x0b, 0x72, 0x09, 0x32, 0x07, 0x5e, 0x5b, 0x5c, 0x77, 0x5d, 0x2b, 0x24, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x98, 0x01, 0x0a, 0x08, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x09, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, - 0x6e, 0x74, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x47, 0x0a, - 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, - 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x91, 0x03, 0x0a, 0x10, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x03, 0x72, - 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x48, 0x00, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x39, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, - 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, - 0x64, 0x65, 0x64, 0x12, 0x52, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x61, 0x74, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x08, 0x73, - 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x04, 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2f, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x74, - 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x57, 0x69, 0x74, 0x68, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, - 0x01, 0x1a, 0x26, 0x0a, 0x10, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x53, 0x65, 0x6c, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0f, 0x0a, 0x06, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0xf6, 0x01, 0x0a, 0x06, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x49, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x28, 0xba, 0x48, 0x25, 0x72, - 0x23, 0x0a, 0x21, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x61, 0x63, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2e, 0x64, 0x65, - 0x76, 0x2f, 0x76, 0x31, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x21, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x0d, - 0xba, 0x48, 0x0a, 0x72, 0x08, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x04, 0x6b, - 0x69, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x6d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x53, 0x70, 0x65, 0x63, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x73, - 0x70, 0x65, 0x63, 0x22, 0xd8, 0x02, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x64, - 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, 0x6f, - 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, 0x72, - 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, 0x75, - 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, - 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, - 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, 0x61, - 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, - 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, 0x0b, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3e, - 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x80, - 0x03, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x18, 0x0a, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x48, - 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, - 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, 0x52, - 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x5e, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x4f, 0x0a, 0x0d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x41, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x1a, 0x82, 0x02, 0x0a, 0x06, 0x52, 0x75, 0x6e, 0x6e, + 0x65, 0x72, 0x12, 0x56, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x35, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x52, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x75, 0x6e, + 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x42, 0x0b, 0xba, 0x48, 0x08, 0x82, 0x01, 0x05, 0x10, + 0x01, 0x22, 0x01, 0x00, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x9f, 0x01, 0x0a, 0x0a, 0x52, + 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x52, 0x55, 0x4e, + 0x4e, 0x45, 0x52, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, + 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x47, 0x49, 0x54, + 0x4c, 0x41, 0x42, 0x5f, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x02, 0x12, 0x12, + 0x0a, 0x0e, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49, 0x4e, 0x45, + 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x4a, 0x45, 0x4e, 0x4b, 0x49, 0x4e, 0x53, 0x5f, 0x4a, 0x4f, + 0x42, 0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x5f, + 0x42, 0x55, 0x49, 0x4c, 0x44, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x41, 0x47, 0x47, 0x45, + 0x52, 0x5f, 0x50, 0x49, 0x50, 0x45, 0x4c, 0x49, 0x4e, 0x45, 0x10, 0x06, 0x1a, 0xe5, 0x05, 0x0a, + 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x5a, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, - 0x70, 0x65, 0x42, 0x0f, 0xba, 0x48, 0x0a, 0x82, 0x01, 0x07, 0x22, 0x05, 0x01, 0x02, 0x03, 0x0a, - 0x0b, 0x18, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, 0x6f, + 0x70, 0x65, 0x42, 0x0b, 0xba, 0x48, 0x08, 0x82, 0x01, 0x05, 0x10, 0x01, 0x22, 0x01, 0x00, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, + 0x61, 0x6d, 0x65, 0x2e, 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, + 0x73, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, + 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, + 0x73, 0x2c, 0x20, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, + 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, + 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, + 0x5d, 0x28, 0x5b, 0x2d, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, + 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x08, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x6f, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x6f, 0x75, 0x74, + 0x70, 0x75, 0x74, 0x12, 0x41, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xeb, 0x02, 0x0a, 0x0c, 0x4d, 0x61, 0x74, 0x65, 0x72, + 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x4d, 0x41, 0x54, 0x45, 0x52, + 0x49, 0x41, 0x4c, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, + 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x4f, 0x4e, 0x54, 0x41, 0x49, 0x4e, 0x45, 0x52, 0x5f, + 0x49, 0x4d, 0x41, 0x47, 0x45, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x41, 0x52, 0x54, 0x49, 0x46, + 0x41, 0x43, 0x54, 0x10, 0x03, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x43, 0x59, + 0x43, 0x4c, 0x4f, 0x4e, 0x45, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, 0x10, 0x04, 0x12, 0x12, + 0x0a, 0x0e, 0x53, 0x42, 0x4f, 0x4d, 0x5f, 0x53, 0x50, 0x44, 0x58, 0x5f, 0x4a, 0x53, 0x4f, 0x4e, + 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x55, 0x4e, 0x49, 0x54, 0x5f, 0x58, 0x4d, 0x4c, 0x10, + 0x06, 0x12, 0x0b, 0x0a, 0x07, 0x4f, 0x50, 0x45, 0x4e, 0x56, 0x45, 0x58, 0x10, 0x07, 0x12, 0x0e, + 0x0a, 0x0a, 0x48, 0x45, 0x4c, 0x4d, 0x5f, 0x43, 0x48, 0x41, 0x52, 0x54, 0x10, 0x0a, 0x12, 0x09, + 0x0a, 0x05, 0x53, 0x41, 0x52, 0x49, 0x46, 0x10, 0x09, 0x12, 0x0c, 0x0a, 0x08, 0x45, 0x56, 0x49, + 0x44, 0x45, 0x4e, 0x43, 0x45, 0x10, 0x0b, 0x12, 0x0f, 0x0a, 0x0b, 0x41, 0x54, 0x54, 0x45, 0x53, + 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x0c, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x53, 0x41, 0x46, + 0x5f, 0x56, 0x45, 0x58, 0x10, 0x08, 0x12, 0x1f, 0x0a, 0x1b, 0x43, 0x53, 0x41, 0x46, 0x5f, 0x49, + 0x4e, 0x46, 0x4f, 0x52, 0x4d, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x5f, 0x41, 0x44, 0x56, + 0x49, 0x53, 0x4f, 0x52, 0x59, 0x10, 0x0d, 0x12, 0x1a, 0x0a, 0x16, 0x43, 0x53, 0x41, 0x46, 0x5f, + 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x41, 0x44, 0x56, 0x49, 0x53, 0x4f, 0x52, + 0x59, 0x10, 0x0e, 0x12, 0x23, 0x0a, 0x1f, 0x43, 0x53, 0x41, 0x46, 0x5f, 0x53, 0x45, 0x43, 0x55, + 0x52, 0x49, 0x54, 0x59, 0x5f, 0x49, 0x4e, 0x43, 0x49, 0x44, 0x45, 0x4e, 0x54, 0x5f, 0x52, 0x45, + 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x10, 0x0f, 0x12, 0x1a, 0x0a, 0x16, 0x47, 0x49, 0x54, 0x4c, + 0x41, 0x42, 0x5f, 0x53, 0x45, 0x43, 0x55, 0x52, 0x49, 0x54, 0x59, 0x5f, 0x52, 0x45, 0x50, 0x4f, + 0x52, 0x54, 0x10, 0x10, 0x22, 0x46, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x0e, 0xba, 0x48, 0x0b, 0x72, 0x09, 0x32, 0x07, 0x5e, 0x5b, 0x5c, 0x77, 0x5d, 0x2b, 0x24, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x98, 0x01, 0x0a, + 0x08, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x09, 0x6d, 0x61, 0x74, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x47, + 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x91, 0x03, 0x0a, 0x10, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x03, + 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x48, 0x00, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x39, 0x0a, 0x08, 0x65, 0x6d, 0x62, + 0x65, 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 0x56, 0x32, 0x52, 0x08, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x3a, 0x8c, 0x01, 0xba, 0x48, 0x88, 0x01, 0x1a, - 0x85, 0x01, 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x73, 0x70, 0x65, 0x63, 0x12, 0x36, - 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x20, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x20, 0x66, - 0x69, 0x65, 0x6c, 0x64, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x1a, 0x3f, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, 0x73, - 0x2e, 0x70, 0x61, 0x74, 0x68, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, - 0x69, 0x73, 0x2e, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x29, 0x20, 0x7c, 0x7c, 0x20, - 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, - 0x65, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x0c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, - 0x56, 0x32, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, - 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x65, 0x6d, - 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x5c, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, - 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, 0x66, 0x74, - 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, - 0x61, 0x6c, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x42, - 0x0d, 0xba, 0x48, 0x0a, 0x82, 0x01, 0x07, 0x22, 0x05, 0x01, 0x02, 0x03, 0x0a, 0x0b, 0x52, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x42, 0x0f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x05, - 0xba, 0x48, 0x02, 0x08, 0x01, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2d, 0x64, 0x65, - 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, 0x61, 0x70, 0x70, 0x2f, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x2f, 0x61, 0x70, 0x69, - 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, - 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x48, 0x00, 0x52, 0x08, 0x65, 0x6d, 0x62, 0x65, + 0x64, 0x64, 0x65, 0x64, 0x12, 0x52, 0x0a, 0x08, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x4d, 0x61, + 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x08, + 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x64, 0x69, 0x73, 0x61, + 0x62, 0x6c, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x04, 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 0x1a, 0x37, 0x0a, 0x09, 0x57, 0x69, 0x74, + 0x68, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0x26, 0x0a, 0x10, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0f, 0x0a, 0x06, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x12, 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0xf6, 0x01, 0x0a, 0x06, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x49, 0x0a, 0x0b, 0x61, 0x70, 0x69, 0x5f, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x28, 0xba, 0x48, 0x25, + 0x72, 0x23, 0x0a, 0x21, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, + 0x72, 0x61, 0x63, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2e, 0x64, + 0x65, 0x76, 0x2f, 0x76, 0x31, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x21, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x0d, 0xba, 0x48, 0x0a, 0x72, 0x08, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x04, + 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x41, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, + 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x6d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x3b, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, + 0x73, 0x70, 0x65, 0x63, 0x22, 0xd8, 0x02, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, 0x0a, 0x0d, 0x6e, 0x61, 0x6d, 0x65, 0x2e, + 0x64, 0x6e, 0x73, 0x2d, 0x31, 0x31, 0x32, 0x33, 0x12, 0x3a, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x77, 0x65, + 0x72, 0x63, 0x61, 0x73, 0x65, 0x20, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x6e, + 0x75, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x68, 0x79, 0x70, 0x68, + 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x2f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, + 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x28, 0x5b, 0x2d, + 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x2a, 0x5b, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, + 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x50, 0x0a, + 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x05, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, + 0x3e, 0x0a, 0x10, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x80, 0x03, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 0x12, 0x18, + 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, + 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x20, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, + 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x48, 0x00, + 0x52, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x5e, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x61, + 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, + 0x79, 0x70, 0x65, 0x42, 0x0f, 0xba, 0x48, 0x0a, 0x82, 0x01, 0x07, 0x22, 0x05, 0x01, 0x02, 0x03, + 0x0a, 0x0b, 0x18, 0x01, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 0x56, 0x32, 0x52, + 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x3a, 0x8c, 0x01, 0xba, 0x48, 0x88, 0x01, + 0x1a, 0x85, 0x01, 0x0a, 0x0a, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x73, 0x70, 0x65, 0x63, 0x12, + 0x36, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x73, 0x70, 0x65, 0x63, 0x20, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x20, 0x6f, 0x72, 0x20, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x20, + 0x66, 0x69, 0x65, 0x6c, 0x64, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x1a, 0x3f, 0x68, 0x61, 0x73, 0x28, 0x74, 0x68, 0x69, + 0x73, 0x2e, 0x70, 0x61, 0x74, 0x68, 0x29, 0x20, 0x7c, 0x7c, 0x20, 0x68, 0x61, 0x73, 0x28, 0x74, + 0x68, 0x69, 0x73, 0x2e, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x29, 0x20, 0x7c, 0x7c, + 0x20, 0x73, 0x69, 0x7a, 0x65, 0x28, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x29, 0x20, 0x3e, 0x20, 0x30, 0x42, 0x08, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x22, 0xb1, 0x01, 0x0a, 0x0c, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, + 0x63, 0x56, 0x32, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x0a, 0x08, 0x65, 0x6d, 0x62, + 0x65, 0x64, 0x64, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x08, 0x65, + 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x5c, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x61, 0x66, + 0x74, 0x69, 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, + 0x69, 0x61, 0x6c, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, + 0x42, 0x0d, 0xba, 0x48, 0x0a, 0x82, 0x01, 0x07, 0x22, 0x05, 0x01, 0x02, 0x03, 0x0a, 0x0b, 0x52, + 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x42, 0x0f, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, + 0x05, 0xba, 0x48, 0x02, 0x08, 0x01, 0x22, 0x32, 0x0a, 0x15, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x19, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x72, 0x65, 0x66, 0x22, 0x9c, 0x04, 0x0a, 0x0b, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x49, 0x0a, 0x0b, 0x61, 0x70, + 0x69, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x28, 0xba, 0x48, 0x25, 0x72, 0x23, 0x0a, 0x21, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, + 0x6f, 0x70, 0x2e, 0x64, 0x65, 0x76, 0x2f, 0x76, 0x31, 0x52, 0x0a, 0x61, 0x70, 0x69, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x12, 0xba, 0x48, 0x0f, 0x72, 0x0d, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x12, 0x41, 0x0a, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, + 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x06, + 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x12, 0x4c, 0x0a, 0x04, 0x73, 0x70, 0x65, 0x63, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, + 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, + 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x70, 0x65, 0x63, + 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x73, 0x70, 0x65, 0x63, 0x1a, 0x63, + 0x0a, 0x0f, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x70, 0x65, + 0x63, 0x12, 0x50, 0x0a, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x47, 0x72, 0x6f, 0x75, 0x70, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x1a, 0xa3, 0x01, 0x0a, 0x13, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x43, 0x0a, 0x09, 0x6d, + 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, + 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, + 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x09, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, + 0x12, 0x47, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0b, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, + 0x70, 0x2d, 0x64, 0x65, 0x76, 0x2f, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x6c, 0x6f, 0x6f, 0x70, 0x2f, + 0x61, 0x70, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x70, 0x6c, 0x61, 0x6e, 0x65, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1269,7 +1543,7 @@ func file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP() []byte { } var file_workflowcontract_v1_crafting_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_workflowcontract_v1_crafting_schema_proto_goTypes = []interface{}{ (CraftingSchema_Runner_RunnerType)(0), // 0: workflowcontract.v1.CraftingSchema.Runner.RunnerType (CraftingSchema_Material_MaterialType)(0), // 1: workflowcontract.v1.CraftingSchema.Material.MaterialType @@ -1281,36 +1555,46 @@ var file_workflowcontract_v1_crafting_schema_proto_goTypes = []interface{}{ (*Metadata)(nil), // 7: workflowcontract.v1.Metadata (*PolicySpec)(nil), // 8: workflowcontract.v1.PolicySpec (*PolicySpecV2)(nil), // 9: workflowcontract.v1.PolicySpecV2 - (*CraftingSchema_Runner)(nil), // 10: workflowcontract.v1.CraftingSchema.Runner - (*CraftingSchema_Material)(nil), // 11: workflowcontract.v1.CraftingSchema.Material - nil, // 12: workflowcontract.v1.PolicyAttachment.WithEntry - (*PolicyAttachment_MaterialSelector)(nil), // 13: workflowcontract.v1.PolicyAttachment.MaterialSelector - nil, // 14: workflowcontract.v1.Metadata.AnnotationsEntry + (*PolicyGroupAttachment)(nil), // 10: workflowcontract.v1.PolicyGroupAttachment + (*PolicyGroup)(nil), // 11: workflowcontract.v1.PolicyGroup + (*CraftingSchema_Runner)(nil), // 12: workflowcontract.v1.CraftingSchema.Runner + (*CraftingSchema_Material)(nil), // 13: workflowcontract.v1.CraftingSchema.Material + nil, // 14: workflowcontract.v1.PolicyAttachment.WithEntry + (*PolicyAttachment_MaterialSelector)(nil), // 15: workflowcontract.v1.PolicyAttachment.MaterialSelector + nil, // 16: workflowcontract.v1.Metadata.AnnotationsEntry + (*PolicyGroup_PolicyGroupSpec)(nil), // 17: workflowcontract.v1.PolicyGroup.PolicyGroupSpec + (*PolicyGroup_PolicyGroupPolicies)(nil), // 18: workflowcontract.v1.PolicyGroup.PolicyGroupPolicies } var file_workflowcontract_v1_crafting_schema_proto_depIdxs = []int32{ - 11, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material - 10, // 1: workflowcontract.v1.CraftingSchema.runner:type_name -> workflowcontract.v1.CraftingSchema.Runner + 13, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material + 12, // 1: workflowcontract.v1.CraftingSchema.runner:type_name -> workflowcontract.v1.CraftingSchema.Runner 3, // 2: workflowcontract.v1.CraftingSchema.annotations:type_name -> workflowcontract.v1.Annotation 4, // 3: workflowcontract.v1.CraftingSchema.policies:type_name -> workflowcontract.v1.Policies - 5, // 4: workflowcontract.v1.Policies.materials:type_name -> workflowcontract.v1.PolicyAttachment - 5, // 5: workflowcontract.v1.Policies.attestation:type_name -> workflowcontract.v1.PolicyAttachment - 6, // 6: workflowcontract.v1.PolicyAttachment.embedded:type_name -> workflowcontract.v1.Policy - 13, // 7: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector - 12, // 8: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.WithEntry - 7, // 9: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata - 8, // 10: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec - 14, // 11: workflowcontract.v1.Metadata.annotations:type_name -> workflowcontract.v1.Metadata.AnnotationsEntry - 1, // 12: workflowcontract.v1.PolicySpec.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 9, // 13: workflowcontract.v1.PolicySpec.policies:type_name -> workflowcontract.v1.PolicySpecV2 - 1, // 14: workflowcontract.v1.PolicySpecV2.kind:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 0, // 15: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 1, // 16: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 3, // 17: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation - 18, // [18:18] is the sub-list for method output_type - 18, // [18:18] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 10, // 4: workflowcontract.v1.CraftingSchema.policy_groups:type_name -> workflowcontract.v1.PolicyGroupAttachment + 5, // 5: workflowcontract.v1.Policies.materials:type_name -> workflowcontract.v1.PolicyAttachment + 5, // 6: workflowcontract.v1.Policies.attestation:type_name -> workflowcontract.v1.PolicyAttachment + 6, // 7: workflowcontract.v1.PolicyAttachment.embedded:type_name -> workflowcontract.v1.Policy + 15, // 8: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector + 14, // 9: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.WithEntry + 7, // 10: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata + 8, // 11: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec + 16, // 12: workflowcontract.v1.Metadata.annotations:type_name -> workflowcontract.v1.Metadata.AnnotationsEntry + 1, // 13: workflowcontract.v1.PolicySpec.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 9, // 14: workflowcontract.v1.PolicySpec.policies:type_name -> workflowcontract.v1.PolicySpecV2 + 1, // 15: workflowcontract.v1.PolicySpecV2.kind:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 7, // 16: workflowcontract.v1.PolicyGroup.metadata:type_name -> workflowcontract.v1.Metadata + 17, // 17: workflowcontract.v1.PolicyGroup.spec:type_name -> workflowcontract.v1.PolicyGroup.PolicyGroupSpec + 0, // 18: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 1, // 19: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 3, // 20: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation + 18, // 21: workflowcontract.v1.PolicyGroup.PolicyGroupSpec.policies:type_name -> workflowcontract.v1.PolicyGroup.PolicyGroupPolicies + 5, // 22: workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.materials:type_name -> workflowcontract.v1.PolicyAttachment + 5, // 23: workflowcontract.v1.PolicyGroup.PolicyGroupPolicies.attestation:type_name -> workflowcontract.v1.PolicyAttachment + 24, // [24:24] is the sub-list for method output_type + 24, // [24:24] is the sub-list for method input_type + 24, // [24:24] is the sub-list for extension type_name + 24, // [24:24] is the sub-list for extension extendee + 0, // [0:24] is the sub-list for field type_name } func init() { file_workflowcontract_v1_crafting_schema_proto_init() } @@ -1416,7 +1700,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingSchema_Runner); i { + switch v := v.(*PolicyGroupAttachment); i { case 0: return &v.state case 1: @@ -1428,7 +1712,19 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingSchema_Material); i { + switch v := v.(*PolicyGroup); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_workflowcontract_v1_crafting_schema_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CraftingSchema_Runner); i { case 0: return &v.state case 1: @@ -1440,6 +1736,18 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CraftingSchema_Material); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_workflowcontract_v1_crafting_schema_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PolicyAttachment_MaterialSelector); i { case 0: return &v.state @@ -1451,6 +1759,30 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { return nil } } + file_workflowcontract_v1_crafting_schema_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PolicyGroup_PolicyGroupSpec); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_workflowcontract_v1_crafting_schema_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PolicyGroup_PolicyGroupPolicies); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[3].OneofWrappers = []interface{}{ (*PolicyAttachment_Ref)(nil), @@ -1470,7 +1802,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_workflowcontract_v1_crafting_schema_proto_rawDesc, NumEnums: 2, - NumMessages: 13, + NumMessages: 17, NumExtensions: 0, NumServices: 0, }, diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 4c4ec96b7..a4e0e339e 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -37,6 +37,9 @@ message CraftingSchema { // Policies to apply to this schema Policies policies = 6; + // Policy groups to apply to this schema + repeated PolicyGroupAttachment policy_groups = 7; + message Runner { RunnerType type = 1 [ (buf.validate.field).enum = { @@ -132,15 +135,6 @@ message PolicyAttachment { // meant to be used to embed the policy in the contract Policy embedded = 2; - // TODO: reference to a policy already known by chainloop - // string name = 2 [(buf.validate.field) = { - // cel: { - // message: "must contain only lowercase letters, numbers, and hyphens.", - // expression: "this.matches('^[a-z0-9]([-a-z0-9]*[a-z0-9])?$')", - // id: "name.dns-1123", - // }, - // }]; - option (buf.validate.oneof).required = true; } @@ -245,3 +239,30 @@ message PolicySpecV2 { ] }]; } + +// Represents a group attachment in a contract +message PolicyGroupAttachment { + // Group reference, it might be an URL or a provider reference + string ref = 1 [(buf.validate.field).string.min_len = 1]; +} + +// Represents a group or policies +message PolicyGroup { + string api_version = 1 [(buf.validate.field).string.const = "workflowcontract.chainloop.dev/v1"]; + string kind = 2 [(buf.validate.field).string.const = "PolicyGroup"]; + + Metadata metadata = 3 [(buf.validate.field).required = true]; + PolicyGroupSpec spec = 4 [(buf.validate.field).required = true]; + + message PolicyGroupSpec { + PolicyGroupPolicies policies = 1; + } + + message PolicyGroupPolicies { + repeated PolicyAttachment materials = 1; + repeated PolicyAttachment attestation = 2; + } +} + + + diff --git a/pkg/attestation/crafter/crafter.go b/pkg/attestation/crafter/crafter.go index dc81f9700..2e3a2c314 100644 --- a/pkg/attestation/crafter/crafter.go +++ b/pkg/attestation/crafter/crafter.go @@ -550,6 +550,14 @@ func (c *Crafter) addMaterial(ctx context.Context, m *schemaapi.CraftingSchema_M return fmt.Errorf("validation error: %w", err) } + // Validate policy groups + pgv := policies.NewPolicyGroupVerifier(c.CraftingState.InputSchema, c.attClient, c.Logger) + policyGroupResults, err := pgv.VerifyMaterial(ctx, mt, value) + if err != nil { + return fmt.Errorf("error applying policy groups to material: %w", err) + } + c.CraftingState.Attestation.PolicyEvaluations = append(c.CraftingState.Attestation.PolicyEvaluations, policyGroupResults...) + // Validate policies pv := policies.NewPolicyVerifier(c.CraftingState.InputSchema, c.attClient, c.Logger) policyResults, err := pv.VerifyMaterial(ctx, mt, value) @@ -557,11 +565,12 @@ func (c *Crafter) addMaterial(ctx context.Context, m *schemaapi.CraftingSchema_M return fmt.Errorf("error applying policies to material: %w", err) } - // log policy violations - policies.LogPolicyViolations(policyResults, c.Logger) // store policy results c.CraftingState.Attestation.PolicyEvaluations = append(c.CraftingState.Attestation.PolicyEvaluations, policyResults...) + // log policy violations + policies.LogPolicyViolations(c.CraftingState.Attestation.PolicyEvaluations, c.Logger) + // 5 - Attach it to state if c.CraftingState.Attestation.Materials == nil { c.CraftingState.Attestation.Materials = map[string]*api.Attestation_Material{m.Name: mt} diff --git a/pkg/attestation/renderer/chainloop/v02.go b/pkg/attestation/renderer/chainloop/v02.go index 20f4948b2..7ce5420d7 100644 --- a/pkg/attestation/renderer/chainloop/v02.go +++ b/pkg/attestation/renderer/chainloop/v02.go @@ -83,6 +83,8 @@ func NewChainloopRendererV02(att *v1.Attestation, schema *schemaapi.CraftingSche } func (r *RendererV02) Statement(ctx context.Context) (*intoto.Statement, error) { + var evaluations []*v1.PolicyEvaluation + subject, err := r.subject() if err != nil { return nil, fmt.Errorf("error creating subject: %w", err) @@ -100,17 +102,26 @@ func (r *RendererV02) Statement(ctx context.Context) (*intoto.Statement, error) Predicate: predicate, } + // Validate policy groups + pgv := policies.NewPolicyGroupVerifier(r.schema, r.attClient, r.logger) + policyGroupResults, err := pgv.VerifyStatement(ctx, statement) + if err != nil { + return nil, fmt.Errorf("error applying policy groups to statement: %w", err) + } + evaluations = append(evaluations, policyGroupResults...) + // validate attestation-level policies pv := policies.NewPolicyVerifier(r.schema, r.attClient, r.logger) policyResults, err := pv.VerifyStatement(ctx, statement) if err != nil { return nil, fmt.Errorf("applying policies to statement: %w", err) } + evaluations = append(evaluations, policyResults...) // log policy violations - policies.LogPolicyViolations(policyResults, r.logger) + policies.LogPolicyViolations(evaluations, r.logger) // insert attestation level policy results into statement - if err = addPolicyResults(statement, policyResults); err != nil { + if err = addPolicyResults(statement, evaluations); err != nil { return nil, fmt.Errorf("adding policy results to statement: %w", err) } diff --git a/pkg/policies/group_loader.go b/pkg/policies/group_loader.go new file mode 100644 index 000000000..8a6630cb2 --- /dev/null +++ b/pkg/policies/group_loader.go @@ -0,0 +1,94 @@ +// +// Copyright 2024 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package policies + +import ( + "context" + "fmt" + "io" + "net/http" + "os" + "path/filepath" + + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v12 "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/api/attestation/v1" +) + +// GroupLoader defines the interface for policy loaders from contract attachments +type GroupLoader interface { + Load(context.Context, *v1.PolicyGroupAttachment) (*v1.PolicyGroup, *v12.ResourceDescriptor, error) +} + +// FileGroupLoader loader loads policies from filesystem and HTTPS references using Cosign's blob package +type FileGroupLoader struct{} + +func (l *FileGroupLoader) Load(_ context.Context, attachment *v1.PolicyGroupAttachment) (*v1.PolicyGroup, *v12.ResourceDescriptor, error) { + var ( + raw []byte + err error + ) + + // First remove the digest if present + ref, wantDigest := ExtractDigest(attachment.GetRef()) + filePath, err := ensureScheme(ref, fileScheme) + if err != nil { + return nil, nil, err + } + + raw, err = os.ReadFile(filepath.Clean(filePath)) + if err != nil { + return nil, nil, fmt.Errorf("loading policy spec: %w", err) + } + + var group v1.PolicyGroup + d, err := unmarshallResource(raw, ref, wantDigest, &group) + if err != nil { + return nil, nil, fmt.Errorf("unmarshalling policy spec: %w", err) + } + + return &group, d, nil +} + +// HTTPSGroupLoader loader loads policies from HTTP or HTTPS references +type HTTPSGroupLoader struct{} + +func (l *HTTPSGroupLoader) Load(_ context.Context, attachment *v1.PolicyGroupAttachment) (*v1.PolicyGroup, *v12.ResourceDescriptor, error) { + ref, wantDigest := ExtractDigest(attachment.GetRef()) + + // and do not remove the scheme since we need http(s):// to make the request + if _, err := ensureScheme(ref, httpScheme, httpsScheme); err != nil { + return nil, nil, fmt.Errorf("invalid policy reference %q: %w", ref, err) + } + + // #nosec G107 + resp, err := http.Get(ref) + if err != nil { + return nil, nil, fmt.Errorf("requesting remote policy: %w", err) + } + defer resp.Body.Close() + raw, err := io.ReadAll(resp.Body) + if err != nil { + return nil, nil, fmt.Errorf("reading remote policy: %w", err) + } + + var group v1.PolicyGroup + d, err := unmarshallResource(raw, ref, wantDigest, &group) + if err != nil { + return nil, nil, fmt.Errorf("unmarshalling policy spec: %w", err) + } + + return &group, d, nil +} diff --git a/pkg/policies/loader.go b/pkg/policies/loader.go index a6ec351da..0fd9b65f5 100644 --- a/pkg/policies/loader.go +++ b/pkg/policies/loader.go @@ -32,6 +32,7 @@ import ( v12 "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/api/attestation/v1" crv1 "github.com/google/go-containerregistry/pkg/v1" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" ) const ( @@ -74,23 +75,13 @@ func (l *FileLoader) Load(_ context.Context, attachment *v1.PolicyAttachment) (* return nil, nil, fmt.Errorf("loading policy spec: %w", err) } - p, err := unmarshalPolicy(raw, filepath.Ext(filePath)) + var policy v1.Policy + d, err := unmarshallResource(raw, ref, wantDigest, &policy) if err != nil { return nil, nil, fmt.Errorf("unmarshalling policy spec: %w", err) } - // calculate hash of the raw data - h, _, err := crv1.SHA256(bytes.NewBuffer(raw)) - if err != nil { - return nil, nil, fmt.Errorf("calculating hash: %w", err) - } - - // compare it with the wanted digest if needed - if wantDigest != "" && h.String() != wantDigest { - return nil, nil, fmt.Errorf("digest mismatch: got %s, want %s", h.String(), wantDigest) - } - - return p, policyReferenceResourceDescriptor(ref, h), nil + return &policy, d, nil } // HTTPSLoader loader loads policies from HTTP or HTTPS references @@ -115,37 +106,13 @@ func (l *HTTPSLoader) Load(_ context.Context, attachment *v1.PolicyAttachment) ( return nil, nil, fmt.Errorf("reading remote policy: %w", err) } - p, err := unmarshalPolicy(raw, filepath.Ext(ref)) + var policy v1.Policy + d, err := unmarshallResource(raw, ref, wantDigest, &policy) if err != nil { return nil, nil, fmt.Errorf("unmarshalling policy spec: %w", err) } - // calculate hash of the raw data - h, _, err := crv1.SHA256(bytes.NewBuffer(raw)) - if err != nil { - return nil, nil, fmt.Errorf("calculating hash: %w", err) - } - - // compare it with the wanted digest if needed - if wantDigest != "" && h.String() != wantDigest { - return nil, nil, fmt.Errorf("digest mismatch: got %s, want %s", h.String(), wantDigest) - } - - return p, policyReferenceResourceDescriptor(ref, h), nil -} - -func unmarshalPolicy(rawData []byte, ext string) (*v1.Policy, error) { - jsonContent, err := attestation.LoadJSONBytes(rawData, ext) - if err != nil { - return nil, fmt.Errorf("loading policy spec: %w", err) - } - - var spec v1.Policy - if err := protojson.Unmarshal(jsonContent, &spec); err != nil { - return nil, fmt.Errorf("unmarshalling policy spec: %w", err) - } - - return &spec, nil + return &policy, d, nil } // ChainloopLoader loads policies referenced with chainloop://provider/name URLs @@ -201,6 +168,30 @@ func (c *ChainloopLoader) Load(ctx context.Context, attachment *v1.PolicyAttachm return resp.GetPolicy(), reference, nil } +func unmarshallResource(raw []byte, ref string, digest string, dest proto.Message) (*v12.ResourceDescriptor, error) { + jsonContent, err := attestation.LoadJSONBytes(raw, filepath.Ext(ref)) + if err != nil { + return nil, fmt.Errorf("loading resource spec: %w", err) + } + + if err := protojson.Unmarshal(jsonContent, dest); err != nil { + return nil, fmt.Errorf("unmarshalling policy spec: %w", err) + } + + // calculate hash of the raw data + h, _, err := crv1.SHA256(bytes.NewBuffer(raw)) + if err != nil { + return nil, fmt.Errorf("calculating hash: %w", err) + } + + // compare it with the wanted digest if needed + if digest != "" && h.String() != digest { + return nil, fmt.Errorf("digest mismatch: got %s, want %s", h.String(), digest) + } + + return policyReferenceResourceDescriptor(ref, h), nil +} + // IsProviderScheme takes a policy reference and returns whether it's referencing to an external provider or not func IsProviderScheme(ref string) bool { scheme, _ := refParts(ref) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index d166670ab..ddc71ee64 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -32,6 +32,7 @@ import ( "github.com/secure-systems-lab/go-securesystemslib/dsse" "github.com/sigstore/cosign/v2/pkg/blob" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v12 "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/api/attestation/v1" @@ -55,12 +56,19 @@ func (e *PolicyError) Unwrap() error { return e.err } +type Verifier interface { + VerifyMaterial(ctx context.Context, m *v12.Attestation_Material, path string) ([]*v12.PolicyEvaluation, error) + VerifyStatement(ctx context.Context, statement *intoto.Statement) ([]*v12.PolicyEvaluation, error) +} + type PolicyVerifier struct { schema *v1.CraftingSchema logger *zerolog.Logger client v13.AttestationServiceClient } +var _ Verifier = (*PolicyVerifier)(nil) + func NewPolicyVerifier(schema *v1.CraftingSchema, client v13.AttestationServiceClient, logger *zerolog.Logger) *PolicyVerifier { return &PolicyVerifier{schema: schema, client: client, logger: logger} } @@ -75,51 +83,71 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte } for _, attachment := range attachments { - // 1. load the policy policy - policy, ref, err := pv.loadPolicySpec(ctx, attachment) + // Load material content + subject, err := getMaterialContent(material, artifactPath) if err != nil { return nil, NewPolicyError(err) } - // load the policy scripts (rego) - scripts, err := LoadPolicyScriptsFromSpec(policy, material.MaterialType) + ev, err := pv.evaluatePolicyAttachment(ctx, attachment, subject, + &evalOpts{kind: material.MaterialType, name: material.GetArtifact().GetId()}, + ) if err != nil { return nil, NewPolicyError(err) } - // Load material content - subject, err := getMaterialContent(material, artifactPath) - if err != nil { - return nil, NewPolicyError(err) - } + result = append(result, ev) + } - pv.logger.Info().Msgf("evaluating policy '%s' against material '%s'", policy.Metadata.Name, material.GetArtifact().GetId()) + return result, nil +} - violations, sources, err := pv.executeScripts(ctx, policy, scripts, subject, attachment) - if err != nil { - return nil, NewPolicyError(err) - } +type evalOpts struct { + name string + kind v1.CraftingSchema_Material_MaterialType +} - var evaluationSources []string - if !IsProviderScheme(ref.GetName()) { - evaluationSources = sources - } +func (pv *PolicyVerifier) evaluatePolicyAttachment(ctx context.Context, attachment *v1.PolicyAttachment, material []byte, opts *evalOpts) (*v12.PolicyEvaluation, error) { + // 1. load the policy policy + policy, ref, err := pv.loadPolicySpec(ctx, attachment) + if err != nil { + return nil, NewPolicyError(err) + } - result = append(result, &v12.PolicyEvaluation{ - Name: policy.GetMetadata().GetName(), - MaterialName: material.GetArtifact().GetId(), - Sources: evaluationSources, - Violations: engineViolationsToAPIViolations(violations), - Annotations: policy.GetMetadata().GetAnnotations(), - Description: policy.GetMetadata().GetDescription(), - With: attachment.GetWith(), - Type: material.GetMaterialType(), - ReferenceName: ref.Name, - ReferenceDigest: ref.Digest["sha256"], - }) + // load the policy scripts (rego) + scripts, err := LoadPolicyScriptsFromSpec(policy, opts.kind) + if err != nil { + return nil, NewPolicyError(err) } - return result, nil + if opts.name != "" { + pv.logger.Info().Msgf("evaluating policy %s against %s", policy.Metadata.Name, opts.name) + } else { + pv.logger.Info().Msgf("evaluating policy %s against attestation", policy.Metadata.Name) + } + + violations, sources, err := pv.executeScripts(ctx, policy, scripts, material, attachment) + if err != nil { + return nil, NewPolicyError(err) + } + + var evaluationSources []string + if !IsProviderScheme(ref.GetName()) { + evaluationSources = sources + } + + return &v12.PolicyEvaluation{ + Name: policy.GetMetadata().GetName(), + MaterialName: opts.name, + Sources: evaluationSources, + Violations: engineViolationsToAPIViolations(violations), + Annotations: policy.GetMetadata().GetAnnotations(), + Description: policy.GetMetadata().GetDescription(), + With: attachment.GetWith(), + Type: opts.kind, + ReferenceName: ref.Name, + ReferenceDigest: ref.Digest["sha256"], + }, nil } // VerifyStatement verifies that the statement is compliant with the policies present in the schema @@ -127,52 +155,17 @@ func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto result := make([]*v12.PolicyEvaluation, 0) policies := pv.schema.GetPolicies().GetAttestation() for _, policyAtt := range policies { - // 1. load the policy spec - policy, ref, err := pv.loadPolicySpec(ctx, policyAtt) - if err != nil { - return nil, NewPolicyError(err) - } - - // it's expected statements can only be validated by policies of type ATTESTATION - types := getPolicyTypes(policy) - if !slices.Contains(types, v1.CraftingSchema_Material_ATTESTATION) { - continue - } - - // 2. load the policy scripts (rego) - scripts, err := LoadPolicyScriptsFromSpec(policy, v1.CraftingSchema_Material_ATTESTATION) - if err != nil { - return nil, NewPolicyError(err) - } - material, err := protojson.Marshal(statement) if err != nil { return nil, NewPolicyError(err) } - pv.logger.Info().Msgf("evaluating policy '%s' on attestation", policy.Metadata.Name) - - violations, sources, err := pv.executeScripts(ctx, policy, scripts, material, policyAtt) + ev, err := pv.evaluatePolicyAttachment(ctx, policyAtt, material, &evalOpts{kind: v1.CraftingSchema_Material_ATTESTATION}) if err != nil { return nil, NewPolicyError(err) } - var evaluationSources []string - if !IsProviderScheme(ref.GetName()) { - evaluationSources = sources - } - - // 5. Store result in the attestation itself (for the renderer to include them in the predicate) - result = append(result, &v12.PolicyEvaluation{ - Name: policy.Metadata.Name, - Sources: evaluationSources, - Violations: policyViolationsToAttestationViolations(violations), - Annotations: policy.GetMetadata().GetAnnotations(), - Description: policy.GetMetadata().GetDescription(), - With: policyAtt.GetWith(), - Type: policy.GetSpec().Type, - ReferenceName: ref.Name, - ReferenceDigest: ref.Digest["sha256"]}) + result = append(result, ev) } return result, nil @@ -222,7 +215,7 @@ func (pv *PolicyVerifier) loadPolicySpec(ctx context.Context, attachment *v1.Pol } // Validate just in case - if err = validatePolicy(spec); err != nil { + if err = validateResource(spec); err != nil { return nil, nil, err } @@ -261,12 +254,12 @@ func (pv *PolicyVerifier) getLoader(attachment *v1.PolicyAttachment) (Loader, er return loader, nil } -func validatePolicy(policy *v1.Policy) error { +func validateResource(m proto.Message) error { validator, err := protovalidate.New() if err != nil { return fmt.Errorf("validating policy spec: %w", err) } - err = validator.Validate(policy) + err = validator.Validate(m) if err != nil { return fmt.Errorf("validating policy spec: %w", err) } @@ -276,6 +269,7 @@ func validatePolicy(policy *v1.Policy) error { func getInputArguments(inputs map[string]string) map[string]any { args := make(map[string]any) + for k, v := range inputs { // scan for multiple values lines := strings.Split(strings.TrimRight(v, "\n"), "\n") @@ -375,36 +369,47 @@ func (pv *PolicyVerifier) requiredPoliciesForMaterial(ctx context.Context, mater policies := pv.schema.GetPolicies().GetMaterials() for _, policyAtt := range policies { - // load the policy spec - spec, _, err := pv.loadPolicySpec(ctx, policyAtt) + apply, err := pv.shouldApplyPolicy(ctx, policyAtt, material) if err != nil { - return nil, fmt.Errorf("failed to load policy attachment %q: %w", policyAtt.GetRef(), err) + return nil, err } - materialType := material.GetMaterialType() - filteredName := policyAtt.GetSelector().GetName() - specTypes := getPolicyTypes(spec) - - // if spec has a type, and it's different to the material type, skip - if len(specTypes) > 0 && !slices.Contains(specTypes, materialType) { - // types don't match, continue - continue + if apply { + result = append(result, policyAtt) } + } - if filteredName != "" && filteredName != material.GetArtifact().GetId() { - // a filer exists and doesn't match - continue - } + return result, nil +} - // no type nor name to match, we can't guess anything - if len(specTypes) == 0 && filteredName == "" { - continue - } +func (pv *PolicyVerifier) shouldApplyPolicy(ctx context.Context, policyAtt *v1.PolicyAttachment, material *v12.Attestation_Material) (bool, error) { + // load the policy spec + spec, _, err := pv.loadPolicySpec(ctx, policyAtt) + if err != nil { + return false, fmt.Errorf("failed to load policy attachment %q: %w", policyAtt.GetRef(), err) + } - result = append(result, policyAtt) + materialType := material.GetMaterialType() + filteredName := policyAtt.GetSelector().GetName() + specTypes := getPolicyTypes(spec) + + // if spec has a type, and it's different to the material type, skip + if len(specTypes) > 0 && !slices.Contains(specTypes, materialType) { + // types don't match, continue + return false, nil } - return result, nil + if filteredName != "" && filteredName != material.GetArtifact().GetId() { + // a filer exists and doesn't match + return false, nil + } + + // no type nor name to match, we can't guess anything + if len(specTypes) == 0 && filteredName == "" { + return false, nil + } + + return true, nil } func getPolicyTypes(p *v1.Policy) []v1.CraftingSchema_Material_MaterialType { @@ -428,16 +433,6 @@ func getPolicyEngine(_ *v1.Policy) engine.PolicyEngine { return new(rego.Rego) } -func policyViolationsToAttestationViolations(violations []*engine.PolicyViolation) (pvs []*v12.PolicyEvaluation_Violation) { - for _, violation := range violations { - pvs = append(pvs, &v12.PolicyEvaluation_Violation{ - Subject: violation.Subject, - Message: violation.Violation, - }) - } - return -} - // LoadPolicyScriptsFromSpec loads all policy script that matches a given material type. It matches if: // * the policy kind is unspecified, meaning that it was forced by name selector // * the policy kind is specified, and it's equal to the material type diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index e6d3bdede..d7f682786 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -226,7 +226,7 @@ func (s *testSuite) TestVerifyAttestations() { for _, tc := range cases { s.Run(tc.name, func() { verifier := NewPolicyVerifier(tc.schema, nil, &s.logger) - statement := s.loadStatement(tc.statement) + statement := loadStatement(tc.statement, &s.Suite) res, err := verifier.VerifyStatement(context.TODO(), statement) if tc.wantErr != nil { @@ -336,7 +336,7 @@ func (s *testSuite) TestArgumentsInViolations() { s.Run("arguments in violations", func() { verifier := NewPolicyVerifier(schema, nil, &s.logger) - statement := s.loadStatement("testdata/statement.json") + statement := loadStatement("testdata/statement.json", &s.Suite) res, err := verifier.VerifyStatement(context.TODO(), statement) s.NoError(err) @@ -782,7 +782,7 @@ func TestPolicyVerifier(t *testing.T) { suite.Run(t, new(testSuite)) } -func (s *testSuite) loadStatement(file string) *intoto.Statement { +func loadStatement(file string, s *suite.Suite) *intoto.Statement { stContent, err := os.ReadFile(file) s.Require().NoError(err) var statement intoto.Statement diff --git a/pkg/policies/policy_groups.go b/pkg/policies/policy_groups.go new file mode 100644 index 000000000..d9efdbeee --- /dev/null +++ b/pkg/policies/policy_groups.go @@ -0,0 +1,166 @@ +// +// Copyright 2024 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package policies + +import ( + "context" + "fmt" + + v13 "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + api "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/api/attestation/v1" + intoto "github.com/in-toto/attestation/go/v1" + "github.com/rs/zerolog" + "google.golang.org/protobuf/encoding/protojson" +) + +type PolicyGroupVerifier struct { + schema *v1.CraftingSchema + logger *zerolog.Logger + client v13.AttestationServiceClient + + *PolicyVerifier +} + +var _ Verifier = (*PolicyGroupVerifier)(nil) + +func NewPolicyGroupVerifier(schema *v1.CraftingSchema, client v13.AttestationServiceClient, logger *zerolog.Logger) *PolicyGroupVerifier { + return &PolicyGroupVerifier{schema: schema, client: client, logger: logger, + PolicyVerifier: NewPolicyVerifier(schema, client, logger)} +} + +// VerifyMaterial evaluates a material against groups of policies defined in the schema +func (pgv *PolicyGroupVerifier) VerifyMaterial(ctx context.Context, material *api.Attestation_Material, path string) ([]*api.PolicyEvaluation, error) { + result := make([]*api.PolicyEvaluation, 0) + + attachments, err := pgv.requiredPolicyGroupsForMaterial(ctx, material) + if err != nil { + return nil, NewPolicyError(err) + } + + for _, attachment := range attachments { + // Load material content + subject, err := getMaterialContent(material, path) + if err != nil { + return nil, NewPolicyError(err) + } + + ev, err := pgv.evaluatePolicyAttachment(ctx, attachment, subject, + &evalOpts{kind: material.MaterialType, name: material.GetArtifact().GetId()}, + ) + if err != nil { + return nil, NewPolicyError(err) + } + + result = append(result, ev) + } + + return result, nil +} + +func (pgv *PolicyGroupVerifier) VerifyStatement(ctx context.Context, statement *intoto.Statement) ([]*api.PolicyEvaluation, error) { + result := make([]*api.PolicyEvaluation, 0) + attachments := pgv.schema.GetPolicyGroups() + for _, groupAtt := range attachments { + group, _, err := pgv.loadPolicyGroup(ctx, groupAtt) + if err != nil { + return nil, NewPolicyError(err) + } + for _, attachment := range group.GetSpec().GetPolicies().GetAttestation() { + material, err := protojson.Marshal(statement) + if err != nil { + return nil, NewPolicyError(err) + } + + ev, err := pgv.evaluatePolicyAttachment(ctx, attachment, material, + &evalOpts{kind: v1.CraftingSchema_Material_ATTESTATION}, + ) + if err != nil { + return nil, NewPolicyError(err) + } + + result = append(result, ev) + } + } + + return result, nil +} + +func (pgv *PolicyGroupVerifier) requiredPolicyGroupsForMaterial(ctx context.Context, material *api.Attestation_Material) ([]*v1.PolicyAttachment, error) { + result := make([]*v1.PolicyAttachment, 0) + attachments := pgv.schema.GetPolicyGroups() + + for _, attachment := range attachments { + // 1. load the policy group + group, _, err := pgv.loadPolicyGroup(ctx, attachment) + if err != nil { + return nil, NewPolicyError(err) + } + + // 2. go through all policies in the group and check individually + for _, policyAtt := range group.GetSpec().GetPolicies().GetMaterials() { + apply, err := pgv.shouldApplyPolicy(ctx, policyAtt, material) + if err != nil { + return nil, err + } + + if apply { + result = append(result, policyAtt) + } + } + } + + return result, nil +} + +// LoadPolicySpec loads and validates a policy spec from a contract +func (pgv *PolicyGroupVerifier) loadPolicyGroup(ctx context.Context, attachment *v1.PolicyGroupAttachment) (*v1.PolicyGroup, *api.ResourceDescriptor, error) { + loader, err := pgv.getGroupLoader(attachment) + if err != nil { + return nil, nil, fmt.Errorf("failed to get a loader for policy group: %w", err) + } + + group, ref, err := loader.Load(ctx, attachment) + if err != nil { + return nil, nil, fmt.Errorf("failed to load policy group: %w", err) + } + + // Validate just in case + if err = validateResource(group); err != nil { + return nil, nil, err + } + + return group, ref, nil +} + +func (pgv *PolicyGroupVerifier) getGroupLoader(attachment *v1.PolicyGroupAttachment) (GroupLoader, error) { + ref := attachment.GetRef() + + var loader GroupLoader + scheme, _ := refParts(ref) + switch scheme { + case fileScheme: + loader = new(FileGroupLoader) + case httpsScheme, httpScheme: + loader = new(HTTPSGroupLoader) + default: + return nil, fmt.Errorf("policy scheme not supported: %q", scheme) + } + + pgv.logger.Debug().Msgf("loading policy group %q using %T", ref, loader) + + return loader, nil +} diff --git a/pkg/policies/policy_groups_test.go b/pkg/policies/policy_groups_test.go new file mode 100644 index 000000000..a84d12786 --- /dev/null +++ b/pkg/policies/policy_groups_test.go @@ -0,0 +1,225 @@ +// +// Copyright 2024 The Chainloop Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package policies + +import ( + "context" + "testing" + + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + api "github.com/chainloop-dev/chainloop/pkg/attestation/crafter/api/attestation/v1" + "github.com/rs/zerolog" + "github.com/stretchr/testify/suite" +) + +type groupsTestSuite struct { + suite.Suite + + logger zerolog.Logger +} + +func (s *groupsTestSuite) SetupTest() { + s.logger = zerolog.Nop() +} + +func TestPolicyGroups(t *testing.T) { + suite.Run(t, new(groupsTestSuite)) +} + +func (s *groupsTestSuite) TestLoadGroupSpec() { + var cases = []struct { + name string + attachment *v1.PolicyGroupAttachment + wantErr bool + expectedName string + expectedDesc string + expectedCategory string + }{ + { + name: "missing ref", + attachment: &v1.PolicyGroupAttachment{}, + wantErr: true, + }, + { + name: "by file ref", + attachment: &v1.PolicyGroupAttachment{ + Ref: "file://testdata/policy_group.yaml", + }, + expectedName: "sbom-quality", + }, + { + name: "with wrong digest", + attachment: &v1.PolicyGroupAttachment{ + Ref: "file://testdata/policy_group.yaml@sha256:24c4bd4f56b470d7436ed0c5a340483fff9ad058033f94b164f5efc59aba5136", + }, + expectedName: "sbom-quality", + wantErr: true, + }, + { + name: "with correct digest", + attachment: &v1.PolicyGroupAttachment{ + Ref: "file://testdata/policy_group.yaml@sha256:1c21e5bb5323934a6c4827e760fa3fe20086470f83b2c99a2cdb75fc0b066035", + }, + expectedName: "sbom-quality", + }, + } + + for _, tc := range cases { + s.Run(tc.name, func() { + verifier := NewPolicyGroupVerifier(nil, nil, &s.logger) + group, _, err := verifier.loadPolicyGroup(context.TODO(), tc.attachment) + if tc.wantErr { + s.Error(err) + return + } + s.Require().NoError(err) + s.Equal(tc.expectedName, group.GetMetadata().GetName()) + if tc.expectedDesc != "" { + s.Equal(tc.expectedDesc, group.Metadata.Description) + } + + if tc.expectedCategory != "" { + s.Equal(tc.expectedCategory, group.Metadata.Annotations["category"]) + } + }) + } +} + +func (s *groupsTestSuite) TestRequiredPoliciesForMaterial() { + cases := []struct { + name string + schemaRef string + materialType v1.CraftingSchema_Material_MaterialType + expected int + }{ + { + name: "no match", + schemaRef: "file://testdata/policy_group.yaml", + materialType: v1.CraftingSchema_Material_GITLAB_SECURITY_REPORT, + expected: 0, + }, + { + name: "match", + schemaRef: "file://testdata/policy_group.yaml", + materialType: v1.CraftingSchema_Material_SBOM_SPDX_JSON, + expected: 1, + }, + } + for _, tc := range cases { + s.Run(tc.name, func() { + schema := &v1.CraftingSchema{PolicyGroups: []*v1.PolicyGroupAttachment{{Ref: tc.schemaRef}}} + + material := &api.Attestation_Material{ + MaterialType: tc.materialType, + } + + v := NewPolicyGroupVerifier(schema, nil, &s.logger) + atts, err := v.requiredPolicyGroupsForMaterial(context.TODO(), material) + s.Require().NoError(err) + s.Len(atts, tc.expected) + }) + } +} + +func (s *groupsTestSuite) TestGroupLoader() { + cases := []struct { + name string + ref string + expected interface{} + wantErr bool + }{ + { + name: "file ref", + ref: "file://local-policy.yaml", + expected: &FileGroupLoader{}, + }, + { + name: "http ref", + ref: "https://myhost/policy.yaml", + expected: &HTTPSGroupLoader{}, + }, + { + name: "invalid ref", + ref: "env://environmentvar", + wantErr: true, + }, + { + name: "empty ref", + ref: "", + wantErr: true, + }, + } + + for _, tc := range cases { + s.Run(tc.name, func() { + v := NewPolicyGroupVerifier(nil, nil, &s.logger) + att := &v1.PolicyGroupAttachment{Ref: tc.ref} + loader, err := v.getGroupLoader(att) + if tc.wantErr { + s.Error(err) + return + } + s.NoError(err) + s.IsType(tc.expected, loader) + }) + } +} + +func (s *groupsTestSuite) TestVerifyAttestations() { + cases := []struct { + name string + schema *v1.CraftingSchema + statement string + npolicies int + violations int + wantErr error + }{ + { + name: "test attestation with violations", + schema: &v1.CraftingSchema{ + PolicyGroups: []*v1.PolicyGroupAttachment{ + { + Ref: "file://testdata/policy_group.yaml", + }, + }, + }, + statement: "testdata/statement.json", + npolicies: 1, + violations: 1, + }, + } + for _, tc := range cases { + s.Run(tc.name, func() { + v := NewPolicyGroupVerifier(tc.schema, nil, &s.logger) + statement := loadStatement(tc.statement, &s.Suite) + res, err := v.VerifyStatement(context.TODO(), statement) + if tc.wantErr != nil { + // #nosec G601 + s.ErrorAs(err, &tc.wantErr) + return + } + s.Require().NoError(err) + s.Len(res, tc.npolicies) + if tc.npolicies > 0 { + violations := 0 + for _, pol := range res { + violations += len(pol.Violations) + } + s.Equal(tc.violations, violations) + } + }) + } +} diff --git a/pkg/policies/testdata/policy_group.yaml b/pkg/policies/testdata/policy_group.yaml new file mode 100644 index 000000000..86d37e7dd --- /dev/null +++ b/pkg/policies/testdata/policy_group.yaml @@ -0,0 +1,14 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: PolicyGroup +metadata: + name: sbom-quality + description: This policy group applies a number of SBOM-related policies + annotations: + category: SBOM +spec: + policies: + attestation: + - ref: file://testdata/with_arguments.yaml + materials: + - ref: file://testdata/sbom_syft.yaml +