From 5a1fb5afbb782bde98461ce7f595f46ca6399483 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 13:47:20 +0200 Subject: [PATCH 01/73] feat(policy): Add Rego policy engine package Signed-off-by: Jose I. Paris --- go.mod | 11 +++ go.sum | 23 +++++ pkg/policies/engine/engine.go | 35 ++++++++ pkg/policies/engine/rego/rego.go | 90 +++++++++++++++++++ pkg/policies/engine/rego/rego_test.go | 84 +++++++++++++++++ .../engine/rego/testfiles/check_qa.rego | 26 ++++++ .../rego/testfiles/policy_without_deny.rego | 14 +++ pkg/policies/policies.go | 28 ++++++ 8 files changed, 311 insertions(+) create mode 100644 pkg/policies/engine/engine.go create mode 100644 pkg/policies/engine/rego/rego.go create mode 100644 pkg/policies/engine/rego/rego_test.go create mode 100644 pkg/policies/engine/rego/testfiles/check_qa.rego create mode 100644 pkg/policies/engine/rego/testfiles/policy_without_deny.rego create mode 100644 pkg/policies/policies.go diff --git a/go.mod b/go.mod index 4ca763249..4ab16bd6b 100644 --- a/go.mod +++ b/go.mod @@ -77,6 +77,7 @@ require ( github.com/invopop/jsonschema v0.7.0 github.com/jackc/pgx/v5 v5.5.4 github.com/muesli/reflow v0.3.0 + github.com/open-policy-agent/opa v0.63.0 github.com/openvex/go-vex v0.2.5 github.com/posthog/posthog-go v0.0.0-20240327112532-87b23fe11103 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 @@ -102,6 +103,8 @@ require ( github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/OneOfOne/xxhash v1.2.8 // indirect + github.com/agnivade/levenshtein v1.1.1 // indirect github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect @@ -120,11 +123,13 @@ require ( github.com/gliderlabs/ssh v0.3.6 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-ini/ini v1.67.0 // indirect github.com/go-jose/go-jose/v4 v4.0.1 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/assert/v2 v2.2.0 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect github.com/goadesign/goa v2.2.5+incompatible // indirect + github.com/gobwas/glob v0.2.3 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/google/cel-go v0.20.1 // indirect @@ -164,6 +169,7 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/xattr v0.4.9 // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/rs/xid v1.5.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -175,14 +181,19 @@ require ( github.com/sourcegraph/conc v0.3.0 // indirect github.com/spiffe/go-spiffe/v2 v2.2.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/tchap/go-patricia/v2 v2.3.1 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/yashtewari/glob-intersection v0.2.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/otel/sdk v1.24.0 // indirect go.step.sm/crypto v0.44.2 // indirect goa.design/goa v2.2.5+incompatible // indirect gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect diff --git a/go.sum b/go.sum index c3bc50823..916f75bce 100644 --- a/go.sum +++ b/go.sum @@ -206,6 +206,8 @@ github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:o github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= +github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= @@ -277,6 +279,8 @@ github.com/buildkite/go-pipeline v0.3.2/go.mod h1:iY5jzs3Afc8yHg6KDUcu3EJVkfaUkd github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251 h1:k6UDF1uPYOs0iy1HPeotNa155qXRWrzKnqAaGXHLZCE= github.com/buildkite/interpolate v0.0.0-20200526001904-07f35b4ae251/go.mod h1:gbPR1gPu9dB96mucYIR7T3B7p/78hRVSOuzIWLHK2Y4= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/bytecodealliance/wasmtime-go/v3 v3.0.2 h1:3uZCA/BLTIu+DqCfguByNMJa2HVHpXvjfy0Dy7g6fuA= +github.com/bytecodealliance/wasmtime-go/v3 v3.0.2/go.mod h1:RnUjnIXxEJcL6BgCvNyzCCRzZcxCgsZCi+RNlvYor5Q= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/casbin/casbin/v2 v2.29.2/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= github.com/casbin/casbin/v2 v2.81.0 h1:vNwJXK7a+TJZElZ5saP+SFJvweZNtJ3MlVP6P4IuRqE= @@ -295,6 +299,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -378,8 +383,14 @@ github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMS github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= +github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= +github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= +github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= +github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8SFyPtHLHbg49SI7NAdJiC5WIA09pe59rfAA= github.com/digitorus/pkcs7 v0.0.0-20230713084857-e76b763bdc49/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352 h1:ge14PCmCvPjpMQMIAH7uKg0lrtNSOdpYsRXlwk3QbaE= github.com/digitorus/pkcs7 v0.0.0-20230818184609-3a137a874352/go.mod h1:SKVExuS+vpu2l9IoOc0RwqE7NYnb0JlcFHFnEJkVDzc= @@ -440,6 +451,10 @@ github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4Nij github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI= +github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= @@ -573,6 +588,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68= +github.com/golang/glog v1.2.0/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -620,6 +637,8 @@ github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/certificate-transparency-go v1.1.8 h1:LGYKkgZF7satzgTak9R4yzfJXEeYVAjV6/EAEJOf1to= github.com/google/certificate-transparency-go v1.1.8/go.mod h1:bV/o8r0TBKRf1X//iiiSgWrvII4d7/8OiA+3vG26gI8= +github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 h1:0VpGH+cDhbDtdcweoyCVsF3fhN8kejK6rFe/2FFX2nU= github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49/go.mod h1:BkkQ4L1KS1xMt2aWSPStnn55ChGC0DPOn2FQYj+f25M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -1005,6 +1024,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= +github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= +github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -1461,6 +1482,8 @@ go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0 h1:9M3+rhx7kZCIQQhQRYaZCdNu1V73tm4TvXs2ntl98C4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.22.0/go.mod h1:noq80iT8rrHP1SfybmPiRGc9dc5M8RPmGvtwo7Oo7tc= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 h1:FyjCyI9jVEfqhUh2MoSkmolPjfh5fp2hnV0b0irxH4Q= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0/go.mod h1:hYwym2nDEeZfG/motx0p7L7J1N1vyzIThemQsb4g2qY= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= diff --git a/pkg/policies/engine/engine.go b/pkg/policies/engine/engine.go new file mode 100644 index 000000000..60dc403e2 --- /dev/null +++ b/pkg/policies/engine/engine.go @@ -0,0 +1,35 @@ +// +// 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 engine + +import ( + "context" +) + +type PolicyEngine interface { + Verify(ctx context.Context, policy *Policy, input []byte) ([]*PolicyViolation, error) +} + +type PolicyViolation struct { + Subject, Violation string +} + +// Policy represents a loaded policy in any of the supported technologies. +type Policy struct { + // + Module []byte `json:"module"` + Name string `json:"name"` +} diff --git a/pkg/policies/engine/rego/rego.go b/pkg/policies/engine/rego/rego.go new file mode 100644 index 000000000..0131338f6 --- /dev/null +++ b/pkg/policies/engine/rego/rego.go @@ -0,0 +1,90 @@ +// +// 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 rego + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + + "github.com/chainloop-dev/chainloop/pkg/policies/engine" + "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/rego" +) + +// Rego policy checker for chainloop attestations and materials +type Rego struct { +} + +// Force interface +var _ engine.PolicyEngine = (*Rego)(nil) + +func (r *Rego) Verify(ctx context.Context, policy *engine.Policy, input []byte) ([]*engine.PolicyViolation, error) { + policyString := string(policy.Module) + parsedModule, err := ast.ParseModule(policy.Name, policyString) + if err != nil { + return nil, fmt.Errorf("failed to parse rego policy: %w", err) + } + + // Decode input as json + decoder := json.NewDecoder(bytes.NewReader(input)) + decoder.UseNumber() + var decodedInput interface{} + if err := decoder.Decode(&decodedInput); err != nil { + return nil, fmt.Errorf("failed to parse input: %w", err) + } + + // add input + regoInput := rego.Input(decodedInput) + + // add module + regoFunc := rego.ParsedModule(parsedModule) + + // add query. Note that the predefined rule to look for is `deny` + query := rego.Query(fmt.Sprintf("%v.deny\n", parsedModule.Package.Path)) + + regoEval := rego.New(regoInput, regoFunc, query) + + res, err := regoEval.Eval(ctx) + if err != nil { + return nil, fmt.Errorf("failed to evaluate policy: %w", err) + } + + violations := make([]*engine.PolicyViolation, 0) + for _, exp := range res { + for _, val := range exp.Expressions { + denyReasons, ok := val.Value.([]interface{}) + if !ok { + return nil, fmt.Errorf("failed to evaluate policy expression evaluation result: %s", val.Text) + } + + for _, reason := range denyReasons { + reasonStr, ok := reason.(string) + if !ok { + return nil, fmt.Errorf("failed to evaluate deny reason: %s", val.Text) + } + + violations = append(violations, &engine.PolicyViolation{ + Subject: policy.Name, + Violation: reasonStr, + }) + } + } + } + + return violations, nil +} diff --git a/pkg/policies/engine/rego/rego_test.go b/pkg/policies/engine/rego/rego_test.go new file mode 100644 index 000000000..e5fd72671 --- /dev/null +++ b/pkg/policies/engine/rego/rego_test.go @@ -0,0 +1,84 @@ +// +// 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 rego + +import ( + "context" + "os" + "testing" + + "github.com/chainloop-dev/chainloop/pkg/policies/engine" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestRego_VerifyWithValidPolicy(t *testing.T) { + regoContent, err := os.ReadFile("testfiles/check_qa.rego") + require.NoError(t, err) + + r := &Rego{} + policy := &engine.Policy{ + Name: "check approval", + Module: regoContent, + } + + t.Run("invalid input", func(t *testing.T) { + violations, err := r.Verify(context.TODO(), policy, []byte("{\"foo\": \"bar\"}")) + require.NoError(t, err) + assert.Len(t, violations, 2) + assert.Contains(t, violations, &engine.PolicyViolation{ + Subject: policy.Name, + Violation: "Container image is not approved", + }) + assert.Contains(t, violations, &engine.PolicyViolation{ + Subject: policy.Name, + Violation: "Container image is not released", + }) + }) + + t.Run("valid input", func(t *testing.T) { + violations, err := r.Verify(context.TODO(), policy, []byte(` + { + "kind": "CONTAINER_IMAGE", + "references": [{ + "metadata": {"name": "chainloop-platform-qa-approval"}, + "annotations": {"approval": "true"} + }, { + "metadata": {"name": "chainloop-platform-release-production"} + }] + }`)) + require.NoError(t, err) + assert.Len(t, violations, 0) + }) +} + +func TestRego_VerifyInvalidPolicy(t *testing.T) { + // load policy without a default deny rule + regoContent, err := os.ReadFile("testfiles/policy_without_deny.rego") + require.NoError(t, err) + + r := &Rego{} + policy := &engine.Policy{ + Name: "invalid", + Module: regoContent, + } + + t.Run("doesn't eval a deny rule", func(t *testing.T) { + violations, err := r.Verify(context.TODO(), policy, []byte("{\"foo\": \"bar\"}")) + require.NoError(t, err) + assert.Len(t, violations, 0) + }) +} diff --git a/pkg/policies/engine/rego/testfiles/check_qa.rego b/pkg/policies/engine/rego/testfiles/check_qa.rego new file mode 100644 index 000000000..6ba9ca6e9 --- /dev/null +++ b/pkg/policies/engine/rego/testfiles/check_qa.rego @@ -0,0 +1,26 @@ +package main + +deny[msg] { + not is_released + + msg:= "Container image is not released" +} + +deny[msg] { + not is_approved + + msg:= "Container image is not approved" +} + +is_approved { + input.kind == "CONTAINER_IMAGE" + + input.references[i].metadata.name == "chainloop-platform-qa-approval" + input.references[i].annotations.approval == "true" +} + +is_released { + input.kind == "CONTAINER_IMAGE" + + input.references[i].metadata.name == "chainloop-platform-release-production" +} diff --git a/pkg/policies/engine/rego/testfiles/policy_without_deny.rego b/pkg/policies/engine/rego/testfiles/policy_without_deny.rego new file mode 100644 index 000000000..372f31ecf --- /dev/null +++ b/pkg/policies/engine/rego/testfiles/policy_without_deny.rego @@ -0,0 +1,14 @@ +package main + +is_approved { + input.kind == "CONTAINER_IMAGE" + + input.references[i].metadata.name == "chainloop-platform-qa-approval" + input.references[i].annotations.approval == "true" +} + +is_released { + input.kind == "CONTAINER_IMAGE" + + input.references[i].metadata.name == "chainloop-platform-release-production" +} diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go new file mode 100644 index 000000000..bfbf96c4d --- /dev/null +++ b/pkg/policies/policies.go @@ -0,0 +1,28 @@ +// +// 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 ( + "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + "github.com/chainloop-dev/chainloop/pkg/policies/engine" + "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" +) + +// GetPolicyEngine returns a PolicyEngine implementation to evaluate a given policy. +func GetPolicyEngine(_ *v1.Policy) engine.PolicyEngine { + // Currently, only Rego is supported + return new(rego.Rego) +} From 8db1f71b3bf4f0241d133fc1bc2bc88bdbabe3e8 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 14:26:53 +0200 Subject: [PATCH 02/73] goimports Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index bfbf96c4d..4dd1c4094 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -16,7 +16,7 @@ package policies import ( - "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/pkg/policies/engine" "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" ) From 60dd12e65a21fbf709b092b21504c1755863fb71 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 16:28:58 +0200 Subject: [PATCH 03/73] wip policy verifier Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 111 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 4dd1c4094..f0322d27b 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -16,11 +16,122 @@ package policies import ( + "context" + "fmt" + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v12 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/pkg/policies/engine" "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" + "github.com/sigstore/cosign/v2/pkg/blob" + "google.golang.org/protobuf/encoding/protojson" + "gopkg.in/yaml.v2" ) +type PolicyVerifier struct { + state *v12.CraftingState + engine engine.PolicyEngine +} + +func NewPolicyVerifier(state *v12.CraftingState) *PolicyVerifier { + // only Rego engine is currently supported + return &PolicyVerifier{state: state, engine: new(rego.Rego)} +} + +// Verify verifies that the statement is compliant with the policies present in the schema +func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation, error) { + violations := make([]*engine.PolicyViolation, 0) + policies := pv.state.GetInputSchema().GetPolicies() + for _, policyAtt := range policies { + if policyAtt.Disabled { + // policy is disabled + // TODO: WARN. + continue + } + spec, err := loadSpec(policyAtt) + if err != nil { + return nil, fmt.Errorf("failed to load policy spec: %w", err) + } + script, err := loadPolicyScriptFromSpec(spec) + if err != nil { + return nil, fmt.Errorf("failed to load policy content: %w", err) + } + m, err := loadSubject(policyAtt, spec, pv.state) + if err != nil { + return nil, fmt.Errorf("failed to load policy subject: %w", err) + } + // verify policy, passing arguments from policyAtt + + res, err := pv.engine.Verify(ctx, script, m) + if err != nil { + return nil, fmt.Errorf("failed to verify policy: %w", err) + } + violations = append(violations, res...) + } + + return violations, nil +} + +func loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { + // 1. look for the referenced policy spec (note: `name` is not supported yet) + reference := attachment.GetRef() + // this method understands env, http and https schemes, and defaults to file system. + specContent, err := blob.LoadFileOrURL(reference) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) + } + var policy *v1.Policy + if err := yaml.Unmarshal(specContent, &policy); err != nil { + return nil, fmt.Errorf("unmarshalling policy spec: %w", err) + } + return policy, nil +} + +// loads a policy referenced from the spec +func loadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Policy, error) { + var content []byte + var err error + if spec.GetSpec().GetEmbedded() != "" { + content = []byte(spec.GetSpec().GetEmbedded()) + } else if spec.GetSpec().GetPath() != "" { + content, err = blob.LoadFileOrURL(spec.GetSpec().GetPath()) + if err != nil { + return nil, fmt.Errorf("loading policy content: %w", err) + } + } else { + return nil, fmt.Errorf("policy spec is empty") + } + + return &engine.Policy{ + Name: spec.GetMetadata().GetName(), + Module: content, + }, nil +} + +func loadSubject(attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.CraftingState) ([]byte, error) { + // Load the affected material or attestation, and checks if the expected name and type match + name := attachment.GetSelector().GetName() + // if name selector is not set, the subject will become the full crafting state + if name == "" { + return protojson.Marshal(state.GetAttestation()) + } + + // if set, we want a material + for _, m := range state.GetAttestation().GetMaterials() { + if m.GetArtifact().GetName() == name { + return getMaterialPayload(m) + } + } + + return nil, fmt.Errorf("no material found with name %s", name) +} + +// Gets the material payload from the CAS +func getMaterialPayload(m *v12.Attestation_Material) ([]byte, error) { + // TODO + return nil, nil +} + // GetPolicyEngine returns a PolicyEngine implementation to evaluate a given policy. func GetPolicyEngine(_ *v1.Policy) engine.PolicyEngine { // Currently, only Rego is supported From d9f8048618b05d7153998fe33bcf707be10c913c Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 16:32:37 +0200 Subject: [PATCH 04/73] apply suggestions Signed-off-by: Jose I. Paris --- pkg/policies/engine/engine.go | 9 ++++++--- pkg/policies/engine/rego/rego.go | 2 +- pkg/policies/engine/rego/rego_test.go | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/policies/engine/engine.go b/pkg/policies/engine/engine.go index 60dc403e2..73d7e13da 100644 --- a/pkg/policies/engine/engine.go +++ b/pkg/policies/engine/engine.go @@ -20,16 +20,19 @@ import ( ) type PolicyEngine interface { + // Verify verifies an input against a policy Verify(ctx context.Context, policy *Policy, input []byte) ([]*PolicyViolation, error) } +// PolicyViolation represents a policy failure type PolicyViolation struct { Subject, Violation string } // Policy represents a loaded policy in any of the supported technologies. type Policy struct { - // - Module []byte `json:"module"` - Name string `json:"name"` + // the source code for this policy + Source []byte `json:"module"` + // The unique policy name + Name string `json:"name"` } diff --git a/pkg/policies/engine/rego/rego.go b/pkg/policies/engine/rego/rego.go index 0131338f6..fc9177ef9 100644 --- a/pkg/policies/engine/rego/rego.go +++ b/pkg/policies/engine/rego/rego.go @@ -34,7 +34,7 @@ type Rego struct { var _ engine.PolicyEngine = (*Rego)(nil) func (r *Rego) Verify(ctx context.Context, policy *engine.Policy, input []byte) ([]*engine.PolicyViolation, error) { - policyString := string(policy.Module) + policyString := string(policy.Source) parsedModule, err := ast.ParseModule(policy.Name, policyString) if err != nil { return nil, fmt.Errorf("failed to parse rego policy: %w", err) diff --git a/pkg/policies/engine/rego/rego_test.go b/pkg/policies/engine/rego/rego_test.go index e5fd72671..252f0149a 100644 --- a/pkg/policies/engine/rego/rego_test.go +++ b/pkg/policies/engine/rego/rego_test.go @@ -32,7 +32,7 @@ func TestRego_VerifyWithValidPolicy(t *testing.T) { r := &Rego{} policy := &engine.Policy{ Name: "check approval", - Module: regoContent, + Source: regoContent, } t.Run("invalid input", func(t *testing.T) { @@ -73,7 +73,7 @@ func TestRego_VerifyInvalidPolicy(t *testing.T) { r := &Rego{} policy := &engine.Policy{ Name: "invalid", - Module: regoContent, + Source: regoContent, } t.Run("doesn't eval a deny rule", func(t *testing.T) { From ece7794c44a5a550e2aeedde0fe5515c9725b177 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 16:47:25 +0200 Subject: [PATCH 05/73] return error if rule not found Signed-off-by: Jose I. Paris --- pkg/policies/engine/rego/rego.go | 6 ++++++ pkg/policies/engine/rego/rego_test.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/policies/engine/rego/rego.go b/pkg/policies/engine/rego/rego.go index fc9177ef9..dfc54a27e 100644 --- a/pkg/policies/engine/rego/rego.go +++ b/pkg/policies/engine/rego/rego.go @@ -19,6 +19,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "github.com/chainloop-dev/chainloop/pkg/policies/engine" @@ -64,6 +65,11 @@ func (r *Rego) Verify(ctx context.Context, policy *engine.Policy, input []byte) return nil, fmt.Errorf("failed to evaluate policy: %w", err) } + // If res is nil, it means that the rule hasn't been found + if res == nil { + return nil, errors.New("failed to evaluate policy: no 'deny' rule found") + } + violations := make([]*engine.PolicyViolation, 0) for _, exp := range res { for _, val := range exp.Expressions { diff --git a/pkg/policies/engine/rego/rego_test.go b/pkg/policies/engine/rego/rego_test.go index 252f0149a..523a9a916 100644 --- a/pkg/policies/engine/rego/rego_test.go +++ b/pkg/policies/engine/rego/rego_test.go @@ -78,7 +78,7 @@ func TestRego_VerifyInvalidPolicy(t *testing.T) { t.Run("doesn't eval a deny rule", func(t *testing.T) { violations, err := r.Verify(context.TODO(), policy, []byte("{\"foo\": \"bar\"}")) - require.NoError(t, err) + assert.Error(t, err) assert.Len(t, violations, 0) }) } From fbb5d11c43ff26a83e5f51f2ab10f36fe833e694 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 17:54:02 +0200 Subject: [PATCH 06/73] inject cas client WIP Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 51 +++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index f0322d27b..c83a27222 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -21,6 +21,7 @@ import ( v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v12 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/chainloop-dev/chainloop/pkg/policies/engine" "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" "github.com/sigstore/cosign/v2/pkg/blob" @@ -29,13 +30,13 @@ import ( ) type PolicyVerifier struct { - state *v12.CraftingState - engine engine.PolicyEngine + state *v12.CraftingState + cas *casclient.Client } -func NewPolicyVerifier(state *v12.CraftingState) *PolicyVerifier { +func NewPolicyVerifier(state *v12.CraftingState, client *casclient.Client) *PolicyVerifier { // only Rego engine is currently supported - return &PolicyVerifier{state: state, engine: new(rego.Rego)} + return &PolicyVerifier{state: state, cas: client} } // Verify verifies that the statement is compliant with the policies present in the schema @@ -48,21 +49,21 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation // TODO: WARN. continue } - spec, err := loadSpec(policyAtt) + spec, err := pv.loadSpec(policyAtt) if err != nil { return nil, fmt.Errorf("failed to load policy spec: %w", err) } - script, err := loadPolicyScriptFromSpec(spec) + script, err := pv.loadPolicyScriptFromSpec(spec) if err != nil { return nil, fmt.Errorf("failed to load policy content: %w", err) } - m, err := loadSubject(policyAtt, spec, pv.state) + material, err := pv.loadSubject(policyAtt, spec, pv.state) if err != nil { return nil, fmt.Errorf("failed to load policy subject: %w", err) } // verify policy, passing arguments from policyAtt - - res, err := pv.engine.Verify(ctx, script, m) + ng := getPolicyEngine(spec) + res, err := ng.Verify(ctx, script, material) if err != nil { return nil, fmt.Errorf("failed to verify policy: %w", err) } @@ -72,7 +73,7 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation return violations, nil } -func loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { +func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { // 1. look for the referenced policy spec (note: `name` is not supported yet) reference := attachment.GetRef() // this method understands env, http and https schemes, and defaults to file system. @@ -88,7 +89,7 @@ func loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { } // loads a policy referenced from the spec -func loadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Policy, error) { +func (pv *PolicyVerifier) loadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Policy, error) { var content []byte var err error if spec.GetSpec().GetEmbedded() != "" { @@ -104,11 +105,12 @@ func loadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Policy, error) { return &engine.Policy{ Name: spec.GetMetadata().GetName(), - Module: content, + Source: content, }, nil } -func loadSubject(attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.CraftingState) ([]byte, error) { +// load the subject of the policy. +func (pv *PolicyVerifier) loadSubject(attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.CraftingState) ([]byte, error) { // Load the affected material or attestation, and checks if the expected name and type match name := attachment.GetSelector().GetName() // if name selector is not set, the subject will become the full crafting state @@ -116,10 +118,14 @@ func loadSubject(attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.Cr return protojson.Marshal(state.GetAttestation()) } - // if set, we want a material + // if name is set, we want a specific material for _, m := range state.GetAttestation().GetMaterials() { if m.GetArtifact().GetName() == name { - return getMaterialPayload(m) + if spec.GetSpec().GetKind() != v1.CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED && spec.GetSpec().GetKind() != m.GetMaterialType() { + // If policy wasn't meant to be evaluated against this type of material, raise an error + return nil, fmt.Errorf("invalid material type: %s, policy spected: %s", m.GetMaterialType(), spec.GetSpec().GetKind()) + } + return pv.getMaterialPayload(m) } } @@ -127,13 +133,20 @@ func loadSubject(attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.Cr } // Gets the material payload from the CAS -func getMaterialPayload(m *v12.Attestation_Material) ([]byte, error) { - // TODO +func (pv *PolicyVerifier) getMaterialPayload(m *v12.Attestation_Material) ([]byte, error) { + if !m.UploadedToCas { + return m.GetArtifact().GetContent(), nil + } + // Look for material, and get its payload depending on which its nature. + // switch m.MaterialType { + // case v1.CraftingSchema_Mate + // } + return nil, nil } -// GetPolicyEngine returns a PolicyEngine implementation to evaluate a given policy. -func GetPolicyEngine(_ *v1.Policy) engine.PolicyEngine { +// getPolicyEngine returns a PolicyEngine implementation to evaluate a given policy. +func getPolicyEngine(_ *v1.Policy) engine.PolicyEngine { // Currently, only Rego is supported return new(rego.Rego) } From efa9b7f9697388fff5ca70ca90d2615262dfb502 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 18:32:03 +0200 Subject: [PATCH 07/73] some fixes Signed-off-by: Jose I. Paris --- app/cli/internal/action/attestation_push.go | 18 ++++++++++++++++++ pkg/policies/policies.go | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index 9a8da31d6..c9ef51ec0 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -18,6 +18,7 @@ package action import ( "context" "encoding/json" + "errors" "fmt" "time" @@ -25,6 +26,7 @@ import ( "github.com/chainloop-dev/chainloop/internal/attestation/crafter" "github.com/chainloop-dev/chainloop/internal/attestation/renderer" "github.com/chainloop-dev/chainloop/internal/attestation/signer" + "github.com/chainloop-dev/chainloop/pkg/policies" "github.com/secure-systems-lab/go-securesystemslib/dsse" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/timestamppb" @@ -143,6 +145,22 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru if err != nil { return nil, fmt.Errorf("creating signer: %w", err) } + + // Apply policies + pv := policies.NewPolicyVerifier(action.c.CraftingState, nil) + violations, err := pv.Verify(ctx) + if err != nil { + return nil, fmt.Errorf("verifying policies: %w", err) + } + + // TODO. Add policy results to crafting state + if len(violations) > 0 { + for _, v := range violations { + action.Logger.Error().Msgf("policy violation [%s]: %s", v.Subject, v.Violation) + } + return nil, errors.New("violations verifying policies") + } + renderer, err := renderer.NewAttestationRenderer(action.c.CraftingState, action.cliVersion, action.cliDigest, sig, renderer.WithLogger(action.Logger), renderer.WithBundleOutputPath(action.bundlePath)) if err != nil { diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index c83a27222..a8c43cca6 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -81,11 +81,11 @@ func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, if err != nil { return nil, fmt.Errorf("loading policy spec: %w", err) } - var policy *v1.Policy + var policy v1.Policy if err := yaml.Unmarshal(specContent, &policy); err != nil { return nil, fmt.Errorf("unmarshalling policy spec: %w", err) } - return policy, nil + return &policy, nil } // loads a policy referenced from the spec From 17ae7c1af71c2be46657a5d9cee9aac89efc9b4d Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 9 Jul 2024 18:51:33 +0200 Subject: [PATCH 08/73] fix unmarshalling Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter.go | 6 +++--- pkg/policies/policies.go | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index f0632cc17..e1a7ac1b5 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -153,8 +153,8 @@ func (c *Crafter) AlreadyInitialized(ctx context.Context, stateID string) (bool, return c.stateManager.Initialized(ctx, stateID) } -// Extract raw data in JSON format from different sources, i.e cue or yaml files -func loadJSONBytes(rawData []byte, extension string) ([]byte, error) { +// LoadJSONBytes Extracts raw data in JSON format from different sources, i.e cue or yaml files +func LoadJSONBytes(rawData []byte, extension string) ([]byte, error) { var jsonRawData []byte var err error @@ -187,7 +187,7 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { return nil, err } - jsonSchemaRaw, err := loadJSONBytes(content, filepath.Ext(pathOrURI)) + jsonSchemaRaw, err := LoadJSONBytes(content, filepath.Ext(pathOrURI)) if err != nil { return nil, err } diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index a8c43cca6..0727ae912 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -18,15 +18,16 @@ package policies import ( "context" "fmt" + "path/filepath" v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + "github.com/chainloop-dev/chainloop/internal/attestation/crafter" v12 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/chainloop-dev/chainloop/pkg/policies/engine" "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" "github.com/sigstore/cosign/v2/pkg/blob" "google.golang.org/protobuf/encoding/protojson" - "gopkg.in/yaml.v2" ) type PolicyVerifier struct { @@ -77,12 +78,13 @@ func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, // 1. look for the referenced policy spec (note: `name` is not supported yet) reference := attachment.GetRef() // this method understands env, http and https schemes, and defaults to file system. - specContent, err := blob.LoadFileOrURL(reference) + rawData, err := blob.LoadFileOrURL(reference) if err != nil { return nil, fmt.Errorf("loading policy spec: %w", err) } + jsonContent, err := crafter.LoadJSONBytes(rawData, filepath.Ext(reference)) var policy v1.Policy - if err := yaml.Unmarshal(specContent, &policy); err != nil { + if err := protojson.Unmarshal(jsonContent, &policy); err != nil { return nil, fmt.Errorf("unmarshalling policy spec: %w", err) } return &policy, nil From c554c280d3712e2d1b04ce32c8638e8ff3160e79 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 13:08:22 +0200 Subject: [PATCH 09/73] add tests Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 15 ++-- pkg/policies/policies_test.go | 111 ++++++++++++++++++++++++ pkg/policies/testdata/workflow.rego | 22 +++++ pkg/policies/testdata/workflow.yaml | 6 ++ pkg/policies/testdata/wrong_policy.rego | 7 ++ pkg/policies/testdata/wrong_policy.yaml | 6 ++ 6 files changed, 162 insertions(+), 5 deletions(-) create mode 100644 pkg/policies/policies_test.go create mode 100644 pkg/policies/testdata/workflow.rego create mode 100644 pkg/policies/testdata/workflow.yaml create mode 100644 pkg/policies/testdata/wrong_policy.rego create mode 100644 pkg/policies/testdata/wrong_policy.yaml diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 0727ae912..a3897405f 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -83,6 +83,9 @@ func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, return nil, fmt.Errorf("loading policy spec: %w", err) } jsonContent, err := crafter.LoadJSONBytes(rawData, filepath.Ext(reference)) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) + } var policy v1.Policy if err := protojson.Unmarshal(jsonContent, &policy); err != nil { return nil, fmt.Errorf("unmarshalling policy spec: %w", err) @@ -94,14 +97,16 @@ func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, func (pv *PolicyVerifier) loadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Policy, error) { var content []byte var err error - if spec.GetSpec().GetEmbedded() != "" { - content = []byte(spec.GetSpec().GetEmbedded()) - } else if spec.GetSpec().GetPath() != "" { - content, err = blob.LoadFileOrURL(spec.GetSpec().GetPath()) + + switch source := spec.GetSpec().GetSource().(type) { + case *v1.PolicySpec_Embedded: + content = []byte(source.Embedded) + case *v1.PolicySpec_Path: + content, err = blob.LoadFileOrURL(source.Path) if err != nil { return nil, fmt.Errorf("loading policy content: %w", err) } - } else { + default: return nil, fmt.Errorf("policy spec is empty") } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go new file mode 100644 index 000000000..709679200 --- /dev/null +++ b/pkg/policies/policies_test.go @@ -0,0 +1,111 @@ +// +// 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" + + v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPolicyVerifier_Verify(t *testing.T) { + cases := []struct { + name string + state *v1.CraftingState + violations int + wantErr bool + }{ + { + name: "happy path, test attestation properties", + state: &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, + }, + }, + }, + { + name: "wrong runner", + violations: 1, + state: &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, + }, + }, + }, + { + name: "missing runner", + violations: 1, + state: &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + }, + }, + }, + { + name: "wrong policy", + wantErr: true, + state: &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/wrong_policy.yaml"}}, + }, + }, + }, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + verifier := NewPolicyVerifier(tc.state, nil) + res, err := verifier.Verify(context.TODO()) + if tc.wantErr { + assert.Error(t, err) + return + } + require.NoError(t, err) + if tc.violations > 0 { + assert.Len(t, res, tc.violations) + } + }) + } +} diff --git a/pkg/policies/testdata/workflow.rego b/pkg/policies/testdata/workflow.rego new file mode 100644 index 000000000..403fa3c4d --- /dev/null +++ b/pkg/policies/testdata/workflow.rego @@ -0,0 +1,22 @@ +package main + +deny[msg] { + not is_workflow + + msg := "incorrect workflow" +} + +deny[msg] { + not is_github + + msg := "incorrect runner" +} + + +is_workflow { + input.workflow.name == "policytest" +} + +is_github { + input.runnerType == "GITHUB_ACTION" +} \ No newline at end of file diff --git a/pkg/policies/testdata/workflow.yaml b/pkg/policies/testdata/workflow.yaml new file mode 100644 index 000000000..60aa90267 --- /dev/null +++ b/pkg/policies/testdata/workflow.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: workflow +spec: + path: testdata/workflow.rego diff --git a/pkg/policies/testdata/wrong_policy.rego b/pkg/policies/testdata/wrong_policy.rego new file mode 100644 index 000000000..9c4e215bf --- /dev/null +++ b/pkg/policies/testdata/wrong_policy.rego @@ -0,0 +1,7 @@ +package main + +# wrong policy without a "deny" rule + +is_wrong { + true +} diff --git a/pkg/policies/testdata/wrong_policy.yaml b/pkg/policies/testdata/wrong_policy.yaml new file mode 100644 index 000000000..e6d2d9b6c --- /dev/null +++ b/pkg/policies/testdata/wrong_policy.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: wrong_policy +spec: + path: testdata/wrong_policy.rego From 0525912a6a9e1ca2382d2f5f53fbe02dba9f8a23 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 13:32:17 +0200 Subject: [PATCH 10/73] more tests Signed-off-by: Jose I. Paris --- pkg/policies/policies_test.go | 39 ++++++++++++++++++------- pkg/policies/testdata/missing_rego.yaml | 6 ++++ 2 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 pkg/policies/testdata/missing_rego.yaml diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 709679200..9439ccbe8 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -17,20 +17,20 @@ package policies import ( "context" + "io/fs" "testing" v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" ) -func TestPolicyVerifier_Verify(t *testing.T) { +func (s *testSuite) TestVerifyAttestations() { cases := []struct { name string state *v1.CraftingState violations int - wantErr bool + wantErr error }{ { name: "happy path, test attestation properties", @@ -83,7 +83,7 @@ func TestPolicyVerifier_Verify(t *testing.T) { }, { name: "wrong policy", - wantErr: true, + wantErr: &fs.PathError{}, state: &v1.CraftingState{ InputSchema: &v12.CraftingSchema{ Policies: []*v12.PolicyAttachment{ @@ -92,20 +92,39 @@ func TestPolicyVerifier_Verify(t *testing.T) { }, }, }, + { + name: "missing rego policy", + wantErr: &fs.PathError{}, + state: &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/missing_rego.yaml"}}, + }, + }, + }, + }, } for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { + s.Run(tc.name, func() { verifier := NewPolicyVerifier(tc.state, nil) res, err := verifier.Verify(context.TODO()) - if tc.wantErr { - assert.Error(t, err) + if tc.wantErr != nil { + s.ErrorAs(err, &tc.wantErr) return } - require.NoError(t, err) + s.Require().NoError(err) if tc.violations > 0 { - assert.Len(t, res, tc.violations) + s.Len(res, tc.violations) } }) } } + +type testSuite struct { + suite.Suite +} + +func TestPolicyVerifier(t *testing.T) { + suite.Run(t, new(testSuite)) +} diff --git a/pkg/policies/testdata/missing_rego.yaml b/pkg/policies/testdata/missing_rego.yaml new file mode 100644 index 000000000..0f326aa1e --- /dev/null +++ b/pkg/policies/testdata/missing_rego.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: missing-rego +spec: + path: this_is_a_missing.rego From 7247443ae3a297699d988aa6e5df2711cb430f1b Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 13:47:52 +0200 Subject: [PATCH 11/73] store result in attestation Signed-off-by: Jose I. Paris --- .../frontend/attestation/v1/crafting_state.ts | 200 ++++++ .../api/attestation/v1/crafting_state.pb.go | 590 ++++++++++++------ .../api/attestation/v1/crafting_state.proto | 18 + 3 files changed, 603 insertions(+), 205 deletions(-) diff --git a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts index af357bd63..193b6abf9 100644 --- a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts +++ b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts @@ -9,6 +9,7 @@ import { CraftingSchema_Runner_RunnerType, craftingSchema_Runner_RunnerTypeFromJSON, craftingSchema_Runner_RunnerTypeToJSON, + PolicyAttachment, } from "../../workflowcontract/v1/crafting_schema"; export const protobufPackage = "attestation.v1"; @@ -26,6 +27,8 @@ export interface Attestation { runnerType: CraftingSchema_Runner_RunnerType; /** Head Commit of the environment where the attestation was executed (optional) */ head?: Commit; + /** Policies that this attestation was validated against */ + policies: Policy[]; } export interface Attestation_MaterialsEntry { @@ -97,6 +100,21 @@ export interface Attestation_EnvVarsEntry { value: string; } +/** A policy executed against an attestation */ +export interface Policy { + /** The attachment as in the contract, with arguments and any other metadata */ + attachment?: PolicyAttachment; + /** The policy script body (rego) */ + body: string; + /** The policy violations, if any */ + violations: Policy_Violation[]; +} + +export interface Policy_Violation { + subject: string; + message: string; +} + export interface Commit { hash: string; authorEmail: string; @@ -141,6 +159,7 @@ function createBaseAttestation(): Attestation { runnerUrl: "", runnerType: 0, head: undefined, + policies: [], }; } @@ -173,6 +192,9 @@ export const Attestation = { if (message.head !== undefined) { Commit.encode(message.head, writer.uint32(74).fork()).ldelim(); } + for (const v of message.policies) { + Policy.encode(v!, writer.uint32(82).fork()).ldelim(); + } return writer; }, @@ -255,6 +277,13 @@ export const Attestation = { message.head = Commit.decode(reader, reader.uint32()); continue; + case 10: + if (tag !== 82) { + break; + } + + message.policies.push(Policy.decode(reader, reader.uint32())); + continue; } if ((tag & 7) === 4 || tag === 0) { break; @@ -290,6 +319,7 @@ export const Attestation = { runnerUrl: isSet(object.runnerUrl) ? String(object.runnerUrl) : "", runnerType: isSet(object.runnerType) ? craftingSchema_Runner_RunnerTypeFromJSON(object.runnerType) : 0, head: isSet(object.head) ? Commit.fromJSON(object.head) : undefined, + policies: Array.isArray(object?.policies) ? object.policies.map((e: any) => Policy.fromJSON(e)) : [], }; }, @@ -320,6 +350,11 @@ export const Attestation = { message.runnerUrl !== undefined && (obj.runnerUrl = message.runnerUrl); message.runnerType !== undefined && (obj.runnerType = craftingSchema_Runner_RunnerTypeToJSON(message.runnerType)); message.head !== undefined && (obj.head = message.head ? Commit.toJSON(message.head) : undefined); + if (message.policies) { + obj.policies = message.policies.map((e) => e ? Policy.toJSON(e) : undefined); + } else { + obj.policies = []; + } return obj; }, @@ -361,6 +396,7 @@ export const Attestation = { message.runnerUrl = object.runnerUrl ?? ""; message.runnerType = object.runnerType ?? 0; message.head = (object.head !== undefined && object.head !== null) ? Commit.fromPartial(object.head) : undefined; + message.policies = object.policies?.map((e) => Policy.fromPartial(e)) || []; return message; }, }; @@ -1133,6 +1169,170 @@ export const Attestation_EnvVarsEntry = { }, }; +function createBasePolicy(): Policy { + return { attachment: undefined, body: "", violations: [] }; +} + +export const Policy = { + encode(message: Policy, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.attachment !== undefined) { + PolicyAttachment.encode(message.attachment, writer.uint32(10).fork()).ldelim(); + } + if (message.body !== "") { + writer.uint32(18).string(message.body); + } + for (const v of message.violations) { + Policy_Violation.encode(v!, writer.uint32(26).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Policy { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicy(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.attachment = PolicyAttachment.decode(reader, reader.uint32()); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.body = reader.string(); + continue; + case 3: + if (tag !== 26) { + break; + } + + message.violations.push(Policy_Violation.decode(reader, reader.uint32())); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Policy { + return { + attachment: isSet(object.attachment) ? PolicyAttachment.fromJSON(object.attachment) : undefined, + body: isSet(object.body) ? String(object.body) : "", + violations: Array.isArray(object?.violations) + ? object.violations.map((e: any) => Policy_Violation.fromJSON(e)) + : [], + }; + }, + + toJSON(message: Policy): unknown { + const obj: any = {}; + message.attachment !== undefined && + (obj.attachment = message.attachment ? PolicyAttachment.toJSON(message.attachment) : undefined); + message.body !== undefined && (obj.body = message.body); + if (message.violations) { + obj.violations = message.violations.map((e) => e ? Policy_Violation.toJSON(e) : undefined); + } else { + obj.violations = []; + } + return obj; + }, + + create, I>>(base?: I): Policy { + return Policy.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Policy { + const message = createBasePolicy(); + message.attachment = (object.attachment !== undefined && object.attachment !== null) + ? PolicyAttachment.fromPartial(object.attachment) + : undefined; + message.body = object.body ?? ""; + message.violations = object.violations?.map((e) => Policy_Violation.fromPartial(e)) || []; + return message; + }, +}; + +function createBasePolicy_Violation(): Policy_Violation { + return { subject: "", message: "" }; +} + +export const Policy_Violation = { + encode(message: Policy_Violation, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.subject !== "") { + writer.uint32(10).string(message.subject); + } + if (message.message !== "") { + writer.uint32(18).string(message.message); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Policy_Violation { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicy_Violation(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.subject = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.message = reader.string(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Policy_Violation { + return { + subject: isSet(object.subject) ? String(object.subject) : "", + message: isSet(object.message) ? String(object.message) : "", + }; + }, + + toJSON(message: Policy_Violation): unknown { + const obj: any = {}; + message.subject !== undefined && (obj.subject = message.subject); + message.message !== undefined && (obj.message = message.message); + return obj; + }, + + create, I>>(base?: I): Policy_Violation { + return Policy_Violation.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Policy_Violation { + const message = createBasePolicy_Violation(); + message.subject = object.subject ?? ""; + message.message = object.message ?? ""; + return message; + }, +}; + function createBaseCommit(): Commit { return { hash: "", authorEmail: "", authorName: "", message: "", date: undefined, remotes: [] }; } diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go index e0bbc9268..e321d56e4 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go @@ -55,6 +55,8 @@ type Attestation struct { RunnerType v1.CraftingSchema_Runner_RunnerType `protobuf:"varint,8,opt,name=runner_type,json=runnerType,proto3,enum=workflowcontract.v1.CraftingSchema_Runner_RunnerType" json:"runner_type,omitempty"` // Head Commit of the environment where the attestation was executed (optional) Head *Commit `protobuf:"bytes,9,opt,name=head,proto3" json:"head,omitempty"` + // Policies that this attestation was validated against + Policies []*Policy `protobuf:"bytes,10,rep,name=policies,proto3" json:"policies,omitempty"` } func (x *Attestation) Reset() { @@ -152,6 +154,80 @@ func (x *Attestation) GetHead() *Commit { return nil } +func (x *Attestation) GetPolicies() []*Policy { + if x != nil { + return x.Policies + } + return nil +} + +// A policy executed against an attestation +type Policy struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The attachment as in the contract, with arguments and any other metadata + Attachment *v1.PolicyAttachment `protobuf:"bytes,1,opt,name=attachment,proto3" json:"attachment,omitempty"` + // The policy script body (rego) + Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` + // The policy violations, if any + Violations []*Policy_Violation `protobuf:"bytes,3,rep,name=violations,proto3" json:"violations,omitempty"` +} + +func (x *Policy) Reset() { + *x = Policy{} + if protoimpl.UnsafeEnabled { + mi := &file_attestation_v1_crafting_state_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy) ProtoMessage() {} + +func (x *Policy) ProtoReflect() protoreflect.Message { + mi := &file_attestation_v1_crafting_state_proto_msgTypes[1] + 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 Policy.ProtoReflect.Descriptor instead. +func (*Policy) Descriptor() ([]byte, []int) { + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{1} +} + +func (x *Policy) GetAttachment() *v1.PolicyAttachment { + if x != nil { + return x.Attachment + } + return nil +} + +func (x *Policy) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + +func (x *Policy) GetViolations() []*Policy_Violation { + if x != nil { + return x.Violations + } + return nil +} + type Commit struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -168,7 +244,7 @@ type Commit struct { func (x *Commit) Reset() { *x = Commit{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[1] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -181,7 +257,7 @@ func (x *Commit) String() string { func (*Commit) ProtoMessage() {} func (x *Commit) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[1] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -194,7 +270,7 @@ func (x *Commit) ProtoReflect() protoreflect.Message { // Deprecated: Use Commit.ProtoReflect.Descriptor instead. func (*Commit) Descriptor() ([]byte, []int) { - return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{1} + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{2} } func (x *Commit) GetHash() string { @@ -253,7 +329,7 @@ type CraftingState struct { func (x *CraftingState) Reset() { *x = CraftingState{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[2] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -266,7 +342,7 @@ func (x *CraftingState) String() string { func (*CraftingState) ProtoMessage() {} func (x *CraftingState) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[2] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -279,7 +355,7 @@ func (x *CraftingState) ProtoReflect() protoreflect.Message { // Deprecated: Use CraftingState.ProtoReflect.Descriptor instead. func (*CraftingState) Descriptor() ([]byte, []int) { - return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{2} + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{3} } func (x *CraftingState) GetInputSchema() *v1.CraftingSchema { @@ -321,7 +397,7 @@ type WorkflowMetadata struct { func (x *WorkflowMetadata) Reset() { *x = WorkflowMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[3] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -334,7 +410,7 @@ func (x *WorkflowMetadata) String() string { func (*WorkflowMetadata) ProtoMessage() {} func (x *WorkflowMetadata) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[3] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -347,7 +423,7 @@ func (x *WorkflowMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use WorkflowMetadata.ProtoReflect.Descriptor instead. func (*WorkflowMetadata) Descriptor() ([]byte, []int) { - return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{3} + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{4} } func (x *WorkflowMetadata) GetName() string { @@ -424,7 +500,7 @@ type Attestation_Material struct { func (x *Attestation_Material) Reset() { *x = Attestation_Material{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[6] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -437,7 +513,7 @@ func (x *Attestation_Material) String() string { func (*Attestation_Material) ProtoMessage() {} func (x *Attestation_Material) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[6] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -550,7 +626,7 @@ type Attestation_Material_KeyVal struct { func (x *Attestation_Material_KeyVal) Reset() { *x = Attestation_Material_KeyVal{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[9] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -563,7 +639,7 @@ func (x *Attestation_Material_KeyVal) String() string { func (*Attestation_Material_KeyVal) ProtoMessage() {} func (x *Attestation_Material_KeyVal) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[9] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -609,7 +685,7 @@ type Attestation_Material_ContainerImage struct { func (x *Attestation_Material_ContainerImage) Reset() { *x = Attestation_Material_ContainerImage{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[10] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -622,7 +698,7 @@ func (x *Attestation_Material_ContainerImage) String() string { func (*Attestation_Material_ContainerImage) ProtoMessage() {} func (x *Attestation_Material_ContainerImage) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[10] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -694,7 +770,7 @@ type Attestation_Material_Artifact struct { func (x *Attestation_Material_Artifact) Reset() { *x = Attestation_Material_Artifact{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[11] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -707,7 +783,7 @@ func (x *Attestation_Material_Artifact) String() string { func (*Attestation_Material_Artifact) ProtoMessage() {} func (x *Attestation_Material_Artifact) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[11] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -758,6 +834,61 @@ func (x *Attestation_Material_Artifact) GetContent() []byte { return nil } +type Policy_Violation struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Subject string `protobuf:"bytes,1,opt,name=subject,proto3" json:"subject,omitempty"` + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *Policy_Violation) Reset() { + *x = Policy_Violation{} + if protoimpl.UnsafeEnabled { + mi := &file_attestation_v1_crafting_state_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy_Violation) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy_Violation) ProtoMessage() {} + +func (x *Policy_Violation) ProtoReflect() protoreflect.Message { + mi := &file_attestation_v1_crafting_state_proto_msgTypes[13] + 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 Policy_Violation.ProtoReflect.Descriptor instead. +func (*Policy_Violation) Descriptor() ([]byte, []int) { + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *Policy_Violation) GetSubject() string { + if x != nil { + return x.Subject + } + return "" +} + +func (x *Policy_Violation) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + type Commit_Remote struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -770,7 +901,7 @@ type Commit_Remote struct { func (x *Commit_Remote) Reset() { *x = Commit_Remote{} if protoimpl.UnsafeEnabled { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[12] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -783,7 +914,7 @@ func (x *Commit_Remote) String() string { func (*Commit_Remote) ProtoMessage() {} func (x *Commit_Remote) ProtoReflect() protoreflect.Message { - mi := &file_attestation_v1_crafting_state_proto_msgTypes[12] + mi := &file_attestation_v1_crafting_state_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -796,7 +927,7 @@ func (x *Commit_Remote) ProtoReflect() protoreflect.Message { // Deprecated: Use Commit_Remote.ProtoReflect.Descriptor instead. func (*Commit_Remote) Descriptor() ([]byte, []int) { - return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{1, 0} + return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{2, 0} } func (x *Commit_Remote) GetName() string { @@ -825,8 +956,8 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd0, - 0x0e, 0x0a, 0x0b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, + 0x67, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x84, + 0x0f, 0x0a, 0x0b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, @@ -864,140 +995,159 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x1a, 0x62, 0x0a, 0x0e, - 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x12, 0x32, 0x0a, 0x08, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, + 0x1a, 0x62, 0x0a, 0x0e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 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, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 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, 0x1a, 0x82, 0x08, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, + 0x6c, 0x12, 0x45, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, + 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x48, 0x00, + 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x5e, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, + 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, + 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, + 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x61, + 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x07, 0x61, 0x64, 0x64, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5e, 0x0a, 0x0d, + 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 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, 0x52, 0x0c, + 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, + 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x61, 0x73, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x54, + 0x6f, 0x43, 0x61, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, + 0x61, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, + 0x43, 0x61, 0x73, 0x12, 0x65, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, + 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, + 0x0c, 0xba, 0x48, 0x09, 0x9a, 0x01, 0x06, 0x2a, 0x04, 0x72, 0x02, 0x10, 0x01, 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, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x24, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, - 0x65, 0x72, 0x69, 0x61, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, - 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, - 0x1a, 0x82, 0x08, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x45, 0x0a, - 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x73, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x12, 0x5e, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, - 0x69, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, - 0x6d, 0x61, 0x67, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, 0x72, 0x74, - 0x69, 0x66, 0x61, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x12, 0x35, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x07, 0x61, 0x64, 0x64, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5e, 0x0a, 0x0d, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 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, 0x52, 0x0c, 0x6d, 0x61, 0x74, 0x65, - 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x54, 0x6f, 0x43, 0x61, 0x73, - 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x61, 0x73, 0x12, - 0x65, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x09, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x0c, 0xba, 0x48, 0x09, - 0x9a, 0x01, 0x06, 0x2a, 0x04, 0x72, 0x02, 0x10, 0x01, 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, 0x1a, 0x40, 0x0a, 0x06, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, - 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, - 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x98, 0x01, 0x0a, 0x0e, 0x43, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, - 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, - 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x74, 0x61, 0x67, 0x1a, 0x9a, 0x01, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x42, 0x03, 0x0a, 0x01, 0x6d, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, 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, 0xc9, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, - 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x21, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, - 0x0a, 0x0d, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, - 0x46, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, - 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, - 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, - 0x8e, 0x02, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x65, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, - 0x28, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, - 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, - 0x64, 0x12, 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x54, 0x5a, 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, - 0x74, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 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, 0x40, 0x0a, 0x06, 0x4b, 0x65, + 0x79, 0x56, 0x61, 0x6c, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x98, 0x01, 0x0a, + 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, + 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x1a, 0x9a, 0x01, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, + 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, + 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x6e, 0x74, 0x42, 0x03, 0x0a, 0x01, 0x6d, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, + 0x56, 0x61, 0x72, 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, 0xf6, 0x01, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 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, 0x42, 0x06, 0xba, 0x48, 0x03, + 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, + 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x76, + 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3f, 0x0a, + 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, + 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, + 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, + 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, + 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, + 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, + 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, + 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, + 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1012,51 +1162,57 @@ func file_attestation_v1_crafting_state_proto_rawDescGZIP() []byte { return file_attestation_v1_crafting_state_proto_rawDescData } -var file_attestation_v1_crafting_state_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_attestation_v1_crafting_state_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_attestation_v1_crafting_state_proto_goTypes = []interface{}{ (*Attestation)(nil), // 0: attestation.v1.Attestation - (*Commit)(nil), // 1: attestation.v1.Commit - (*CraftingState)(nil), // 2: attestation.v1.CraftingState - (*WorkflowMetadata)(nil), // 3: attestation.v1.WorkflowMetadata - nil, // 4: attestation.v1.Attestation.MaterialsEntry - nil, // 5: attestation.v1.Attestation.AnnotationsEntry - (*Attestation_Material)(nil), // 6: attestation.v1.Attestation.Material - nil, // 7: attestation.v1.Attestation.EnvVarsEntry - nil, // 8: attestation.v1.Attestation.Material.AnnotationsEntry - (*Attestation_Material_KeyVal)(nil), // 9: attestation.v1.Attestation.Material.KeyVal - (*Attestation_Material_ContainerImage)(nil), // 10: attestation.v1.Attestation.Material.ContainerImage - (*Attestation_Material_Artifact)(nil), // 11: attestation.v1.Attestation.Material.Artifact - (*Commit_Remote)(nil), // 12: attestation.v1.Commit.Remote - (*timestamppb.Timestamp)(nil), // 13: google.protobuf.Timestamp - (v1.CraftingSchema_Runner_RunnerType)(0), // 14: workflowcontract.v1.CraftingSchema.Runner.RunnerType - (*v1.CraftingSchema)(nil), // 15: workflowcontract.v1.CraftingSchema - (v1.CraftingSchema_Material_MaterialType)(0), // 16: workflowcontract.v1.CraftingSchema.Material.MaterialType + (*Policy)(nil), // 1: attestation.v1.Policy + (*Commit)(nil), // 2: attestation.v1.Commit + (*CraftingState)(nil), // 3: attestation.v1.CraftingState + (*WorkflowMetadata)(nil), // 4: attestation.v1.WorkflowMetadata + nil, // 5: attestation.v1.Attestation.MaterialsEntry + nil, // 6: attestation.v1.Attestation.AnnotationsEntry + (*Attestation_Material)(nil), // 7: attestation.v1.Attestation.Material + nil, // 8: attestation.v1.Attestation.EnvVarsEntry + nil, // 9: attestation.v1.Attestation.Material.AnnotationsEntry + (*Attestation_Material_KeyVal)(nil), // 10: attestation.v1.Attestation.Material.KeyVal + (*Attestation_Material_ContainerImage)(nil), // 11: attestation.v1.Attestation.Material.ContainerImage + (*Attestation_Material_Artifact)(nil), // 12: attestation.v1.Attestation.Material.Artifact + (*Policy_Violation)(nil), // 13: attestation.v1.Policy.Violation + (*Commit_Remote)(nil), // 14: attestation.v1.Commit.Remote + (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp + (v1.CraftingSchema_Runner_RunnerType)(0), // 16: workflowcontract.v1.CraftingSchema.Runner.RunnerType + (*v1.PolicyAttachment)(nil), // 17: workflowcontract.v1.PolicyAttachment + (*v1.CraftingSchema)(nil), // 18: workflowcontract.v1.CraftingSchema + (v1.CraftingSchema_Material_MaterialType)(0), // 19: workflowcontract.v1.CraftingSchema.Material.MaterialType } var file_attestation_v1_crafting_state_proto_depIdxs = []int32{ - 13, // 0: attestation.v1.Attestation.initialized_at:type_name -> google.protobuf.Timestamp - 13, // 1: attestation.v1.Attestation.finished_at:type_name -> google.protobuf.Timestamp - 3, // 2: attestation.v1.Attestation.workflow:type_name -> attestation.v1.WorkflowMetadata - 4, // 3: attestation.v1.Attestation.materials:type_name -> attestation.v1.Attestation.MaterialsEntry - 5, // 4: attestation.v1.Attestation.annotations:type_name -> attestation.v1.Attestation.AnnotationsEntry - 7, // 5: attestation.v1.Attestation.env_vars:type_name -> attestation.v1.Attestation.EnvVarsEntry - 14, // 6: attestation.v1.Attestation.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 1, // 7: attestation.v1.Attestation.head:type_name -> attestation.v1.Commit - 13, // 8: attestation.v1.Commit.date:type_name -> google.protobuf.Timestamp - 12, // 9: attestation.v1.Commit.remotes:type_name -> attestation.v1.Commit.Remote - 15, // 10: attestation.v1.CraftingState.input_schema:type_name -> workflowcontract.v1.CraftingSchema - 0, // 11: attestation.v1.CraftingState.attestation:type_name -> attestation.v1.Attestation - 6, // 12: attestation.v1.Attestation.MaterialsEntry.value:type_name -> attestation.v1.Attestation.Material - 9, // 13: attestation.v1.Attestation.Material.string:type_name -> attestation.v1.Attestation.Material.KeyVal - 10, // 14: attestation.v1.Attestation.Material.container_image:type_name -> attestation.v1.Attestation.Material.ContainerImage - 11, // 15: attestation.v1.Attestation.Material.artifact:type_name -> attestation.v1.Attestation.Material.Artifact - 13, // 16: attestation.v1.Attestation.Material.added_at:type_name -> google.protobuf.Timestamp - 16, // 17: attestation.v1.Attestation.Material.material_type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 8, // 18: attestation.v1.Attestation.Material.annotations:type_name -> attestation.v1.Attestation.Material.AnnotationsEntry - 19, // [19:19] is the sub-list for method output_type - 19, // [19:19] is the sub-list for method input_type - 19, // [19:19] is the sub-list for extension type_name - 19, // [19:19] is the sub-list for extension extendee - 0, // [0:19] is the sub-list for field type_name + 15, // 0: attestation.v1.Attestation.initialized_at:type_name -> google.protobuf.Timestamp + 15, // 1: attestation.v1.Attestation.finished_at:type_name -> google.protobuf.Timestamp + 4, // 2: attestation.v1.Attestation.workflow:type_name -> attestation.v1.WorkflowMetadata + 5, // 3: attestation.v1.Attestation.materials:type_name -> attestation.v1.Attestation.MaterialsEntry + 6, // 4: attestation.v1.Attestation.annotations:type_name -> attestation.v1.Attestation.AnnotationsEntry + 8, // 5: attestation.v1.Attestation.env_vars:type_name -> attestation.v1.Attestation.EnvVarsEntry + 16, // 6: attestation.v1.Attestation.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 2, // 7: attestation.v1.Attestation.head:type_name -> attestation.v1.Commit + 1, // 8: attestation.v1.Attestation.policies:type_name -> attestation.v1.Policy + 17, // 9: attestation.v1.Policy.attachment:type_name -> workflowcontract.v1.PolicyAttachment + 13, // 10: attestation.v1.Policy.violations:type_name -> attestation.v1.Policy.Violation + 15, // 11: attestation.v1.Commit.date:type_name -> google.protobuf.Timestamp + 14, // 12: attestation.v1.Commit.remotes:type_name -> attestation.v1.Commit.Remote + 18, // 13: attestation.v1.CraftingState.input_schema:type_name -> workflowcontract.v1.CraftingSchema + 0, // 14: attestation.v1.CraftingState.attestation:type_name -> attestation.v1.Attestation + 7, // 15: attestation.v1.Attestation.MaterialsEntry.value:type_name -> attestation.v1.Attestation.Material + 10, // 16: attestation.v1.Attestation.Material.string:type_name -> attestation.v1.Attestation.Material.KeyVal + 11, // 17: attestation.v1.Attestation.Material.container_image:type_name -> attestation.v1.Attestation.Material.ContainerImage + 12, // 18: attestation.v1.Attestation.Material.artifact:type_name -> attestation.v1.Attestation.Material.Artifact + 15, // 19: attestation.v1.Attestation.Material.added_at:type_name -> google.protobuf.Timestamp + 19, // 20: attestation.v1.Attestation.Material.material_type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 9, // 21: attestation.v1.Attestation.Material.annotations:type_name -> attestation.v1.Attestation.Material.AnnotationsEntry + 22, // [22:22] is the sub-list for method output_type + 22, // [22:22] is the sub-list for method input_type + 22, // [22:22] is the sub-list for extension type_name + 22, // [22:22] is the sub-list for extension extendee + 0, // [0:22] is the sub-list for field type_name } func init() { file_attestation_v1_crafting_state_proto_init() } @@ -1078,7 +1234,7 @@ func file_attestation_v1_crafting_state_proto_init() { } } file_attestation_v1_crafting_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Commit); i { + switch v := v.(*Policy); i { case 0: return &v.state case 1: @@ -1090,7 +1246,7 @@ func file_attestation_v1_crafting_state_proto_init() { } } file_attestation_v1_crafting_state_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingState); i { + switch v := v.(*Commit); i { case 0: return &v.state case 1: @@ -1102,6 +1258,18 @@ func file_attestation_v1_crafting_state_proto_init() { } } file_attestation_v1_crafting_state_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CraftingState); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attestation_v1_crafting_state_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*WorkflowMetadata); i { case 0: return &v.state @@ -1113,7 +1281,7 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attestation_Material); i { case 0: return &v.state @@ -1125,7 +1293,7 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attestation_Material_KeyVal); i { case 0: return &v.state @@ -1137,7 +1305,7 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attestation_Material_ContainerImage); i { case 0: return &v.state @@ -1149,7 +1317,7 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Attestation_Material_Artifact); i { case 0: return &v.state @@ -1161,7 +1329,19 @@ func file_attestation_v1_crafting_state_proto_init() { return nil } } - file_attestation_v1_crafting_state_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_attestation_v1_crafting_state_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Policy_Violation); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_attestation_v1_crafting_state_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Commit_Remote); i { case 0: return &v.state @@ -1174,7 +1354,7 @@ func file_attestation_v1_crafting_state_proto_init() { } } } - file_attestation_v1_crafting_state_proto_msgTypes[6].OneofWrappers = []interface{}{ + file_attestation_v1_crafting_state_proto_msgTypes[7].OneofWrappers = []interface{}{ (*Attestation_Material_String_)(nil), (*Attestation_Material_ContainerImage_)(nil), (*Attestation_Material_Artifact_)(nil), @@ -1185,7 +1365,7 @@ func file_attestation_v1_crafting_state_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_attestation_v1_crafting_state_proto_rawDesc, NumEnums: 0, - NumMessages: 13, + NumMessages: 15, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto index b7f62566d..d22846a9a 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto @@ -88,6 +88,24 @@ message Attestation { // Head Commit of the environment where the attestation was executed (optional) Commit head = 9; + + // Policies that this attestation was validated against + repeated Policy policies = 10; +} + +// A policy executed against an attestation +message Policy { + // The attachment as in the contract, with arguments and any other metadata + workflowcontract.v1.PolicyAttachment attachment = 1 [(buf.validate.field).required = true]; + // The policy script body (rego) + string body = 2 [(buf.validate.field).required = true]; + // The policy violations, if any + repeated Violation violations = 3; + + message Violation { + string subject = 1; + string message = 2; + } } message Commit { From bb7d5bf2899dbf4fce971146da3351aefc344bbc Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 14:22:59 +0200 Subject: [PATCH 12/73] store attestation result Signed-off-by: Jose I. Paris --- .../frontend/attestation/v1/crafting_state.ts | 27 ++- .../api/attestation/v1/crafting_state.pb.go | 158 ++++++++++-------- .../api/attestation/v1/crafting_state.proto | 8 +- pkg/policies/policies.go | 18 ++ pkg/policies/policies_test.go | 31 ++++ 5 files changed, 159 insertions(+), 83 deletions(-) diff --git a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts index 193b6abf9..c8de72c81 100644 --- a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts +++ b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts @@ -102,6 +102,8 @@ export interface Attestation_EnvVarsEntry { /** A policy executed against an attestation */ export interface Policy { + /** The policy name from the policy spec */ + name: string; /** The attachment as in the contract, with arguments and any other metadata */ attachment?: PolicyAttachment; /** The policy script body (rego) */ @@ -1170,19 +1172,22 @@ export const Attestation_EnvVarsEntry = { }; function createBasePolicy(): Policy { - return { attachment: undefined, body: "", violations: [] }; + return { name: "", attachment: undefined, body: "", violations: [] }; } export const Policy = { encode(message: Policy, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.name !== "") { + writer.uint32(10).string(message.name); + } if (message.attachment !== undefined) { - PolicyAttachment.encode(message.attachment, writer.uint32(10).fork()).ldelim(); + PolicyAttachment.encode(message.attachment, writer.uint32(18).fork()).ldelim(); } if (message.body !== "") { - writer.uint32(18).string(message.body); + writer.uint32(26).string(message.body); } for (const v of message.violations) { - Policy_Violation.encode(v!, writer.uint32(26).fork()).ldelim(); + Policy_Violation.encode(v!, writer.uint32(34).fork()).ldelim(); } return writer; }, @@ -1199,20 +1204,27 @@ export const Policy = { break; } - message.attachment = PolicyAttachment.decode(reader, reader.uint32()); + message.name = reader.string(); continue; case 2: if (tag !== 18) { break; } - message.body = reader.string(); + message.attachment = PolicyAttachment.decode(reader, reader.uint32()); continue; case 3: if (tag !== 26) { break; } + message.body = reader.string(); + continue; + case 4: + if (tag !== 34) { + break; + } + message.violations.push(Policy_Violation.decode(reader, reader.uint32())); continue; } @@ -1226,6 +1238,7 @@ export const Policy = { fromJSON(object: any): Policy { return { + name: isSet(object.name) ? String(object.name) : "", attachment: isSet(object.attachment) ? PolicyAttachment.fromJSON(object.attachment) : undefined, body: isSet(object.body) ? String(object.body) : "", violations: Array.isArray(object?.violations) @@ -1236,6 +1249,7 @@ export const Policy = { toJSON(message: Policy): unknown { const obj: any = {}; + message.name !== undefined && (obj.name = message.name); message.attachment !== undefined && (obj.attachment = message.attachment ? PolicyAttachment.toJSON(message.attachment) : undefined); message.body !== undefined && (obj.body = message.body); @@ -1253,6 +1267,7 @@ export const Policy = { fromPartial, I>>(object: I): Policy { const message = createBasePolicy(); + message.name = object.name ?? ""; message.attachment = (object.attachment !== undefined && object.attachment !== null) ? PolicyAttachment.fromPartial(object.attachment) : undefined; diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go index e321d56e4..d4c12008b 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go @@ -167,12 +167,14 @@ type Policy struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // The policy name from the policy spec + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The attachment as in the contract, with arguments and any other metadata - Attachment *v1.PolicyAttachment `protobuf:"bytes,1,opt,name=attachment,proto3" json:"attachment,omitempty"` + Attachment *v1.PolicyAttachment `protobuf:"bytes,2,opt,name=attachment,proto3" json:"attachment,omitempty"` // The policy script body (rego) - Body string `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` + Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` // The policy violations, if any - Violations []*Policy_Violation `protobuf:"bytes,3,rep,name=violations,proto3" json:"violations,omitempty"` + Violations []*Policy_Violation `protobuf:"bytes,4,rep,name=violations,proto3" json:"violations,omitempty"` } func (x *Policy) Reset() { @@ -207,6 +209,13 @@ func (*Policy) Descriptor() ([]byte, []int) { return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{1} } +func (x *Policy) GetName() string { + if x != nil { + return x.Name + } + return "" +} + func (x *Policy) GetAttachment() *v1.PolicyAttachment { if x != nil { return x.Attachment @@ -1077,77 +1086,78 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x56, 0x61, 0x72, 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, 0xf6, 0x01, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x01, - 0x20, 0x01, 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, 0x42, 0x06, 0xba, 0x48, 0x03, - 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, - 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, - 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x76, - 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x3f, 0x0a, - 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, - 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, - 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, - 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, - 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, - 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, - 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, - 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x8a, 0x02, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 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, 0x42, + 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, + 0x40, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x1a, 0x3f, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, + 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x22, 0xc9, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, + 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, + 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, + 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, + 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, + 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, + 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, + 0x22, 0x8e, 0x02, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, + 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, + 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x42, 0x54, 0x5a, 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, + 0x66, 0x74, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto index d22846a9a..265aeb033 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto @@ -95,12 +95,14 @@ message Attestation { // A policy executed against an attestation message Policy { + // The policy name from the policy spec + string name = 1; // The attachment as in the contract, with arguments and any other metadata - workflowcontract.v1.PolicyAttachment attachment = 1 [(buf.validate.field).required = true]; + workflowcontract.v1.PolicyAttachment attachment = 2 [(buf.validate.field).required = true]; // The policy script body (rego) - string body = 2 [(buf.validate.field).required = true]; + string body = 3 [(buf.validate.field).required = true]; // The policy violations, if any - repeated Violation violations = 3; + repeated Violation violations = 4; message Violation { string subject = 1; diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index a3897405f..3a3b4fdab 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -69,6 +69,14 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation return nil, fmt.Errorf("failed to verify policy: %w", err) } violations = append(violations, res...) + + // Store result in the attestation itself (for the renderer to include them in the predicate) + pv.state.Attestation.Policies = append(pv.state.Attestation.Policies, &v12.Policy{ + Name: spec.Metadata.Name, + Attachment: policyAtt, + Body: string(script.Source), + Violations: policyViolationsToAttestationViolations(violations), + }) } return violations, nil @@ -157,3 +165,13 @@ func getPolicyEngine(_ *v1.Policy) engine.PolicyEngine { // Currently, only Rego is supported return new(rego.Rego) } + +func policyViolationsToAttestationViolations(violations []*engine.PolicyViolation) (pvs []*v12.Policy_Violation) { + for _, violation := range violations { + pvs = append(pvs, &v12.Policy_Violation{ + Subject: violation.Subject, + Message: violation.Violation, + }) + } + return +} diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 9439ccbe8..93e3092d7 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -110,6 +110,7 @@ func (s *testSuite) TestVerifyAttestations() { verifier := NewPolicyVerifier(tc.state, nil) res, err := verifier.Verify(context.TODO()) if tc.wantErr != nil { + // #nosec G601 s.ErrorAs(err, &tc.wantErr) return } @@ -121,6 +122,36 @@ func (s *testSuite) TestVerifyAttestations() { } } +func (s *testSuite) TestAttestationResult() { + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, + }, + } + + verifier := NewPolicyVerifier(state, nil) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Len(res, 0) + + att := state.GetAttestation() + s.Len(att.Policies, 1) + + p := att.Policies[0] + s.Len(p.Violations, 0) + s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) + s.Equal("workflow", p.Name) + s.Contains(p.Body, "package main") +} + type testSuite struct { suite.Suite } From ce470b1e33b566f8e14fa9030ef5a7ef442fd0b2 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 15:09:27 +0200 Subject: [PATCH 13/73] more testing and fixes Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 2 +- pkg/policies/policies_test.go | 151 +++++++++++++++++++++++---- pkg/policies/testdata/materials.rego | 26 +++++ pkg/policies/testdata/materials.yaml | 6 ++ 4 files changed, 162 insertions(+), 23 deletions(-) create mode 100644 pkg/policies/testdata/materials.rego create mode 100644 pkg/policies/testdata/materials.yaml diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 3a3b4fdab..2371c29d1 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -75,7 +75,7 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation Name: spec.Metadata.Name, Attachment: policyAtt, Body: string(script.Source), - Violations: policyViolationsToAttestationViolations(violations), + Violations: policyViolationsToAttestationViolations(res), }) } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 93e3092d7..ea84b7fa1 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -23,6 +23,7 @@ import ( v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/stretchr/testify/suite" + "golang.org/x/exp/slices" ) func (s *testSuite) TestVerifyAttestations() { @@ -123,33 +124,139 @@ func (s *testSuite) TestVerifyAttestations() { } func (s *testSuite) TestAttestationResult() { - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ - {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + s.Run("successful attestation", func() { + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + }, }, - }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, }, - RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, - }, - } + } - verifier := NewPolicyVerifier(state, nil) - res, err := verifier.Verify(context.TODO()) - s.Require().NoError(err) - s.Len(res, 0) + verifier := NewPolicyVerifier(state, nil) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Len(res, 0) - att := state.GetAttestation() - s.Len(att.Policies, 1) + att := state.GetAttestation() + s.Len(att.Policies, 1) - p := att.Policies[0] - s.Len(p.Violations, 0) - s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) - s.Equal("workflow", p.Name) - s.Contains(p.Body, "package main") + p := att.Policies[0] + s.Len(p.Violations, 0) + s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) + s.Equal("workflow", p.Name) + s.Contains(p.Body, "package main") + }) + + s.Run("failed attestation", func() { + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, + }, + } + + verifier := NewPolicyVerifier(state, nil) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Len(res, 1) + + att := state.GetAttestation() + s.Len(att.Policies, 1) + + p := att.Policies[0] + s.Len(p.Violations, 1) + s.Contains(p.Body, "package main") + v := p.Violations[0] + s.Equal(p.Name, v.Subject) + s.Equal("incorrect runner", v.Message) + }) + + s.Run("multiple successful policies", func() { + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, + Materials: map[string]*v1.Attestation_Material{ + "vex": { + MaterialType: v12.CraftingSchema_Material_OPENVEX, + }, + }, + }, + } + + verifier := NewPolicyVerifier(state, nil) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Len(res, 0) + att := state.GetAttestation() + s.Len(att.Policies, 2) + s.Len(att.Policies[0].Violations, 0) + s.Len(att.Policies[1].Violations, 0) + }) + + s.Run("partial success", func() { + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, + Materials: map[string]*v1.Attestation_Material{ + "vex": { + MaterialType: v12.CraftingSchema_Material_OPENVEX, + }, + }, + }, + } + + verifier := NewPolicyVerifier(state, nil) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Greater(len(res), 0) + att := state.GetAttestation() + s.Len(att.Policies, 2) + + // Check that only 1 policy failed + index := slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { + return p.Name == "workflow" + }) + p := att.Policies[index] + s.Len(p.Violations, 1) + + index = slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { + return p.Name == "materials" + }) + p = att.Policies[index] + s.Len(p.Violations, 0) + }) } type testSuite struct { diff --git a/pkg/policies/testdata/materials.rego b/pkg/policies/testdata/materials.rego new file mode 100644 index 000000000..a31b6d1c3 --- /dev/null +++ b/pkg/policies/testdata/materials.rego @@ -0,0 +1,26 @@ +package main + +import future.keywords.in +import future.keywords.contains + +# Verifies there is a VEX material, even if not enforced by contract + +deny[msg] { + not has_vex + + msg := "missing VEX material" +} + +# Collect all material types +kinds contains kind { + some material in input.materials + kind := material.materialType +} + +has_vex { + "CSAF_VEX" in kinds +} + +has_vex { + "OPENVEX" in kinds +} diff --git a/pkg/policies/testdata/materials.yaml b/pkg/policies/testdata/materials.yaml new file mode 100644 index 000000000..15a851a8d --- /dev/null +++ b/pkg/policies/testdata/materials.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: materials +spec: + path: testdata/materials.rego From 99ad1325e929daae8c119fee5ee6b075bd2a7a20 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 15:10:12 +0200 Subject: [PATCH 14/73] do not integrate yet Signed-off-by: Jose I. Paris --- app/cli/internal/action/attestation_push.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index c9ef51ec0..a9b9dddf6 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -18,7 +18,6 @@ package action import ( "context" "encoding/json" - "errors" "fmt" "time" @@ -26,7 +25,6 @@ import ( "github.com/chainloop-dev/chainloop/internal/attestation/crafter" "github.com/chainloop-dev/chainloop/internal/attestation/renderer" "github.com/chainloop-dev/chainloop/internal/attestation/signer" - "github.com/chainloop-dev/chainloop/pkg/policies" "github.com/secure-systems-lab/go-securesystemslib/dsse" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/timestamppb" @@ -146,21 +144,6 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru return nil, fmt.Errorf("creating signer: %w", err) } - // Apply policies - pv := policies.NewPolicyVerifier(action.c.CraftingState, nil) - violations, err := pv.Verify(ctx) - if err != nil { - return nil, fmt.Errorf("verifying policies: %w", err) - } - - // TODO. Add policy results to crafting state - if len(violations) > 0 { - for _, v := range violations { - action.Logger.Error().Msgf("policy violation [%s]: %s", v.Subject, v.Violation) - } - return nil, errors.New("violations verifying policies") - } - renderer, err := renderer.NewAttestationRenderer(action.c.CraftingState, action.cliVersion, action.cliDigest, sig, renderer.WithLogger(action.Logger), renderer.WithBundleOutputPath(action.bundlePath)) if err != nil { From 7871e539d2f63a0291131e05d4576740fdfe3dff Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 15:14:38 +0200 Subject: [PATCH 15/73] some comments Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 2371c29d1..d2f20a388 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -138,7 +138,7 @@ func (pv *PolicyVerifier) loadSubject(attachment *v1.PolicyAttachment, spec *v1. if m.GetArtifact().GetName() == name { if spec.GetSpec().GetKind() != v1.CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED && spec.GetSpec().GetKind() != m.GetMaterialType() { // If policy wasn't meant to be evaluated against this type of material, raise an error - return nil, fmt.Errorf("invalid material type: %s, policy spected: %s", m.GetMaterialType(), spec.GetSpec().GetKind()) + return nil, fmt.Errorf("invalid material type: %s, policy expected: %s", m.GetMaterialType(), spec.GetSpec().GetKind()) } return pv.getMaterialPayload(m) } @@ -152,10 +152,8 @@ func (pv *PolicyVerifier) getMaterialPayload(m *v12.Attestation_Material) ([]byt if !m.UploadedToCas { return m.GetArtifact().GetContent(), nil } - // Look for material, and get its payload depending on which its nature. - // switch m.MaterialType { - // case v1.CraftingSchema_Mate - // } + + // TODO: Use the CAS to look for the material,. return nil, nil } From 95c90a8ed3dcc747abccd52f6628716f09a5b124 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 16:48:57 +0200 Subject: [PATCH 16/73] test inline materials Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 6 +- pkg/policies/policies_test.go | 46 + pkg/policies/testdata/sbom-spdx.json | 1874 ++++++++++++++++++++++++++ pkg/policies/testdata/sbom_syft.rego | 14 + pkg/policies/testdata/sbom_syft.yaml | 6 + 5 files changed, 1943 insertions(+), 3 deletions(-) create mode 100644 pkg/policies/testdata/sbom-spdx.json create mode 100644 pkg/policies/testdata/sbom_syft.rego create mode 100644 pkg/policies/testdata/sbom_syft.yaml diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index d2f20a388..efa4aacfa 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -134,8 +134,8 @@ func (pv *PolicyVerifier) loadSubject(attachment *v1.PolicyAttachment, spec *v1. } // if name is set, we want a specific material - for _, m := range state.GetAttestation().GetMaterials() { - if m.GetArtifact().GetName() == name { + for k, m := range state.GetAttestation().GetMaterials() { + if k == name { if spec.GetSpec().GetKind() != v1.CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED && spec.GetSpec().GetKind() != m.GetMaterialType() { // If policy wasn't meant to be evaluated against this type of material, raise an error return nil, fmt.Errorf("invalid material type: %s, policy expected: %s", m.GetMaterialType(), spec.GetSpec().GetKind()) @@ -149,7 +149,7 @@ func (pv *PolicyVerifier) loadSubject(attachment *v1.PolicyAttachment, spec *v1. // Gets the material payload from the CAS func (pv *PolicyVerifier) getMaterialPayload(m *v12.Attestation_Material) ([]byte, error) { - if !m.UploadedToCas { + if m.InlineCas { return m.GetArtifact().GetContent(), nil } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index ea84b7fa1..17ceac115 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -18,6 +18,7 @@ package policies import ( "context" "io/fs" + "os" "testing" v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" @@ -259,6 +260,51 @@ func (s *testSuite) TestAttestationResult() { }) } +func (s *testSuite) TestInlineMaterial() { + content, err := os.ReadFile("testdata/sbom-spdx.json") + s.Require().NoError(err) + + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Materials: []*v12.CraftingSchema_Material{ + { + Name: "sbom", + Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + }, + }, + Policies: []*v12.PolicyAttachment{ + { + Selector: &v12.PolicyAttachment_MaterialSelector{Name: "sbom"}, + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, + }, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + Materials: map[string]*v1.Attestation_Material{ + "sbom": { + MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ + Content: content, + }, + }, + InlineCas: true, + }, + }, + }, + } + verifier := NewPolicyVerifier(state, nil) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Len(res, 0) + + att := state.GetAttestation() + s.Len(att.Policies, 1) + s.Len(att.Policies[0].Violations, 0) +} + type testSuite struct { suite.Suite } diff --git a/pkg/policies/testdata/sbom-spdx.json b/pkg/policies/testdata/sbom-spdx.json new file mode 100644 index 000000000..1f001e97a --- /dev/null +++ b/pkg/policies/testdata/sbom-spdx.json @@ -0,0 +1,1874 @@ +{ + "spdxVersion": "SPDX-2.3", + "dataLicense": "CC0-1.0", + "SPDXID": "SPDXRef-DOCUMENT", + "name": ".", + "documentNamespace": "https://anchore.com/syft/dir/5d82480d-1f44-4351-b216-24880a877ce4", + "creationInfo": { + "licenseListVersion": "3.20", + "creators": [ + "Organization: Anchore, Inc", + "Tool: syft-0.73.0" + ], + "created": "2023-02-25T15:16:03Z" + }, + "packages": [ + { + "name": "@algolia/autocomplete-core", + "SPDXID": "SPDXRef-Package-npm--algolia-autocomplete-core-d4f529d2efd5d873", + "versionInfo": "1.7.4", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-core:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-core:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_core:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_core:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/autocomplete-core@1.7.4" + } + ] + }, + { + "name": "@algolia/autocomplete-core", + "SPDXID": "SPDXRef-Package-npm--algolia-autocomplete-core-a75e9cc60748602d", + "versionInfo": "1.7.4", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-core:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-core:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_core:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_core:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete-core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete_core:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/autocomplete-core@1.7.4" + } + ] + }, + { + "name": "@algolia/autocomplete-preset-algolia", + "SPDXID": "SPDXRef-Package-npm--algolia-autocomplete-preset-algolia-2efe8108bf5904fb", + "versionInfo": "1.7.4", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset-algolia:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset-algolia:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset_algolia:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset_algolia:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/autocomplete-preset-algolia@1.7.4" + } + ] + }, + { + "name": "@algolia/autocomplete-preset-algolia", + "SPDXID": "SPDXRef-Package-npm--algolia-autocomplete-preset-algolia-719fbc0a971c8423", + "versionInfo": "1.7.4", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset-algolia:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset-algolia:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset_algolia:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset_algolia:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-preset:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_preset:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete-preset-algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete_preset_algolia:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/autocomplete-preset-algolia@1.7.4" + } + ] + }, + { + "name": "@algolia/autocomplete-shared", + "SPDXID": "SPDXRef-Package-npm--algolia-autocomplete-shared-c04c8898a671ed16", + "versionInfo": "1.7.4", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-shared:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-shared:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_shared:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_shared:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/autocomplete-shared@1.7.4" + } + ] + }, + { + "name": "@algolia/autocomplete-shared", + "SPDXID": "SPDXRef-Package-npm--algolia-autocomplete-shared-349e9c24c2b4f2c5", + "versionInfo": "1.7.4", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-shared:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete-shared:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_shared:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete_shared:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/autocomplete:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete-shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/autocomplete_shared:1.7.4:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/autocomplete-shared@1.7.4" + } + ] + }, + { + "name": "@algolia/cache-browser-local-storage", + "SPDXID": "SPDXRef-Package-npm--algolia-cache-browser-local-storage-7f047bcfa53ed7ee", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local-storage:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local-storage:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local_storage:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local_storage:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/cache-browser-local-storage@4.14.3" + } + ] + }, + { + "name": "@algolia/cache-browser-local-storage", + "SPDXID": "SPDXRef-Package-npm--algolia-cache-browser-local-storage-699118b8ecb40e29", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local-storage:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local-storage:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local_storage:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local_storage:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser-local:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser_local:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-browser:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_browser:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache-browser-local-storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache_browser_local_storage:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/cache-browser-local-storage@4.14.3" + } + ] + }, + { + "name": "@algolia/cache-common", + "SPDXID": "SPDXRef-Package-npm--algolia-cache-common-b83a20f4252c841a", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-common:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-common:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_common:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_common:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/cache-common@4.14.3" + } + ] + }, + { + "name": "@algolia/cache-common", + "SPDXID": "SPDXRef-Package-npm--algolia-cache-common-8feb5c8eb82329a3", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-common:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-common:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_common:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_common:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/cache-common@4.14.3" + } + ] + }, + { + "name": "@algolia/cache-in-memory", + "SPDXID": "SPDXRef-Package-npm--algolia-cache-in-memory-5b4709d3757a3a6d", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in-memory:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in-memory:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in_memory:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in_memory:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/cache-in-memory@4.14.3" + } + ] + }, + { + "name": "@algolia/cache-in-memory", + "SPDXID": "SPDXRef-Package-npm--algolia-cache-in-memory-a4bf58feef42f315", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in-memory:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in-memory:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in_memory:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in_memory:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache-in:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache_in:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/cache:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache-in-memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/cache_in_memory:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/cache-in-memory@4.14.3" + } + ] + }, + { + "name": "@algolia/client-account", + "SPDXID": "SPDXRef-Package-npm--algolia-client-account-ccad52fb07b66b08", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-account:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-account:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_account:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_account:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-account@4.14.3" + } + ] + }, + { + "name": "@algolia/client-account", + "SPDXID": "SPDXRef-Package-npm--algolia-client-account-dcac7f21f13a1b6", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-account:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-account:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_account:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_account:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_account:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-account@4.14.3" + } + ] + }, + { + "name": "@algolia/client-analytics", + "SPDXID": "SPDXRef-Package-npm--algolia-client-analytics-da8f8d5e4a42283c", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-analytics:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-analytics:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_analytics:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_analytics:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-analytics@4.14.3" + } + ] + }, + { + "name": "@algolia/client-analytics", + "SPDXID": "SPDXRef-Package-npm--algolia-client-analytics-7aa06ac329e132f6", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-analytics:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-analytics:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_analytics:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_analytics:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_analytics:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-analytics@4.14.3" + } + ] + }, + { + "name": "@algolia/client-common", + "SPDXID": "SPDXRef-Package-npm--algolia-client-common-fdab2e146ab09cb0", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-common:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-common:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_common:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_common:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-common@4.14.3" + } + ] + }, + { + "name": "@algolia/client-common", + "SPDXID": "SPDXRef-Package-npm--algolia-client-common-1e82fe4ac5f06142", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-common:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-common:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_common:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_common:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-common@4.14.3" + } + ] + }, + { + "name": "@algolia/client-personalization", + "SPDXID": "SPDXRef-Package-npm--algolia-client-personalization-5860c568f6a2884b", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-personalization:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-personalization:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_personalization:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_personalization:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-personalization@4.14.3" + } + ] + }, + { + "name": "@algolia/client-personalization", + "SPDXID": "SPDXRef-Package-npm--algolia-client-personalization-5230f032c64636a3", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-personalization:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-personalization:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_personalization:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_personalization:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_personalization:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-personalization@4.14.3" + } + ] + }, + { + "name": "@algolia/client-search", + "SPDXID": "SPDXRef-Package-npm--algolia-client-search-dd73cb953fef8932", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-search:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-search:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_search:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_search:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-search@4.14.3" + } + ] + }, + { + "name": "@algolia/client-search", + "SPDXID": "SPDXRef-Package-npm--algolia-client-search-a19e56cf638775e2", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-search:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client-search:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_search:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client_search:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/client:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client-search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/client_search:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/client-search@4.14.3" + } + ] + }, + { + "name": "@algolia/events", + "SPDXID": "SPDXRef-Package-npm--algolia-events-5f312ad698b9cd07", + "versionInfo": "4.0.1", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/events:\\@algolia\\/events:4.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/events:4.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/events@4.0.1" + } + ] + }, + { + "name": "@algolia/events", + "SPDXID": "SPDXRef-Package-npm--algolia-events-4f529c22422af8a", + "versionInfo": "4.0.1", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/events:\\@algolia\\/events:4.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/events:4.0.1:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/events@4.0.1" + } + ] + }, + { + "name": "@algolia/logger-common", + "SPDXID": "SPDXRef-Package-npm--algolia-logger-common-4beb0a564e01e8dd", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-common:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-common:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_common:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_common:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/logger-common@4.14.3" + } + ] + }, + { + "name": "@algolia/logger-common", + "SPDXID": "SPDXRef-Package-npm--algolia-logger-common-b5611c2c52827c17", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-common:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-common:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_common:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_common:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger-common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger_common:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/logger-common@4.14.3" + } + ] + }, + { + "name": "@algolia/logger-console", + "SPDXID": "SPDXRef-Package-npm--algolia-logger-console-7d44d092b7346496", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-console:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-console:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_console:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_console:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/logger-console@4.14.3" + } + ] + }, + { + "name": "@algolia/logger-console", + "SPDXID": "SPDXRef-Package-npm--algolia-logger-console-bd05c3862ee5c855", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-console:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger-console:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_console:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger_console:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/logger:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger-console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/logger_console:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/logger-console@4.14.3" + } + ] + }, + { + "name": "@algolia/requester-browser-xhr", + "SPDXID": "SPDXRef-Package-npm--algolia-requester-browser-xhr-2547173fb30f7bf4", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: package-lock.json", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser-xhr:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser-xhr:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser_xhr:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser_xhr:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/requester-browser-xhr@4.14.3" + } + ] + }, + { + "name": "@algolia/requester-browser-xhr", + "SPDXID": "SPDXRef-Package-npm--algolia-requester-browser-xhr-afdcaeba77bd9241", + "versionInfo": "4.14.3", + "downloadLocation": "NOASSERTION", + "sourceInfo": "acquired package info from installed node module manifest file: yarn.lock", + "licenseConcluded": "MIT", + "licenseDeclared": "MIT", + "copyrightText": "NOASSERTION", + "externalRefs": [ + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser-xhr:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser-xhr:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser_xhr:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser_xhr:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester-browser:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester_browser:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:\\@algolia\\/requester:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/requester-browser-xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "SECURITY", + "referenceType": "cpe23Type", + "referenceLocator": "cpe:2.3:a:*:\\@algolia\\/requester_browser_xhr:4.14.3:*:*:*:*:*:*:*" + }, + { + "referenceCategory": "PACKAGE-MANAGER", + "referenceType": "purl", + "referenceLocator": "pkg:npm/%40algolia/requester-browser-xhr@4.14.3" + } + ] + } + ], + "relationships": [ + { + "spdxElementId": "SPDXRef-DOCUMENT", + "relatedSpdxElement": "SPDXRef-DOCUMENT", + "relationshipType": "DESCRIBES" + } + ] +} diff --git a/pkg/policies/testdata/sbom_syft.rego b/pkg/policies/testdata/sbom_syft.rego new file mode 100644 index 000000000..5bfe098c8 --- /dev/null +++ b/pkg/policies/testdata/sbom_syft.rego @@ -0,0 +1,14 @@ +package main + +import future.keywords.in + +deny[msg] { + not made_with_syft + + msg := "Not made with syft" +} + +made_with_syft { + some creator in input.creationInfo.creators + contains(creator, "syft") +} \ No newline at end of file diff --git a/pkg/policies/testdata/sbom_syft.yaml b/pkg/policies/testdata/sbom_syft.yaml new file mode 100644 index 000000000..4fa4d9a1a --- /dev/null +++ b/pkg/policies/testdata/sbom_syft.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: made-with-syft +spec: + path: testdata/sbom_syft.rego From 531eb244b73663c8b58026b9e2b0b2e23f9b31a3 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 16:53:30 +0200 Subject: [PATCH 17/73] remove change Signed-off-by: Jose I. Paris --- app/cli/internal/action/attestation_push.go | 1 - 1 file changed, 1 deletion(-) diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index a9b9dddf6..9a8da31d6 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -143,7 +143,6 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru if err != nil { return nil, fmt.Errorf("creating signer: %w", err) } - renderer, err := renderer.NewAttestationRenderer(action.c.CraftingState, action.cliVersion, action.cliDigest, sig, renderer.WithLogger(action.Logger), renderer.WithBundleOutputPath(action.bundlePath)) if err != nil { From 4ae46787a1d51c345db202e2bbb162a3861dad43 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 17:04:42 +0200 Subject: [PATCH 18/73] test embedded policies Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 13 ++++++-- pkg/policies/policies_test.go | 31 ++++++++++++++++++++ pkg/policies/testdata/workflow_embedded.yaml | 15 ++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 pkg/policies/testdata/workflow_embedded.yaml diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index efa4aacfa..36eafc7af 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -50,19 +50,26 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation // TODO: WARN. continue } + + // 1. load the policy spec spec, err := pv.loadSpec(policyAtt) if err != nil { return nil, fmt.Errorf("failed to load policy spec: %w", err) } + + // 2. load the policy script (rego) script, err := pv.loadPolicyScriptFromSpec(spec) if err != nil { return nil, fmt.Errorf("failed to load policy content: %w", err) } + + // 3. load the affected material (or the whole attestation) material, err := pv.loadSubject(policyAtt, spec, pv.state) if err != nil { return nil, fmt.Errorf("failed to load policy subject: %w", err) } - // verify policy, passing arguments from policyAtt + + // 4. verify the policy ng := getPolicyEngine(spec) res, err := ng.Verify(ctx, script, material) if err != nil { @@ -70,7 +77,7 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation } violations = append(violations, res...) - // Store result in the attestation itself (for the renderer to include them in the predicate) + // 5. Store result in the attestation itself (for the renderer to include them in the predicate) pv.state.Attestation.Policies = append(pv.state.Attestation.Policies, &v12.Policy{ Name: spec.Metadata.Name, Attachment: policyAtt, @@ -83,7 +90,7 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation } func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { - // 1. look for the referenced policy spec (note: `name` is not supported yet) + // look for the referenced policy spec (note: loading by `name` is not supported yet) reference := attachment.GetRef() // this method understands env, http and https schemes, and defaults to file system. rawData, err := blob.LoadFileOrURL(reference) diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 17ceac115..4dda894ce 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -105,6 +105,37 @@ func (s *testSuite) TestVerifyAttestations() { }, }, }, + { + name: "embedded rego policy", + state: &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow_embedded.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + }, + }, + }, + { + name: "embedded rego policy violations", + state: &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Policies: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow_embedded.yaml"}}, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "wrongname", + }, + }, + }, + violations: 1, + }, } for _, tc := range cases { diff --git a/pkg/policies/testdata/workflow_embedded.yaml b/pkg/policies/testdata/workflow_embedded.yaml new file mode 100644 index 000000000..6e02a4062 --- /dev/null +++ b/pkg/policies/testdata/workflow_embedded.yaml @@ -0,0 +1,15 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: workflow +spec: + embedded: | + package main + deny[msg] { + not is_workflow + msg := "incorrect workflow" + } + + is_workflow { + input.workflow.name == "policytest" + } From 67c1e537ae08c09748a681f8968497bc11c5d203 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 18:18:21 +0200 Subject: [PATCH 19/73] integrate CAS Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 28 +++++++--- pkg/policies/policies_test.go | 96 +++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 8 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 36eafc7af..0b6d26851 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -16,6 +16,8 @@ package policies import ( + "bufio" + "bytes" "context" "fmt" "path/filepath" @@ -32,10 +34,10 @@ import ( type PolicyVerifier struct { state *v12.CraftingState - cas *casclient.Client + cas casclient.Downloader } -func NewPolicyVerifier(state *v12.CraftingState, client *casclient.Client) *PolicyVerifier { +func NewPolicyVerifier(state *v12.CraftingState, client casclient.Downloader) *PolicyVerifier { // only Rego engine is currently supported return &PolicyVerifier{state: state, cas: client} } @@ -64,7 +66,7 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation } // 3. load the affected material (or the whole attestation) - material, err := pv.loadSubject(policyAtt, spec, pv.state) + material, err := pv.loadSubject(ctx, policyAtt, spec, pv.state) if err != nil { return nil, fmt.Errorf("failed to load policy subject: %w", err) } @@ -132,7 +134,7 @@ func (pv *PolicyVerifier) loadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Pol } // load the subject of the policy. -func (pv *PolicyVerifier) loadSubject(attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.CraftingState) ([]byte, error) { +func (pv *PolicyVerifier) loadSubject(ctx context.Context, attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.CraftingState) ([]byte, error) { // Load the affected material or attestation, and checks if the expected name and type match name := attachment.GetSelector().GetName() // if name selector is not set, the subject will become the full crafting state @@ -147,7 +149,7 @@ func (pv *PolicyVerifier) loadSubject(attachment *v1.PolicyAttachment, spec *v1. // If policy wasn't meant to be evaluated against this type of material, raise an error return nil, fmt.Errorf("invalid material type: %s, policy expected: %s", m.GetMaterialType(), spec.GetSpec().GetKind()) } - return pv.getMaterialPayload(m) + return pv.getMaterialPayload(ctx, m) } } @@ -155,14 +157,24 @@ func (pv *PolicyVerifier) loadSubject(attachment *v1.PolicyAttachment, spec *v1. } // Gets the material payload from the CAS -func (pv *PolicyVerifier) getMaterialPayload(m *v12.Attestation_Material) ([]byte, error) { +func (pv *PolicyVerifier) getMaterialPayload(ctx context.Context, m *v12.Attestation_Material) ([]byte, error) { if m.InlineCas { return m.GetArtifact().GetContent(), nil } - // TODO: Use the CAS to look for the material,. + // Use the CAS to look for the material + var b bytes.Buffer + w := bufio.NewWriter(&b) + err := pv.cas.Download(ctx, w, m.GetArtifact().GetDigest()) + if err != nil { + return nil, fmt.Errorf("failed to download artifact: %w", err) + } + err = w.Flush() + if err != nil { + return nil, fmt.Errorf("failed to download artifact: %w", err) + } - return nil, nil + return b.Bytes(), nil } // getPolicyEngine returns a PolicyEngine implementation to evaluate a given policy. diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 4dda894ce..229b4d5c2 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -17,12 +17,15 @@ package policies import ( "context" + "io" "io/fs" "os" "testing" v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/casclient/mocks" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "golang.org/x/exp/slices" ) @@ -336,6 +339,99 @@ func (s *testSuite) TestInlineMaterial() { s.Len(att.Policies[0].Violations, 0) } +func (s *testSuite) TestDownloadedMaterial() { + content, err := os.ReadFile("testdata/sbom-spdx.json") + s.Require().NoError(err) + + d := mocks.NewDownloader(s.T()) + d.On("Download", context.TODO(), mock.AnythingOfType("*bufio.Writer"), "foobar").Run(func(args mock.Arguments) { + w := args.Get(1).(io.Writer) + _, err := w.Write(content) + s.Require().NoError(err) + }).Return(nil) + + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Materials: []*v12.CraftingSchema_Material{ + { + Name: "sbom", + Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + }, + }, + Policies: []*v12.PolicyAttachment{ + { + Selector: &v12.PolicyAttachment_MaterialSelector{Name: "sbom"}, + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, + }, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + Materials: map[string]*v1.Attestation_Material{ + "sbom": { + MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ + Digest: "foobar", + }, + }, + UploadedToCas: true, + }, + }, + }, + } + verifier := NewPolicyVerifier(state, d) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Len(res, 0) +} + +func (s *testSuite) TestInvalidDownloadedMaterial() { + d := mocks.NewDownloader(s.T()) + d.On("Download", context.TODO(), mock.AnythingOfType("*bufio.Writer"), "another").Run(func(args mock.Arguments) { + w := args.Get(1).(io.Writer) + _, err := w.Write([]byte(`{"this": { "is": "not", "a": "sbom"}}`)) + s.Require().NoError(err) + }).Return(nil) + + state := &v1.CraftingState{ + InputSchema: &v12.CraftingSchema{ + Materials: []*v12.CraftingSchema_Material{ + { + Name: "sbom", + Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + }, + }, + Policies: []*v12.PolicyAttachment{ + { + Selector: &v12.PolicyAttachment_MaterialSelector{Name: "sbom"}, + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, + }, + }, + }, + Attestation: &v1.Attestation{ + Workflow: &v1.WorkflowMetadata{ + Name: "policytest", + }, + Materials: map[string]*v1.Attestation_Material{ + "sbom": { + MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ + Digest: "another", + }, + }, + UploadedToCas: true, + }, + }, + }, + } + verifier := NewPolicyVerifier(state, d) + res, err := verifier.Verify(context.TODO()) + s.Require().NoError(err) + s.Len(res, 1) +} + type testSuite struct { suite.Suite } From 614c31a4e17b5f673e048ff81e6aa7ea8c1a7ec5 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 22:00:50 +0200 Subject: [PATCH 20/73] refactor CAS client in CLI. Signed-off-by: Jose I. Paris --- app/cli/internal/action/action.go | 57 +++++++++++++++++++++ app/cli/internal/action/attestation_add.go | 49 ++---------------- app/cli/internal/action/attestation_push.go | 22 ++++++++ internal/casclient/casclient.go | 3 +- 4 files changed, 85 insertions(+), 46 deletions(-) diff --git a/app/cli/internal/action/action.go b/app/cli/internal/action/action.go index 0a687ea61..7c642a0b0 100644 --- a/app/cli/internal/action/action.go +++ b/app/cli/internal/action/action.go @@ -16,6 +16,7 @@ package action import ( + "context" "fmt" "os" "path/filepath" @@ -23,8 +24,11 @@ import ( pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter/statemanager/filesystem" "github.com/chainloop-dev/chainloop/internal/attestation/crafter/statemanager/remote" + "github.com/chainloop-dev/chainloop/internal/casclient" + "github.com/chainloop-dev/chainloop/internal/grpcconn" "github.com/rs/zerolog" "google.golang.org/grpc" ) @@ -57,3 +61,56 @@ func newCrafter(enableRemoteState bool, conn *grpc.ClientConn, opts ...crafter.N return crafter.NewCrafter(stateManager, opts...) } + +func getCasBackend(ctx context.Context, state *v1.CraftingState, opts *ActionsOpts, casCAPath, casURI string, insecure bool) (*casclient.CASBackend, func() error, error) { + // Default to inline CASBackend and override if we are not in dry-run mode + var closefunc func() error + backend := &casclient.CASBackend{ + Name: "not-set", + } + + // Define CASbackend information based on the API response + if !state.GetDryRun() { + // Get upload creds and CASbackend for the current attestation and set up CAS client + client := pb.NewAttestationServiceClient(opts.CPConnection) + creds, err := client.GetUploadCreds(ctx, + &pb.AttestationServiceGetUploadCredsRequest{ + WorkflowRunId: state.GetAttestation().GetWorkflow().GetWorkflowRunId(), + }, + ) + if err != nil { + return nil, nil, fmt.Errorf("failed to get upload creds: %w", err) + } + b := creds.GetResult().GetBackend() + if b == nil { + return nil, nil, fmt.Errorf("no backend found in upload creds") + } + backend.Name = b.Provider + backend.MaxSize = b.GetLimits().MaxBytes + + // Some CASBackends will actually upload information to the CAS server + // in such case we need to set up a connection + if !b.IsInline && creds.Result.Token != "" { + var grpcopts = []grpcconn.Option{ + grpcconn.WithInsecure(insecure), + } + + if casCAPath != "" { + grpcopts = append(grpcopts, grpcconn.WithCAFile(casCAPath)) + } + + artifactCASConn, err := grpcconn.New(casURI, creds.Result.Token, grpcopts...) + closefunc = artifactCASConn.Close + + if err != nil { + return nil, nil, fmt.Errorf("failed to create CAS client: %w", err) + } + + cascli := casclient.New(artifactCASConn, casclient.WithLogger(opts.Logger)) + backend.Uploader = cascli + backend.Downloader = cascli + } + } + + return backend, closefunc, nil +} diff --git a/app/cli/internal/action/attestation_add.go b/app/cli/internal/action/attestation_add.go index 1894f1679..f37dad2fd 100644 --- a/app/cli/internal/action/attestation_add.go +++ b/app/cli/internal/action/attestation_add.go @@ -20,11 +20,8 @@ import ( "errors" "fmt" - pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" - "github.com/chainloop-dev/chainloop/internal/casclient" - "github.com/chainloop-dev/chainloop/internal/grpcconn" "google.golang.org/grpc" ) @@ -83,52 +80,14 @@ func (action *AttestationAdd) Run(ctx context.Context, attestationID, materialNa } // Default to inline CASBackend and override if we are not in dry-run mode - casBackend := &casclient.CASBackend{ - Name: "not-set", - } - - // Define CASbackend information based on the API response - if !action.c.CraftingState.GetDryRun() { - // Get upload creds and CASbackend for the current attestation and set up CAS client - client := pb.NewAttestationServiceClient(action.CPConnection) - creds, err := client.GetUploadCreds(ctx, - &pb.AttestationServiceGetUploadCredsRequest{ - WorkflowRunId: action.c.CraftingState.GetAttestation().GetWorkflow().GetWorkflowRunId(), - }, - ) - if err != nil { - return err - } - b := creds.GetResult().GetBackend() - if b == nil { - return fmt.Errorf("no backend found in upload creds") - } - casBackend.Name = b.Provider - casBackend.MaxSize = b.GetLimits().MaxBytes - // Some CASBackends will actually upload information to the CAS server - // in such case we need to set up a connection - if !b.IsInline && creds.Result.Token != "" { - var opts = []grpcconn.Option{ - grpcconn.WithInsecure(action.connectionInsecure), - } - - if action.casCAPath != "" { - opts = append(opts, grpcconn.WithCAFile(action.casCAPath)) - } - - artifactCASConn, err := grpcconn.New(action.casURI, creds.Result.Token, opts...) - if err != nil { - return err - } - defer artifactCASConn.Close() - - casBackend.Uploader = casclient.New(artifactCASConn, casclient.WithLogger(action.Logger)) - } + casBackend, closefunc, err := getCasBackend(ctx, action.c.CraftingState, action.ActionsOpts, action.casCAPath, action.casURI, action.connectionInsecure) + if err != nil { + return fmt.Errorf("getting cas backend: %w", err) } + defer closefunc() // Add material to the attestation crafting state based on if the material is contract free or not. // By default, try to detect the material kind automatically - var err error switch { case materialName == "" && materialType == "": var kind schemaapi.CraftingSchema_Material_MaterialType diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index 9a8da31d6..b67eb7f63 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -25,6 +25,7 @@ import ( "github.com/chainloop-dev/chainloop/internal/attestation/crafter" "github.com/chainloop-dev/chainloop/internal/attestation/renderer" "github.com/chainloop-dev/chainloop/internal/attestation/signer" + "github.com/chainloop-dev/chainloop/pkg/policies" "github.com/secure-systems-lab/go-securesystemslib/dsse" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/timestamppb" @@ -143,6 +144,27 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru if err != nil { return nil, fmt.Errorf("creating signer: %w", err) } + + // Apply policies + backend, closefunc, err := getCasBackend(ctx, action.c.CraftingState, action.ActionsOpts, "", "", false) + if err != nil { + return nil, fmt.Errorf("creating cas backend: %w", err) + } + defer closefunc() + + pv := policies.NewPolicyVerifier(action.c.CraftingState, backend.Downloader) + violations, err := pv.Verify(ctx) + if err != nil { + return nil, fmt.Errorf("verifying policies: %w", err) + } + + // Log violations + if len(violations) > 0 { + for _, v := range violations { + action.Logger.Error().Msgf("policy violation [%s]: %s", v.Subject, v.Violation) + } + } + renderer, err := renderer.NewAttestationRenderer(action.c.CraftingState, action.cliVersion, action.cliDigest, sig, renderer.WithLogger(action.Logger), renderer.WithBundleOutputPath(action.bundlePath)) if err != nil { diff --git a/internal/casclient/casclient.go b/internal/casclient/casclient.go index 1db5557ce..30ec2a804 100644 --- a/internal/casclient/casclient.go +++ b/internal/casclient/casclient.go @@ -53,7 +53,8 @@ type DownloaderUploader interface { } type CASBackend struct { - Uploader Uploader + Uploader Uploader + Downloader Downloader // Max number of bytes this backend can store per artifact MaxSize int64 // CAS backend name From 485d1d7ecdcd95a7d6dbca3ca5760a107ef5b524 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 22:28:22 +0200 Subject: [PATCH 21/73] inject CAS options in attestation_push Signed-off-by: Jose I. Paris --- app/cli/cmd/attestation_init.go | 2 +- app/cli/cmd/attestation_push.go | 6 +++- app/cli/internal/action/action.go | 1 + app/cli/internal/action/attestation_push.go | 33 +++++++++++++++------ 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/app/cli/cmd/attestation_init.go b/app/cli/cmd/attestation_init.go index 091fbb6b4..a2859e583 100644 --- a/app/cli/cmd/attestation_init.go +++ b/app/cli/cmd/attestation_init.go @@ -44,7 +44,7 @@ func newAttestationInitCmd() *cobra.Command { return nil }, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { a, err := action.NewAttestationInit( &action.AttestationInitOpts{ ActionsOpts: actionOpts, diff --git a/app/cli/cmd/attestation_push.go b/app/cli/cmd/attestation_push.go index 4c1631874..4cf437a64 100644 --- a/app/cli/cmd/attestation_push.go +++ b/app/cli/cmd/attestation_push.go @@ -21,6 +21,7 @@ import ( "github.com/chainloop-dev/chainloop/app/cli/internal/action" "github.com/spf13/cobra" + "github.com/spf13/viper" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -64,7 +65,10 @@ func newAttestationPushCmd() *cobra.Command { a, err := action.NewAttestationPush(&action.AttestationPushOpts{ ActionsOpts: actionOpts, KeyPath: pkPath, BundlePath: bundle, CLIVersion: info.Version, CLIDigest: info.Digest, - SignServerCAPath: signServerCAPath, + SignServerCAPath: signServerCAPath, + CASURI: viper.GetString(confOptions.CASAPI.viperKey), + CASCAPath: viper.GetString(confOptions.CASCA.viperKey), + ConnectionInsecure: flagInsecure, }) if err != nil { return fmt.Errorf("failed to load action: %w", err) diff --git a/app/cli/internal/action/action.go b/app/cli/internal/action/action.go index 7c642a0b0..1c326f112 100644 --- a/app/cli/internal/action/action.go +++ b/app/cli/internal/action/action.go @@ -62,6 +62,7 @@ func newCrafter(enableRemoteState bool, conn *grpc.ClientConn, opts ...crafter.N return crafter.NewCrafter(stateManager, opts...) } +// creates a connection to a CAS backend func getCasBackend(ctx context.Context, state *v1.CraftingState, opts *ActionsOpts, casCAPath, casURI string, insecure bool) (*casclient.CASBackend, func() error, error) { // Default to inline CASBackend and override if we are not in dry-run mode var closefunc func() error diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index b67eb7f63..5d9e4423a 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -36,6 +36,11 @@ type AttestationPushOpts struct { KeyPath, CLIVersion, CLIDigest, BundlePath string SignServerCAPath string + + CASURI string + CASCAPath string // optional CA certificate for the CAS connection + // CAS connection insecure flag + ConnectionInsecure bool } type AttestationResult struct { @@ -49,6 +54,12 @@ type AttestationPush struct { c *crafter.Crafter keyPath, cliVersion, cliDigest, bundlePath string signServerCAPath string + + // CAS options + casURI string + // optional CA certificate for the CAS connection + casCAPath string + connectionInsecure bool } func NewAttestationPush(cfg *AttestationPushOpts) (*AttestationPush, error) { @@ -58,13 +69,16 @@ func NewAttestationPush(cfg *AttestationPushOpts) (*AttestationPush, error) { } return &AttestationPush{ - ActionsOpts: cfg.ActionsOpts, - c: c, - keyPath: cfg.KeyPath, - cliVersion: cfg.CLIVersion, - cliDigest: cfg.CLIDigest, - bundlePath: cfg.BundlePath, - signServerCAPath: cfg.SignServerCAPath, + ActionsOpts: cfg.ActionsOpts, + c: c, + keyPath: cfg.KeyPath, + cliVersion: cfg.CLIVersion, + cliDigest: cfg.CLIDigest, + bundlePath: cfg.BundlePath, + signServerCAPath: cfg.SignServerCAPath, + casURI: cfg.CASURI, + casCAPath: cfg.CASCAPath, + connectionInsecure: cfg.ConnectionInsecure, }, nil } @@ -145,13 +159,14 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru return nil, fmt.Errorf("creating signer: %w", err) } - // Apply policies - backend, closefunc, err := getCasBackend(ctx, action.c.CraftingState, action.ActionsOpts, "", "", false) + // CAS backend for policies + backend, closefunc, err := getCasBackend(ctx, action.c.CraftingState, action.ActionsOpts, action.casCAPath, action.casURI, action.connectionInsecure) if err != nil { return nil, fmt.Errorf("creating cas backend: %w", err) } defer closefunc() + // Apply policies pv := policies.NewPolicyVerifier(action.c.CraftingState, backend.Downloader) violations, err := pv.Verify(ctx) if err != nil { From f8f74e13dd29020782ce2eeaf768d077aaefd3ef Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 10 Jul 2024 22:58:35 +0200 Subject: [PATCH 22/73] fix nil pointer Signed-off-by: Jose I. Paris --- app/cli/internal/action/attestation_add.go | 4 +++- app/cli/internal/action/attestation_push.go | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/cli/internal/action/attestation_add.go b/app/cli/internal/action/attestation_add.go index f37dad2fd..657468a04 100644 --- a/app/cli/internal/action/attestation_add.go +++ b/app/cli/internal/action/attestation_add.go @@ -84,7 +84,9 @@ func (action *AttestationAdd) Run(ctx context.Context, attestationID, materialNa if err != nil { return fmt.Errorf("getting cas backend: %w", err) } - defer closefunc() + if closefunc != nil { + defer closefunc() + } // Add material to the attestation crafting state based on if the material is contract free or not. // By default, try to detect the material kind automatically diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index 5d9e4423a..4f21efe09 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -164,7 +164,9 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru if err != nil { return nil, fmt.Errorf("creating cas backend: %w", err) } - defer closefunc() + if closefunc != nil { + defer closefunc() + } // Apply policies pv := policies.NewPolicyVerifier(action.c.CraftingState, backend.Downloader) From 90f7b317e161c3f45cbaed5f0b757427720de74f Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 11:00:59 +0200 Subject: [PATCH 23/73] implement cas client Signed-off-by: Jose I. Paris --- app/cli/cmd/attestation_init.go | 2 +- app/cli/internal/action/action.go | 58 ---------------- app/cli/internal/action/attestation_add.go | 49 +++++++++++-- app/cli/internal/action/attestation_push.go | 16 ++--- internal/casclient/casclient.go | 3 +- pkg/policies/policies.go | 58 ++++++++++++++-- pkg/policies/policies_test.go | 77 +++------------------ 7 files changed, 115 insertions(+), 148 deletions(-) diff --git a/app/cli/cmd/attestation_init.go b/app/cli/cmd/attestation_init.go index a2859e583..091fbb6b4 100644 --- a/app/cli/cmd/attestation_init.go +++ b/app/cli/cmd/attestation_init.go @@ -44,7 +44,7 @@ func newAttestationInitCmd() *cobra.Command { return nil }, - RunE: func(cmd *cobra.Command, _ []string) error { + RunE: func(cmd *cobra.Command, args []string) error { a, err := action.NewAttestationInit( &action.AttestationInitOpts{ ActionsOpts: actionOpts, diff --git a/app/cli/internal/action/action.go b/app/cli/internal/action/action.go index 1c326f112..0a687ea61 100644 --- a/app/cli/internal/action/action.go +++ b/app/cli/internal/action/action.go @@ -16,7 +16,6 @@ package action import ( - "context" "fmt" "os" "path/filepath" @@ -24,11 +23,8 @@ import ( pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter/statemanager/filesystem" "github.com/chainloop-dev/chainloop/internal/attestation/crafter/statemanager/remote" - "github.com/chainloop-dev/chainloop/internal/casclient" - "github.com/chainloop-dev/chainloop/internal/grpcconn" "github.com/rs/zerolog" "google.golang.org/grpc" ) @@ -61,57 +57,3 @@ func newCrafter(enableRemoteState bool, conn *grpc.ClientConn, opts ...crafter.N return crafter.NewCrafter(stateManager, opts...) } - -// creates a connection to a CAS backend -func getCasBackend(ctx context.Context, state *v1.CraftingState, opts *ActionsOpts, casCAPath, casURI string, insecure bool) (*casclient.CASBackend, func() error, error) { - // Default to inline CASBackend and override if we are not in dry-run mode - var closefunc func() error - backend := &casclient.CASBackend{ - Name: "not-set", - } - - // Define CASbackend information based on the API response - if !state.GetDryRun() { - // Get upload creds and CASbackend for the current attestation and set up CAS client - client := pb.NewAttestationServiceClient(opts.CPConnection) - creds, err := client.GetUploadCreds(ctx, - &pb.AttestationServiceGetUploadCredsRequest{ - WorkflowRunId: state.GetAttestation().GetWorkflow().GetWorkflowRunId(), - }, - ) - if err != nil { - return nil, nil, fmt.Errorf("failed to get upload creds: %w", err) - } - b := creds.GetResult().GetBackend() - if b == nil { - return nil, nil, fmt.Errorf("no backend found in upload creds") - } - backend.Name = b.Provider - backend.MaxSize = b.GetLimits().MaxBytes - - // Some CASBackends will actually upload information to the CAS server - // in such case we need to set up a connection - if !b.IsInline && creds.Result.Token != "" { - var grpcopts = []grpcconn.Option{ - grpcconn.WithInsecure(insecure), - } - - if casCAPath != "" { - grpcopts = append(grpcopts, grpcconn.WithCAFile(casCAPath)) - } - - artifactCASConn, err := grpcconn.New(casURI, creds.Result.Token, grpcopts...) - closefunc = artifactCASConn.Close - - if err != nil { - return nil, nil, fmt.Errorf("failed to create CAS client: %w", err) - } - - cascli := casclient.New(artifactCASConn, casclient.WithLogger(opts.Logger)) - backend.Uploader = cascli - backend.Downloader = cascli - } - } - - return backend, closefunc, nil -} diff --git a/app/cli/internal/action/attestation_add.go b/app/cli/internal/action/attestation_add.go index 657468a04..936c9398a 100644 --- a/app/cli/internal/action/attestation_add.go +++ b/app/cli/internal/action/attestation_add.go @@ -20,8 +20,11 @@ import ( "errors" "fmt" + pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" + "github.com/chainloop-dev/chainloop/internal/casclient" + "github.com/chainloop-dev/chainloop/internal/grpcconn" "google.golang.org/grpc" ) @@ -80,16 +83,52 @@ func (action *AttestationAdd) Run(ctx context.Context, attestationID, materialNa } // Default to inline CASBackend and override if we are not in dry-run mode - casBackend, closefunc, err := getCasBackend(ctx, action.c.CraftingState, action.ActionsOpts, action.casCAPath, action.casURI, action.connectionInsecure) - if err != nil { - return fmt.Errorf("getting cas backend: %w", err) + casBackend := &casclient.CASBackend{ + Name: "not-set", } - if closefunc != nil { - defer closefunc() + + // Define CASbackend information based on the API response + if !action.c.CraftingState.GetDryRun() { + // Get upload creds and CASbackend for the current attestation and set up CAS client + client := pb.NewAttestationServiceClient(action.CPConnection) + creds, err := client.GetUploadCreds(ctx, + &pb.AttestationServiceGetUploadCredsRequest{ + WorkflowRunId: action.c.CraftingState.GetAttestation().GetWorkflow().GetWorkflowRunId(), + }, + ) + if err != nil { + return err + } + b := creds.GetResult().GetBackend() + if b == nil { + return fmt.Errorf("no backend found in upload creds") + } + casBackend.Name = b.Provider + casBackend.MaxSize = b.GetLimits().MaxBytes + // Some CASBackends will actually upload information to the CAS server + // in such case we need to set up a connection + if !b.IsInline && creds.Result.Token != "" { + var grpcopts = []grpcconn.Option{ + grpcconn.WithInsecure(action.connectionInsecure), + } + + if action.casCAPath != "" { + grpcopts = append(grpcopts, grpcconn.WithCAFile(action.casCAPath)) + } + + artifactCASConn, err := grpcconn.New(action.casURI, creds.Result.Token, grpcopts...) + if err != nil { + return err + } + defer artifactCASConn.Close() + + casBackend.Uploader = casclient.New(artifactCASConn, casclient.WithLogger(action.Logger)) + } } // Add material to the attestation crafting state based on if the material is contract free or not. // By default, try to detect the material kind automatically + var err error switch { case materialName == "" && materialType == "": var kind schemaapi.CraftingSchema_Material_MaterialType diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index 4f21efe09..6203cb020 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -159,17 +159,13 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru return nil, fmt.Errorf("creating signer: %w", err) } - // CAS backend for policies - backend, closefunc, err := getCasBackend(ctx, action.c.CraftingState, action.ActionsOpts, action.casCAPath, action.casURI, action.connectionInsecure) - if err != nil { - return nil, fmt.Errorf("creating cas backend: %w", err) - } - if closefunc != nil { - defer closefunc() - } - // Apply policies - pv := policies.NewPolicyVerifier(action.c.CraftingState, backend.Downloader) + pv := policies.NewPolicyVerifier(action.c.CraftingState, &policies.CASConnecitonOpts{ + Insecure: action.connectionInsecure, + CpConn: action.CPConnection, + CasAPI: action.casURI, + CasCA: action.casCAPath, + }, &action.Logger) violations, err := pv.Verify(ctx) if err != nil { return nil, fmt.Errorf("verifying policies: %w", err) diff --git a/internal/casclient/casclient.go b/internal/casclient/casclient.go index 30ec2a804..1db5557ce 100644 --- a/internal/casclient/casclient.go +++ b/internal/casclient/casclient.go @@ -53,8 +53,7 @@ type DownloaderUploader interface { } type CASBackend struct { - Uploader Uploader - Downloader Downloader + Uploader Uploader // Max number of bytes this backend can store per artifact MaxSize int64 // CAS backend name diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 0b6d26851..bb2e94996 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -22,24 +22,35 @@ import ( "fmt" "path/filepath" + pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" v12 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/casclient" + "github.com/chainloop-dev/chainloop/internal/grpcconn" "github.com/chainloop-dev/chainloop/pkg/policies/engine" "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" + "github.com/rs/zerolog" "github.com/sigstore/cosign/v2/pkg/blob" + "google.golang.org/grpc" "google.golang.org/protobuf/encoding/protojson" ) type PolicyVerifier struct { - state *v12.CraftingState - cas casclient.Downloader + state *v12.CraftingState + casOpts *CASConnecitonOpts + logger *zerolog.Logger } -func NewPolicyVerifier(state *v12.CraftingState, client casclient.Downloader) *PolicyVerifier { +type CASConnecitonOpts struct { + CasAPI, CasCA string + Insecure bool + CpConn *grpc.ClientConn +} + +func NewPolicyVerifier(state *v12.CraftingState, opts *CASConnecitonOpts, logger *zerolog.Logger) *PolicyVerifier { // only Rego engine is currently supported - return &PolicyVerifier{state: state, cas: client} + return &PolicyVerifier{state: state, casOpts: opts, logger: logger} } // Verify verifies that the statement is compliant with the policies present in the schema @@ -165,7 +176,12 @@ func (pv *PolicyVerifier) getMaterialPayload(ctx context.Context, m *v12.Attesta // Use the CAS to look for the material var b bytes.Buffer w := bufio.NewWriter(&b) - err := pv.cas.Download(ctx, w, m.GetArtifact().GetDigest()) + + client, err := pv.getCASClient(pb.CASCredentialsServiceGetRequest_ROLE_DOWNLOADER, m.GetArtifact().GetDigest()) + if err != nil { + return nil, err + } + err = client.Download(ctx, w, m.GetArtifact().GetDigest()) if err != nil { return nil, fmt.Errorf("failed to download artifact: %w", err) } @@ -192,3 +208,35 @@ func policyViolationsToAttestationViolations(violations []*engine.PolicyViolatio } return } + +// We need to create a connection for every single artifact, because it depends on the digest +func (pv *PolicyVerifier) getCASClient(role pb.CASCredentialsServiceGetRequest_Role, digest string) (*casclient.Client, error) { + // Retrieve temporary credentials for uploading + client := pb.NewCASCredentialsServiceClient(pv.casOpts.CpConn) + resp, err := client.Get(context.Background(), &pb.CASCredentialsServiceGetRequest{ + Role: role, + Digest: digest, + }) + if err != nil { + return nil, err + } + + if pv.casOpts.Insecure { + pv.logger.Warn().Msg("API contacted in insecure mode") + } + + var opts = []grpcconn.Option{ + grpcconn.WithInsecure(pv.casOpts.Insecure), + } + + if pv.casOpts.CasCA != "" { + opts = append(opts, grpcconn.WithCAFile(pv.casOpts.CasCA)) + } + + conn, err := grpcconn.New(pv.casOpts.CasAPI, resp.Result.Token, opts...) + if err != nil { + return nil, fmt.Errorf("failed to create cas client: %w", err) + } + + return casclient.New(conn, casclient.WithLogger(*pv.logger)), nil +} diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 229b4d5c2..61f08269b 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -17,15 +17,12 @@ package policies import ( "context" - "io" "io/fs" "os" "testing" v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/casclient/mocks" - "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "golang.org/x/exp/slices" ) @@ -143,7 +140,7 @@ func (s *testSuite) TestVerifyAttestations() { for _, tc := range cases { s.Run(tc.name, func() { - verifier := NewPolicyVerifier(tc.state, nil) + verifier := NewPolicyVerifier(tc.state, nil, nil) res, err := verifier.Verify(context.TODO()) if tc.wantErr != nil { // #nosec G601 @@ -174,7 +171,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil) + verifier := NewPolicyVerifier(state, nil, nil) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) s.Len(res, 0) @@ -204,7 +201,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil) + verifier := NewPolicyVerifier(state, nil, nil) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) s.Len(res, 1) @@ -241,7 +238,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil) + verifier := NewPolicyVerifier(state, nil, nil) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) s.Len(res, 0) @@ -272,7 +269,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil) + verifier := NewPolicyVerifier(state, nil, nil) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) s.Greater(len(res), 0) @@ -329,7 +326,7 @@ func (s *testSuite) TestInlineMaterial() { }, }, } - verifier := NewPolicyVerifier(state, nil) + verifier := NewPolicyVerifier(state, nil, nil) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) s.Len(res, 0) @@ -339,17 +336,7 @@ func (s *testSuite) TestInlineMaterial() { s.Len(att.Policies[0].Violations, 0) } -func (s *testSuite) TestDownloadedMaterial() { - content, err := os.ReadFile("testdata/sbom-spdx.json") - s.Require().NoError(err) - - d := mocks.NewDownloader(s.T()) - d.On("Download", context.TODO(), mock.AnythingOfType("*bufio.Writer"), "foobar").Run(func(args mock.Arguments) { - w := args.Get(1).(io.Writer) - _, err := w.Write(content) - s.Require().NoError(err) - }).Return(nil) - +func (s *testSuite) TestInvalidInlineMaterial() { state := &v1.CraftingState{ InputSchema: &v12.CraftingSchema{ Materials: []*v12.CraftingSchema_Material{ @@ -373,60 +360,16 @@ func (s *testSuite) TestDownloadedMaterial() { "sbom": { MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ - Digest: "foobar", + Content: []byte(`{"this": { "is": "not", "a": "sbom"}}`), }, }, - UploadedToCas: true, + InlineCas: true, }, }, }, } - verifier := NewPolicyVerifier(state, d) - res, err := verifier.Verify(context.TODO()) - s.Require().NoError(err) - s.Len(res, 0) -} -func (s *testSuite) TestInvalidDownloadedMaterial() { - d := mocks.NewDownloader(s.T()) - d.On("Download", context.TODO(), mock.AnythingOfType("*bufio.Writer"), "another").Run(func(args mock.Arguments) { - w := args.Get(1).(io.Writer) - _, err := w.Write([]byte(`{"this": { "is": "not", "a": "sbom"}}`)) - s.Require().NoError(err) - }).Return(nil) - - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Materials: []*v12.CraftingSchema_Material{ - { - Name: "sbom", - Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, - }, - }, - Policies: []*v12.PolicyAttachment{ - { - Selector: &v12.PolicyAttachment_MaterialSelector{Name: "sbom"}, - Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, - }, - }, - }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - Materials: map[string]*v1.Attestation_Material{ - "sbom": { - MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, - M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ - Digest: "another", - }, - }, - UploadedToCas: true, - }, - }, - }, - } - verifier := NewPolicyVerifier(state, d) + verifier := NewPolicyVerifier(state, nil, nil) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) s.Len(res, 1) From c6b270b7bb034e3bf273e0e40dff48077e7585c8 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 11:11:53 +0200 Subject: [PATCH 24/73] apply suggestions Signed-off-by: Jose I. Paris --- .../api/attestation/v1/crafting_state.pb.go | 154 ++++++++++-------- .../api/attestation/v1/crafting_state.proto | 12 +- pkg/policies/policies.go | 11 ++ 3 files changed, 102 insertions(+), 75 deletions(-) diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go index d4c12008b..0b1f3a1f5 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go @@ -1086,78 +1086,88 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x56, 0x61, 0x72, 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, 0x8a, 0x02, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, - 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 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, 0x42, - 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, - 0x40, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x1a, 0x3f, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, - 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0xc9, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, - 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, - 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, - 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, - 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, - 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, - 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, - 0x22, 0x8e, 0x02, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, - 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, - 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, - 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x42, 0x54, 0x5a, 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa0, 0x03, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 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, 0x4d, 0x0a, 0x0a, 0x61, 0x74, + 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 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, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x61, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, + 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x4f, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x07, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, + 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, + 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, + 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, + 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, + 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, + 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, + 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, + 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, + 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, + 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, 0x52, 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, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, + 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto index 265aeb033..a181e4260 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto @@ -96,7 +96,13 @@ message Attestation { // A policy executed against an attestation message Policy { // The policy name from the policy spec - string name = 1; + string name = 1 [(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", + }, + }]; // The attachment as in the contract, with arguments and any other metadata workflowcontract.v1.PolicyAttachment attachment = 2 [(buf.validate.field).required = true]; // The policy script body (rego) @@ -105,8 +111,8 @@ message Policy { repeated Violation violations = 4; message Violation { - string subject = 1; - string message = 2; + string subject = 1 [(buf.validate.field).required = true]; + string message = 2 [(buf.validate.field).required = true]; } } diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 0b6d26851..690d637d0 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -22,6 +22,7 @@ import ( "fmt" "path/filepath" + "github.com/bufbuild/protovalidate-go" v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" v12 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" @@ -107,6 +108,16 @@ func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, if err := protojson.Unmarshal(jsonContent, &policy); err != nil { return nil, fmt.Errorf("unmarshalling policy spec: %w", err) } + // Validate just in case + validator, err := protovalidate.New() + if err != nil { + return nil, fmt.Errorf("validating policy spec: %w", err) + } + err = validator.Validate(&policy) + if err != nil { + return nil, fmt.Errorf("validating policy spec: %w", err) + } + return &policy, nil } From 3368d634df6f9e9be349a689213e92f272957e56 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 11:31:14 +0200 Subject: [PATCH 25/73] sort imports Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 5 +++-- pkg/policies/policies_test.go | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 690d637d0..50aa829a3 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -23,14 +23,15 @@ import ( "path/filepath" "github.com/bufbuild/protovalidate-go" + "github.com/sigstore/cosign/v2/pkg/blob" + "google.golang.org/protobuf/encoding/protojson" + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" v12 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/chainloop-dev/chainloop/pkg/policies/engine" "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" - "github.com/sigstore/cosign/v2/pkg/blob" - "google.golang.org/protobuf/encoding/protojson" ) type PolicyVerifier struct { diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 229b4d5c2..4f9aad354 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -22,12 +22,13 @@ import ( "os" "testing" - v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/casclient/mocks" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" "golang.org/x/exp/slices" + + v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/casclient/mocks" ) func (s *testSuite) TestVerifyAttestations() { From 38ced90e76ebf8242b850ed1f7d8fc90761df220 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 12:23:57 +0200 Subject: [PATCH 26/73] load and validate policy on contract add Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter.go | 82 +++++++++++++++++-- internal/attestation/crafter/crafter_test.go | 44 +++++++--- .../crafter/testdata/contracts/policy.rego | 9 ++ .../testdata/contracts/policy_embedded.yaml | 15 ++++ .../contracts/policy_missing_rego.yaml | 6 ++ .../testdata/contracts/policy_rego.yaml | 6 ++ .../contracts/with_missing_policy.yaml | 3 + .../contracts/with_policy_embedded.yaml | 3 + .../contracts/with_policy_missing_rego.yaml | 3 + .../crafter/testdata/contracts/with_rego.yaml | 3 + pkg/policies/policies.go | 67 ++------------- 11 files changed, 164 insertions(+), 77 deletions(-) create mode 100644 internal/attestation/crafter/testdata/contracts/policy.rego create mode 100644 internal/attestation/crafter/testdata/contracts/policy_embedded.yaml create mode 100644 internal/attestation/crafter/testdata/contracts/policy_missing_rego.yaml create mode 100644 internal/attestation/crafter/testdata/contracts/policy_rego.yaml create mode 100644 internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml create mode 100644 internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml create mode 100644 internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml create mode 100644 internal/attestation/crafter/testdata/contracts/with_rego.yaml diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index e1a7ac1b5..22bc2e87c 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -29,18 +29,21 @@ import ( "cuelang.org/go/cue/cuecontext" "github.com/bufbuild/protovalidate-go" - schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/attestation/crafter/materials" - "github.com/chainloop-dev/chainloop/internal/casclient" - "github.com/chainloop-dev/chainloop/internal/ociauth" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/google/go-containerregistry/pkg/authn" "github.com/rs/zerolog" + "github.com/sigstore/cosign/v2/pkg/blob" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/timestamppb" "sigs.k8s.io/yaml" + + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/attestation/crafter/materials" + "github.com/chainloop-dev/chainloop/internal/casclient" + "github.com/chainloop-dev/chainloop/internal/ociauth" + "github.com/chainloop-dev/chainloop/pkg/policies/engine" ) // StateManager is an interface for managing the state of the crafting process @@ -203,18 +206,83 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { } // Proto validations - if err := validator.Validate(schema); err != nil { + if err = validator.Validate(schema); err != nil { return nil, err } // Custom Validations - if err := schema.ValidateUniqueMaterialName(); err != nil { + if err = schema.ValidateUniqueMaterialName(); err != nil { return nil, err } + // Load and validate policies, if any + for _, p := range schema.GetPolicies() { + spec, err := LoadPolicySpec(p) + if err != nil { + return nil, fmt.Errorf("validating policy: %w", err) + } + _, err = LoadPolicyScriptFromSpec(spec) + if err != nil { + return nil, fmt.Errorf("loading policy script: %w", err) + } + } + return schema, nil } +// LoadPolicySpec loads and validates a policy spec from a contract +func LoadPolicySpec(attachment *schemaapi.PolicyAttachment) (*schemaapi.Policy, error) { + // look for the referenced policy spec (note: loading by `name` is not supported yet) + reference := attachment.GetRef() + // this method understands env, http and https schemes, and defaults to file system. + rawData, err := blob.LoadFileOrURL(reference) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) + } + jsonContent, err := LoadJSONBytes(rawData, filepath.Ext(reference)) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) + } + var policy schemaapi.Policy + if err := protojson.Unmarshal(jsonContent, &policy); err != nil { + return nil, fmt.Errorf("unmarshalling policy spec: %w", err) + } + // Validate just in case + validator, err := protovalidate.New() + if err != nil { + return nil, fmt.Errorf("validating policy spec: %w", err) + } + err = validator.Validate(&policy) + if err != nil { + return nil, fmt.Errorf("validating policy spec: %w", err) + } + + return &policy, nil +} + +// LoadPolicyScriptFromSpec loads a policy referenced from the spec +func LoadPolicyScriptFromSpec(spec *schemaapi.Policy) (*engine.Policy, error) { + var content []byte + var err error + + switch source := spec.GetSpec().GetSource().(type) { + case *schemaapi.PolicySpec_Embedded: + content = []byte(source.Embedded) + case *schemaapi.PolicySpec_Path: + content, err = blob.LoadFileOrURL(source.Path) + if err != nil { + return nil, fmt.Errorf("loading policy content: %w", err) + } + default: + return nil, fmt.Errorf("policy spec is empty") + } + + return &engine.Policy{ + Name: spec.GetMetadata().GetName(), + Source: content, + }, nil +} + // Initialize the temporary file with the content of the schema func (c *Crafter) initCraftingStateFile( ctx context.Context, diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 48b37bb35..7268361d5 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -182,22 +182,33 @@ func newInitializedCrafter(t *testing.T, contractPath string, wfMeta *v1.Workflo } func (s *crafterSuite) TestLoadSchema() { + want := &schemaapi.CraftingSchema{ + SchemaVersion: "v1", + Runner: &schemaapi.CraftingSchema_Runner{ + Type: schemaapi.CraftingSchema_Runner_GITHUB_ACTION, + }, + } + testCases := []struct { name string contractPath string + want *schemaapi.CraftingSchema wantErr bool }{ { name: "yaml", contractPath: "testdata/contracts/empty_github.yaml", + want: want, }, { name: "json", contractPath: "testdata/contracts/empty_github.json", + want: want, }, { name: "cue", contractPath: "testdata/contracts/empty_github.cue", + want: want, }, { name: "unsupported", @@ -209,6 +220,24 @@ func (s *crafterSuite) TestLoadSchema() { contractPath: "testdata/contracts/invalid.yaml", wantErr: true, }, + { + name: "policies", + contractPath: "testdata/contracts/with_policy_embedded.yaml", + }, + { + name: "missing policy", + contractPath: "testdata/contracts/with_missing_policy.yaml", + wantErr: true, + }, + { + name: "missing script", + contractPath: "testdata/contracts/with_policy_missing_rego.yaml", + wantErr: true, + }, + { + name: "rego policy", + contractPath: "testdata/contracts/with_rego.yaml", + }, } for _, tc := range testCases { @@ -219,16 +248,11 @@ func (s *crafterSuite) TestLoadSchema() { return } - want := &schemaapi.CraftingSchema{ - SchemaVersion: "v1", - Runner: &schemaapi.CraftingSchema_Runner{ - Type: schemaapi.CraftingSchema_Runner_GITHUB_ACTION, - }, - } - - // Check state - if ok := proto.Equal(want, got); !ok { - s.Fail(fmt.Sprintf("These two protobuf messages are not equal:\nexpected: %v\nactual: %v", want, got)) + if tc.want != nil { + // Check state + if ok := proto.Equal(want, got); !ok { + s.Fail(fmt.Sprintf("These two protobuf messages are not equal:\nexpected: %v\nactual: %v", want, got)) + } } }) } diff --git a/internal/attestation/crafter/testdata/contracts/policy.rego b/internal/attestation/crafter/testdata/contracts/policy.rego new file mode 100644 index 000000000..a6d0b5038 --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/policy.rego @@ -0,0 +1,9 @@ +package main +deny[msg] { + not is_workflow + msg := "incorrect workflow" +} + +is_workflow { + input.workflow.name == "policytest" +} diff --git a/internal/attestation/crafter/testdata/contracts/policy_embedded.yaml b/internal/attestation/crafter/testdata/contracts/policy_embedded.yaml new file mode 100644 index 000000000..6e02a4062 --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/policy_embedded.yaml @@ -0,0 +1,15 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: workflow +spec: + embedded: | + package main + deny[msg] { + not is_workflow + msg := "incorrect workflow" + } + + is_workflow { + input.workflow.name == "policytest" + } diff --git a/internal/attestation/crafter/testdata/contracts/policy_missing_rego.yaml b/internal/attestation/crafter/testdata/contracts/policy_missing_rego.yaml new file mode 100644 index 000000000..898fa6315 --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/policy_missing_rego.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: workflow +spec: + path: idontexist.rego diff --git a/internal/attestation/crafter/testdata/contracts/policy_rego.yaml b/internal/attestation/crafter/testdata/contracts/policy_rego.yaml new file mode 100644 index 000000000..1a64eeb9e --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/policy_rego.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: workflow +spec: + path: testdata/contracts/policy.rego diff --git a/internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml b/internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml new file mode 100644 index 000000000..9a1450fa1 --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml @@ -0,0 +1,3 @@ +schemaVersion: "v1" +policies: + - ref: idontexist.yaml diff --git a/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml b/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml new file mode 100644 index 000000000..a20b3f6f4 --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml @@ -0,0 +1,3 @@ +schemaVersion: "v1" +policies: + - ref: testdata/contracts/policy_embedded.yaml diff --git a/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml b/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml new file mode 100644 index 000000000..4bef873de --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml @@ -0,0 +1,3 @@ +schemaVersion: "v1" +policies: + - ref: testdata/contracts/policy_missing_rego.yaml diff --git a/internal/attestation/crafter/testdata/contracts/with_rego.yaml b/internal/attestation/crafter/testdata/contracts/with_rego.yaml new file mode 100644 index 000000000..ed68d31ad --- /dev/null +++ b/internal/attestation/crafter/testdata/contracts/with_rego.yaml @@ -0,0 +1,3 @@ +schemaVersion: "v1" +policies: + - ref: testdata/contracts/policy_rego.yaml diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 73574d2b2..e65ed00bc 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -20,11 +20,8 @@ import ( "bytes" "context" "fmt" - "path/filepath" - "github.com/bufbuild/protovalidate-go" "github.com/rs/zerolog" - "github.com/sigstore/cosign/v2/pkg/blob" "google.golang.org/grpc" "google.golang.org/protobuf/encoding/protojson" @@ -62,24 +59,24 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation for _, policyAtt := range policies { if policyAtt.Disabled { // policy is disabled - // TODO: WARN. + pv.logger.Warn().Msgf("policy [name: %s, ref: %s] disabled", policyAtt.GetName(), policyAtt.GetRef()) continue } // 1. load the policy spec - spec, err := pv.loadSpec(policyAtt) + spec, err := crafter.LoadPolicySpec(policyAtt) if err != nil { return nil, fmt.Errorf("failed to load policy spec: %w", err) } // 2. load the policy script (rego) - script, err := pv.loadPolicyScriptFromSpec(spec) + script, err := crafter.LoadPolicyScriptFromSpec(spec) if err != nil { return nil, fmt.Errorf("failed to load policy content: %w", err) } // 3. load the affected material (or the whole attestation) - material, err := pv.loadSubject(ctx, policyAtt, spec, pv.state) + material, err := pv.loadSubject(ctx, policyAtt, spec) if err != nil { return nil, fmt.Errorf("failed to load policy subject: %w", err) } @@ -104,60 +101,10 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation return violations, nil } -func (pv *PolicyVerifier) loadSpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { - // look for the referenced policy spec (note: loading by `name` is not supported yet) - reference := attachment.GetRef() - // this method understands env, http and https schemes, and defaults to file system. - rawData, err := blob.LoadFileOrURL(reference) - if err != nil { - return nil, fmt.Errorf("loading policy spec: %w", err) - } - jsonContent, err := crafter.LoadJSONBytes(rawData, filepath.Ext(reference)) - if err != nil { - return nil, fmt.Errorf("loading policy spec: %w", err) - } - var policy v1.Policy - if err := protojson.Unmarshal(jsonContent, &policy); err != nil { - return nil, fmt.Errorf("unmarshalling policy spec: %w", err) - } - // Validate just in case - validator, err := protovalidate.New() - if err != nil { - return nil, fmt.Errorf("validating policy spec: %w", err) - } - err = validator.Validate(&policy) - if err != nil { - return nil, fmt.Errorf("validating policy spec: %w", err) - } - - return &policy, nil -} - -// loads a policy referenced from the spec -func (pv *PolicyVerifier) loadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Policy, error) { - var content []byte - var err error - - switch source := spec.GetSpec().GetSource().(type) { - case *v1.PolicySpec_Embedded: - content = []byte(source.Embedded) - case *v1.PolicySpec_Path: - content, err = blob.LoadFileOrURL(source.Path) - if err != nil { - return nil, fmt.Errorf("loading policy content: %w", err) - } - default: - return nil, fmt.Errorf("policy spec is empty") - } - - return &engine.Policy{ - Name: spec.GetMetadata().GetName(), - Source: content, - }, nil -} - // load the subject of the policy. -func (pv *PolicyVerifier) loadSubject(ctx context.Context, attachment *v1.PolicyAttachment, spec *v1.Policy, state *v12.CraftingState) ([]byte, error) { +func (pv *PolicyVerifier) loadSubject(ctx context.Context, attachment *v1.PolicyAttachment, spec *v1.Policy) ([]byte, error) { + state := pv.state + // Load the affected material or attestation, and checks if the expected name and type match name := attachment.GetSelector().GetName() // if name selector is not set, the subject will become the full crafting state From f2da2ae49850ea4bed5f9d571f56b9385de72a91 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 12:32:51 +0200 Subject: [PATCH 27/73] undo change Signed-off-by: Jose I. Paris --- app/cli/internal/action/attestation_add.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/cli/internal/action/attestation_add.go b/app/cli/internal/action/attestation_add.go index 936c9398a..452dcc4de 100644 --- a/app/cli/internal/action/attestation_add.go +++ b/app/cli/internal/action/attestation_add.go @@ -20,12 +20,13 @@ import ( "errors" "fmt" + "google.golang.org/grpc" + pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/chainloop-dev/chainloop/internal/grpcconn" - "google.golang.org/grpc" ) type AttestationAddOpts struct { @@ -108,15 +109,15 @@ func (action *AttestationAdd) Run(ctx context.Context, attestationID, materialNa // Some CASBackends will actually upload information to the CAS server // in such case we need to set up a connection if !b.IsInline && creds.Result.Token != "" { - var grpcopts = []grpcconn.Option{ + var opts = []grpcconn.Option{ grpcconn.WithInsecure(action.connectionInsecure), } if action.casCAPath != "" { - grpcopts = append(grpcopts, grpcconn.WithCAFile(action.casCAPath)) + opts = append(opts, grpcconn.WithCAFile(action.casCAPath)) } - artifactCASConn, err := grpcconn.New(action.casURI, creds.Result.Token, grpcopts...) + artifactCASConn, err := grpcconn.New(action.casURI, creds.Result.Token, opts...) if err != nil { return err } From 7127e63e5abf66e4f2391c53a5609171cbbcd389 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 14:00:59 +0200 Subject: [PATCH 28/73] store policies in the predicate Signed-off-by: Jose I. Paris --- internal/attestation/renderer/chainloop/v02.go | 8 ++++++-- pkg/policies/policies.go | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index 73dc94eb2..696fd491b 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -23,13 +23,15 @@ import ( "strings" "time" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" crv1 "github.com/google/go-containerregistry/pkg/v1" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" - schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + intoto "github.com/in-toto/attestation/go/v1" + + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" ) // Replace custom material type with https://github.com/in-toto/attestation/blob/main/spec/v1.0/resource_descriptor.md @@ -38,6 +40,7 @@ const PredicateTypeV02 = "chainloop.dev/attestation/v0.2" type ProvenancePredicateV02 struct { *ProvenancePredicateCommon Materials []*intoto.ResourceDescriptor `json:"materials,omitempty"` + Policies []*v1.Policy `json:"policies,omitempty"` } type RendererV02 struct { @@ -150,6 +153,7 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { p := ProvenancePredicateV02{ ProvenancePredicateCommon: predicateCommon(r.builder, r.att), Materials: normalizedMaterials, + Policies: r.att.Policies, } // transform to structpb.Struct in a two steps process diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 86cc9d386..b4c2bdc08 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -19,6 +19,7 @@ import ( "bufio" "bytes" "context" + "encoding/base64" "fmt" "github.com/rs/zerolog" @@ -83,6 +84,8 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation return nil, fmt.Errorf("failed to load policy subject: %w", err) } + pv.logger.Debug().Msgf("evaluating policy %s", spec.Metadata.Name) + // 4. verify the policy ng := getPolicyEngine(spec) res, err := ng.Verify(ctx, script, material) @@ -95,7 +98,7 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation pv.state.Attestation.Policies = append(pv.state.Attestation.Policies, &v12.Policy{ Name: spec.Metadata.Name, Attachment: policyAtt, - Body: string(script.Source), + Body: base64.StdEncoding.EncodeToString(script.Source), Violations: policyViolationsToAttestationViolations(res), }) } From 89957fa665957a848bae8feafe55470640ec00d3 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 15:24:37 +0200 Subject: [PATCH 29/73] fix tests Signed-off-by: Jose I. Paris --- pkg/policies/policies_test.go | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 822e99929..11ecf8597 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -17,10 +17,12 @@ package policies import ( "context" + "encoding/base64" "io/fs" "os" "testing" + "github.com/rs/zerolog" "github.com/stretchr/testify/suite" "golang.org/x/exp/slices" @@ -141,7 +143,7 @@ func (s *testSuite) TestVerifyAttestations() { for _, tc := range cases { s.Run(tc.name, func() { - verifier := NewPolicyVerifier(tc.state, nil, nil) + verifier := NewPolicyVerifier(tc.state, nil, &s.logger) res, err := verifier.Verify(context.TODO()) if tc.wantErr != nil { @@ -173,7 +175,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil, nil) + verifier := NewPolicyVerifier(state, nil, &s.logger) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) @@ -186,7 +188,9 @@ func (s *testSuite) TestAttestationResult() { s.Len(p.Violations, 0) s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) s.Equal("workflow", p.Name) - s.Contains(p.Body, "package main") + body, err := base64.StdEncoding.DecodeString(p.Body) + s.Require().NoError(err) + s.Contains(string(body), "package main") }) s.Run("failed attestation", func() { @@ -204,7 +208,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil, nil) + verifier := NewPolicyVerifier(state, nil, &s.logger) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) @@ -215,7 +219,9 @@ func (s *testSuite) TestAttestationResult() { p := att.Policies[0] s.Len(p.Violations, 1) - s.Contains(p.Body, "package main") + body, err := base64.StdEncoding.DecodeString(p.Body) + s.Require().NoError(err) + s.Contains(string(body), "package main") v := p.Violations[0] s.Equal(p.Name, v.Subject) s.Equal("incorrect runner", v.Message) @@ -242,7 +248,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil, nil) + verifier := NewPolicyVerifier(state, nil, &s.logger) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) @@ -274,7 +280,7 @@ func (s *testSuite) TestAttestationResult() { }, } - verifier := NewPolicyVerifier(state, nil, nil) + verifier := NewPolicyVerifier(state, nil, &s.logger) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) @@ -332,7 +338,7 @@ func (s *testSuite) TestInlineMaterial() { }, }, } - verifier := NewPolicyVerifier(state, nil, nil) + verifier := NewPolicyVerifier(state, nil, &s.logger) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) @@ -376,7 +382,7 @@ func (s *testSuite) TestInvalidInlineMaterial() { }, } - verifier := NewPolicyVerifier(state, nil, nil) + verifier := NewPolicyVerifier(state, nil, &s.logger) res, err := verifier.Verify(context.TODO()) s.Require().NoError(err) @@ -385,6 +391,12 @@ func (s *testSuite) TestInvalidInlineMaterial() { type testSuite struct { suite.Suite + + logger zerolog.Logger +} + +func (s *testSuite) SetupTest() { + s.logger = zerolog.Nop() } func TestPolicyVerifier(t *testing.T) { From 752d17a8228e17f29cb3aeb49e23ed2020d29e8b Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Thu, 11 Jul 2024 18:28:15 +0200 Subject: [PATCH 30/73] "compile" policies into contracts Signed-off-by: Jose I. Paris --- .../workflowcontract/v1/crafting_schema.ts | 343 +++++++++++- .../workflowcontract/v1/crafting_schema.pb.go | 506 +++++++++++++++--- .../workflowcontract/v1/crafting_schema.proto | 49 ++ .../api/workflowcontract/v1/policy.pb.go | 470 ---------------- .../api/workflowcontract/v1/policy.proto | 68 --- internal/attestation/crafter/crafter.go | 15 +- pkg/policies/policies.go | 3 +- pkg/policies/policies_test.go | 9 +- 8 files changed, 851 insertions(+), 612 deletions(-) delete mode 100644 app/controlplane/api/workflowcontract/v1/policy.pb.go delete mode 100644 app/controlplane/api/workflowcontract/v1/policy.proto 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 5c9726237..ffa9c1ac1 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -248,6 +248,10 @@ export interface PolicyAttachment { name?: | string | undefined; + /** meant to be used to embed the policy in the contract */ + embedded?: + | Policy + | undefined; /** * rules to select a material or materials to be validated by the policy. * If none provided, the whole statement will be injected to the policy @@ -269,6 +273,74 @@ export interface PolicyAttachment_PolicyArgument { value: string; } +/** Represents a policy to be applied to a material or attestation */ +export interface Policy { + apiVersion: string; + kind: string; + metadata?: Metadata; + spec?: PolicySpec; +} + +export interface Metadata { + /** the name of the policy */ + name: string; +} + +export interface PolicySpec { + /** path to a policy script. It might consist of a URI reference */ + path?: + | string + | undefined; + /** embedded source code (only Rego supported currently) */ + embedded?: + | string + | undefined; + /** + * stage at which this policy will be run. + * Only "push" is supported currently and this field will be ignored + */ + stage: PolicySpec_PolicyStage; + /** if set, it will match a material kind supported by Chainloop. */ + kind: CraftingSchema_Material_MaterialType; +} + +/** + * buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX + * buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX + */ +export enum PolicySpec_PolicyStage { + UNSPECIFIED = 0, + PUSH = 1, + UNRECOGNIZED = -1, +} + +export function policySpec_PolicyStageFromJSON(object: any): PolicySpec_PolicyStage { + switch (object) { + case 0: + case "UNSPECIFIED": + return PolicySpec_PolicyStage.UNSPECIFIED; + case 1: + case "PUSH": + return PolicySpec_PolicyStage.PUSH; + case -1: + case "UNRECOGNIZED": + default: + return PolicySpec_PolicyStage.UNRECOGNIZED; + } +} + +export function policySpec_PolicyStageToJSON(object: PolicySpec_PolicyStage): string { + switch (object) { + case PolicySpec_PolicyStage.UNSPECIFIED: + return "UNSPECIFIED"; + case PolicySpec_PolicyStage.PUSH: + return "PUSH"; + case PolicySpec_PolicyStage.UNRECOGNIZED: + default: + return "UNRECOGNIZED"; + } +} + function createBaseCraftingSchema(): CraftingSchema { return { schemaVersion: "", materials: [], envAllowList: [], runner: undefined, annotations: [], policies: [] }; } @@ -655,7 +727,7 @@ export const Annotation = { }; function createBasePolicyAttachment(): PolicyAttachment { - return { ref: undefined, name: undefined, selector: undefined, disabled: false, with: [] }; + return { ref: undefined, name: undefined, embedded: undefined, selector: undefined, disabled: false, with: [] }; } export const PolicyAttachment = { @@ -666,6 +738,9 @@ export const PolicyAttachment = { if (message.name !== undefined) { writer.uint32(18).string(message.name); } + if (message.embedded !== undefined) { + Policy.encode(message.embedded, writer.uint32(50).fork()).ldelim(); + } if (message.selector !== undefined) { PolicyAttachment_MaterialSelector.encode(message.selector, writer.uint32(26).fork()).ldelim(); } @@ -699,6 +774,13 @@ export const PolicyAttachment = { message.name = reader.string(); continue; + case 6: + if (tag !== 50) { + break; + } + + message.embedded = Policy.decode(reader, reader.uint32()); + continue; case 3: if (tag !== 26) { break; @@ -733,6 +815,7 @@ export const PolicyAttachment = { return { ref: isSet(object.ref) ? String(object.ref) : undefined, name: isSet(object.name) ? String(object.name) : undefined, + embedded: isSet(object.embedded) ? Policy.fromJSON(object.embedded) : undefined, selector: isSet(object.selector) ? PolicyAttachment_MaterialSelector.fromJSON(object.selector) : undefined, disabled: isSet(object.disabled) ? Boolean(object.disabled) : false, with: Array.isArray(object?.with) ? object.with.map((e: any) => PolicyAttachment_PolicyArgument.fromJSON(e)) : [], @@ -743,6 +826,7 @@ export const PolicyAttachment = { const obj: any = {}; message.ref !== undefined && (obj.ref = message.ref); message.name !== undefined && (obj.name = message.name); + message.embedded !== undefined && (obj.embedded = message.embedded ? Policy.toJSON(message.embedded) : undefined); message.selector !== undefined && (obj.selector = message.selector ? PolicyAttachment_MaterialSelector.toJSON(message.selector) : undefined); message.disabled !== undefined && (obj.disabled = message.disabled); @@ -762,6 +846,9 @@ export const PolicyAttachment = { const message = createBasePolicyAttachment(); message.ref = object.ref ?? undefined; message.name = object.name ?? undefined; + message.embedded = (object.embedded !== undefined && object.embedded !== null) + ? Policy.fromPartial(object.embedded) + : undefined; message.selector = (object.selector !== undefined && object.selector !== null) ? PolicyAttachment_MaterialSelector.fromPartial(object.selector) : undefined; @@ -904,6 +991,260 @@ export const PolicyAttachment_PolicyArgument = { }, }; +function createBasePolicy(): Policy { + return { apiVersion: "", kind: "", metadata: undefined, spec: undefined }; +} + +export const Policy = { + encode(message: Policy, 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) { + PolicySpec.encode(message.spec, writer.uint32(34).fork()).ldelim(); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Policy { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicy(); + 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 = PolicySpec.decode(reader, reader.uint32()); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Policy { + 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) ? PolicySpec.fromJSON(object.spec) : undefined, + }; + }, + + toJSON(message: Policy): 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 ? PolicySpec.toJSON(message.spec) : undefined); + return obj; + }, + + create, I>>(base?: I): Policy { + return Policy.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Policy { + const message = createBasePolicy(); + 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) + ? PolicySpec.fromPartial(object.spec) + : undefined; + return message; + }, +}; + +function createBaseMetadata(): Metadata { + return { name: "" }; +} + +export const Metadata = { + encode(message: Metadata, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.name !== "") { + writer.uint32(26).string(message.name); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): Metadata { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseMetadata(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 3: + if (tag !== 26) { + break; + } + + message.name = reader.string(); + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): Metadata { + return { name: isSet(object.name) ? String(object.name) : "" }; + }, + + toJSON(message: Metadata): unknown { + const obj: any = {}; + message.name !== undefined && (obj.name = message.name); + return obj; + }, + + create, I>>(base?: I): Metadata { + return Metadata.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Metadata { + const message = createBaseMetadata(); + message.name = object.name ?? ""; + return message; + }, +}; + +function createBasePolicySpec(): PolicySpec { + return { path: undefined, embedded: undefined, stage: 0, kind: 0 }; +} + +export const PolicySpec = { + encode(message: PolicySpec, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.path !== undefined) { + writer.uint32(10).string(message.path); + } + if (message.embedded !== undefined) { + writer.uint32(18).string(message.embedded); + } + if (message.stage !== 0) { + writer.uint32(24).int32(message.stage); + } + if (message.kind !== 0) { + writer.uint32(32).int32(message.kind); + } + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): PolicySpec { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicySpec(); + while (reader.pos < end) { + const tag = reader.uint32(); + switch (tag >>> 3) { + case 1: + if (tag !== 10) { + break; + } + + message.path = reader.string(); + continue; + case 2: + if (tag !== 18) { + break; + } + + message.embedded = reader.string(); + continue; + case 3: + if (tag !== 24) { + break; + } + + message.stage = reader.int32() as any; + continue; + case 4: + if (tag !== 32) { + break; + } + + message.kind = reader.int32() as any; + continue; + } + if ((tag & 7) === 4 || tag === 0) { + break; + } + reader.skipType(tag & 7); + } + return message; + }, + + fromJSON(object: any): PolicySpec { + return { + path: isSet(object.path) ? String(object.path) : undefined, + embedded: isSet(object.embedded) ? String(object.embedded) : undefined, + stage: isSet(object.stage) ? policySpec_PolicyStageFromJSON(object.stage) : 0, + kind: isSet(object.kind) ? craftingSchema_Material_MaterialTypeFromJSON(object.kind) : 0, + }; + }, + + toJSON(message: PolicySpec): unknown { + const obj: any = {}; + message.path !== undefined && (obj.path = message.path); + message.embedded !== undefined && (obj.embedded = message.embedded); + message.stage !== undefined && (obj.stage = policySpec_PolicyStageToJSON(message.stage)); + message.kind !== undefined && (obj.kind = craftingSchema_Material_MaterialTypeToJSON(message.kind)); + return obj; + }, + + create, I>>(base?: I): PolicySpec { + return PolicySpec.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): PolicySpec { + const message = createBasePolicySpec(); + message.path = object.path ?? undefined; + message.embedded = object.embedded ?? undefined; + message.stage = object.stage ?? 0; + message.kind = object.kind ?? 0; + return message; + }, +}; + type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined; export type DeepPartial = T extends Builtin ? T diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index b3903b99f..996f3fb4e 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -192,6 +192,54 @@ func (CraftingSchema_Material_MaterialType) EnumDescriptor() ([]byte, []int) { return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{0, 1, 0} } +// buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX +// buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX +type PolicySpec_PolicyStage int32 + +const ( + PolicySpec_UNSPECIFIED PolicySpec_PolicyStage = 0 + PolicySpec_PUSH PolicySpec_PolicyStage = 1 +) + +// Enum value maps for PolicySpec_PolicyStage. +var ( + PolicySpec_PolicyStage_name = map[int32]string{ + 0: "UNSPECIFIED", + 1: "PUSH", + } + PolicySpec_PolicyStage_value = map[string]int32{ + "UNSPECIFIED": 0, + "PUSH": 1, + } +) + +func (x PolicySpec_PolicyStage) Enum() *PolicySpec_PolicyStage { + p := new(PolicySpec_PolicyStage) + *p = x + return p +} + +func (x PolicySpec_PolicyStage) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (PolicySpec_PolicyStage) Descriptor() protoreflect.EnumDescriptor { + return file_workflowcontract_v1_crafting_schema_proto_enumTypes[2].Descriptor() +} + +func (PolicySpec_PolicyStage) Type() protoreflect.EnumType { + return &file_workflowcontract_v1_crafting_schema_proto_enumTypes[2] +} + +func (x PolicySpec_PolicyStage) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use PolicySpec_PolicyStage.Descriptor instead. +func (PolicySpec_PolicyStage) EnumDescriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{5, 0} +} + // Schema definition provided by the user to the tool // that defines the schema of the workflowRun type CraftingSchema struct { @@ -351,6 +399,7 @@ type PolicyAttachment struct { // // *PolicyAttachment_Ref // *PolicyAttachment_Name + // *PolicyAttachment_Embedded Policy isPolicyAttachment_Policy `protobuf_oneof:"policy"` // rules to select a material or materials to be validated by the policy. // If none provided, the whole statement will be injected to the policy @@ -413,6 +462,13 @@ func (x *PolicyAttachment) GetName() string { return "" } +func (x *PolicyAttachment) GetEmbedded() *Policy { + if x, ok := x.GetPolicy().(*PolicyAttachment_Embedded); ok { + return x.Embedded + } + return nil +} + func (x *PolicyAttachment) GetSelector() *PolicyAttachment_MaterialSelector { if x != nil { return x.Selector @@ -448,10 +504,239 @@ type PolicyAttachment_Name struct { Name string `protobuf:"bytes,2,opt,name=name,proto3,oneof"` } +type PolicyAttachment_Embedded struct { + // meant to be used to embed the policy in the contract + Embedded *Policy `protobuf:"bytes,6,opt,name=embedded,proto3,oneof"` +} + func (*PolicyAttachment_Ref) isPolicyAttachment_Policy() {} func (*PolicyAttachment_Name) isPolicyAttachment_Policy() {} +func (*PolicyAttachment_Embedded) isPolicyAttachment_Policy() {} + +// Represents a policy to be applied to a material or attestation +type Policy 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 *PolicySpec `protobuf:"bytes,4,opt,name=spec,proto3" json:"spec,omitempty"` +} + +func (x *Policy) Reset() { + *x = Policy{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy) ProtoMessage() {} + +func (x *Policy) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] + 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 Policy.ProtoReflect.Descriptor instead. +func (*Policy) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{3} +} + +func (x *Policy) GetApiVersion() string { + if x != nil { + return x.ApiVersion + } + return "" +} + +func (x *Policy) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *Policy) GetMetadata() *Metadata { + if x != nil { + return x.Metadata + } + return nil +} + +func (x *Policy) GetSpec() *PolicySpec { + if x != nil { + return x.Spec + } + return nil +} + +type Metadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // the name of the policy + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *Metadata) Reset() { + *x = Metadata{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Metadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Metadata) ProtoMessage() {} + +func (x *Metadata) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[4] + 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 Metadata.ProtoReflect.Descriptor instead. +func (*Metadata) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{4} +} + +func (x *Metadata) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type PolicySpec struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Types that are assignable to Source: + // + // *PolicySpec_Path + // *PolicySpec_Embedded + Source isPolicySpec_Source `protobuf_oneof:"source"` + // stage at which this policy will be run. + // Only "push" is supported currently and this field will be ignored + Stage PolicySpec_PolicyStage `protobuf:"varint,3,opt,name=stage,proto3,enum=workflowcontract.v1.PolicySpec_PolicyStage" json:"stage,omitempty"` + // if set, it will match a material kind supported by Chainloop. + Kind CraftingSchema_Material_MaterialType `protobuf:"varint,4,opt,name=kind,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"kind,omitempty"` +} + +func (x *PolicySpec) Reset() { + *x = PolicySpec{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicySpec) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicySpec) ProtoMessage() {} + +func (x *PolicySpec) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[5] + 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 PolicySpec.ProtoReflect.Descriptor instead. +func (*PolicySpec) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{5} +} + +func (m *PolicySpec) GetSource() isPolicySpec_Source { + if m != nil { + return m.Source + } + return nil +} + +func (x *PolicySpec) GetPath() string { + if x, ok := x.GetSource().(*PolicySpec_Path); ok { + return x.Path + } + return "" +} + +func (x *PolicySpec) GetEmbedded() string { + if x, ok := x.GetSource().(*PolicySpec_Embedded); ok { + return x.Embedded + } + return "" +} + +func (x *PolicySpec) GetStage() PolicySpec_PolicyStage { + if x != nil { + return x.Stage + } + return PolicySpec_UNSPECIFIED +} + +func (x *PolicySpec) GetKind() CraftingSchema_Material_MaterialType { + if x != nil { + return x.Kind + } + return CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED +} + +type isPolicySpec_Source interface { + isPolicySpec_Source() +} + +type PolicySpec_Path struct { + // path to a policy script. It might consist of a URI reference + Path string `protobuf:"bytes,1,opt,name=path,proto3,oneof"` +} + +type PolicySpec_Embedded struct { + // embedded source code (only Rego supported currently) + Embedded string `protobuf:"bytes,2,opt,name=embedded,proto3,oneof"` +} + +func (*PolicySpec_Path) isPolicySpec_Source() {} + +func (*PolicySpec_Embedded) isPolicySpec_Source() {} + type CraftingSchema_Runner struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -463,7 +748,7 @@ type CraftingSchema_Runner struct { func (x *CraftingSchema_Runner) Reset() { *x = CraftingSchema_Runner{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -476,7 +761,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[3] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -517,7 +802,7 @@ type CraftingSchema_Material struct { func (x *CraftingSchema_Material) Reset() { *x = CraftingSchema_Material{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[4] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -530,7 +815,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[4] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -593,7 +878,7 @@ type PolicyAttachment_MaterialSelector struct { func (x *PolicyAttachment_MaterialSelector) Reset() { *x = PolicyAttachment_MaterialSelector{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[5] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -606,7 +891,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[5] + 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 { @@ -642,7 +927,7 @@ type PolicyAttachment_PolicyArgument struct { func (x *PolicyAttachment_PolicyArgument) Reset() { *x = PolicyAttachment_PolicyArgument{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[6] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -655,7 +940,7 @@ func (x *PolicyAttachment_PolicyArgument) String() string { func (*PolicyAttachment_PolicyArgument) ProtoMessage() {} func (x *PolicyAttachment_PolicyArgument) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[6] + 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 { @@ -776,7 +1061,7 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0x8a, 0x04, 0x0a, 0x10, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x74, + 0x6c, 0x75, 0x65, 0x22, 0xc5, 0x04, 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, 0x99, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, @@ -789,32 +1074,79 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 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, + 0x65, 0x12, 0x39, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x18, 0x06, 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, - 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, 0x48, 0x0a, 0x04, 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 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, 0x41, 0x74, 0x74, 0x61, - 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 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, 0x1a, 0x4a, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, - 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, - 0x0f, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 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, + 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, 0x48, 0x0a, 0x04, + 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 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, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, + 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 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, 0x1a, 0x4a, + 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, + 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, + 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 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, 0xa4, 0x01, 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, 0x22, 0x8d, 0x02, 0x0a, 0x0a, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 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, 0x41, + 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 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, 0x2e, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, + 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 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, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, + 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, + 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, 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, } var ( @@ -829,34 +1161,43 @@ func file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP() []byte { return file_workflowcontract_v1_crafting_schema_proto_rawDescData } -var file_workflowcontract_v1_crafting_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_workflowcontract_v1_crafting_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 10) 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 - (*CraftingSchema)(nil), // 2: workflowcontract.v1.CraftingSchema - (*Annotation)(nil), // 3: workflowcontract.v1.Annotation - (*PolicyAttachment)(nil), // 4: workflowcontract.v1.PolicyAttachment - (*CraftingSchema_Runner)(nil), // 5: workflowcontract.v1.CraftingSchema.Runner - (*CraftingSchema_Material)(nil), // 6: workflowcontract.v1.CraftingSchema.Material - (*PolicyAttachment_MaterialSelector)(nil), // 7: workflowcontract.v1.PolicyAttachment.MaterialSelector - (*PolicyAttachment_PolicyArgument)(nil), // 8: workflowcontract.v1.PolicyAttachment.PolicyArgument + (PolicySpec_PolicyStage)(0), // 2: workflowcontract.v1.PolicySpec.PolicyStage + (*CraftingSchema)(nil), // 3: workflowcontract.v1.CraftingSchema + (*Annotation)(nil), // 4: workflowcontract.v1.Annotation + (*PolicyAttachment)(nil), // 5: workflowcontract.v1.PolicyAttachment + (*Policy)(nil), // 6: workflowcontract.v1.Policy + (*Metadata)(nil), // 7: workflowcontract.v1.Metadata + (*PolicySpec)(nil), // 8: workflowcontract.v1.PolicySpec + (*CraftingSchema_Runner)(nil), // 9: workflowcontract.v1.CraftingSchema.Runner + (*CraftingSchema_Material)(nil), // 10: workflowcontract.v1.CraftingSchema.Material + (*PolicyAttachment_MaterialSelector)(nil), // 11: workflowcontract.v1.PolicyAttachment.MaterialSelector + (*PolicyAttachment_PolicyArgument)(nil), // 12: workflowcontract.v1.PolicyAttachment.PolicyArgument } var file_workflowcontract_v1_crafting_schema_proto_depIdxs = []int32{ - 6, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material - 5, // 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.PolicyAttachment - 7, // 4: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector - 8, // 5: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.PolicyArgument - 0, // 6: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 1, // 7: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 3, // 8: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 10, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material + 9, // 1: workflowcontract.v1.CraftingSchema.runner:type_name -> workflowcontract.v1.CraftingSchema.Runner + 4, // 2: workflowcontract.v1.CraftingSchema.annotations:type_name -> workflowcontract.v1.Annotation + 5, // 3: workflowcontract.v1.CraftingSchema.policies:type_name -> workflowcontract.v1.PolicyAttachment + 6, // 4: workflowcontract.v1.PolicyAttachment.embedded:type_name -> workflowcontract.v1.Policy + 11, // 5: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector + 12, // 6: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.PolicyArgument + 7, // 7: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata + 8, // 8: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec + 2, // 9: workflowcontract.v1.PolicySpec.stage:type_name -> workflowcontract.v1.PolicySpec.PolicyStage + 1, // 10: workflowcontract.v1.PolicySpec.kind:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 0, // 11: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 1, // 12: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 4, // 13: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation + 14, // [14:14] is the sub-list for method output_type + 14, // [14:14] is the sub-list for method input_type + 14, // [14:14] is the sub-list for extension type_name + 14, // [14:14] is the sub-list for extension extendee + 0, // [0:14] is the sub-list for field type_name } func init() { file_workflowcontract_v1_crafting_schema_proto_init() } @@ -902,7 +1243,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingSchema_Runner); i { + switch v := v.(*Policy); i { case 0: return &v.state case 1: @@ -914,7 +1255,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingSchema_Material); i { + switch v := v.(*Metadata); i { case 0: return &v.state case 1: @@ -926,7 +1267,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PolicyAttachment_MaterialSelector); i { + switch v := v.(*PolicySpec); i { case 0: return &v.state case 1: @@ -938,6 +1279,42 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CraftingSchema_Runner); 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[7].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[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PolicyAttachment_MaterialSelector); 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[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PolicyAttachment_PolicyArgument); i { case 0: return &v.state @@ -953,14 +1330,19 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { file_workflowcontract_v1_crafting_schema_proto_msgTypes[2].OneofWrappers = []interface{}{ (*PolicyAttachment_Ref)(nil), (*PolicyAttachment_Name)(nil), + (*PolicyAttachment_Embedded)(nil), + } + file_workflowcontract_v1_crafting_schema_proto_msgTypes[5].OneofWrappers = []interface{}{ + (*PolicySpec_Path)(nil), + (*PolicySpec_Embedded)(nil), } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_workflowcontract_v1_crafting_schema_proto_rawDesc, - NumEnums: 2, - NumMessages: 7, + NumEnums: 3, + NumMessages: 10, 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 77299c13b..c9a65204d 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -121,6 +121,9 @@ message PolicyAttachment { }, }]; + // meant to be used to embed the policy in the contract + Policy embedded = 6; + option (buf.validate.oneof).required = true; } @@ -144,3 +147,49 @@ message PolicyAttachment { string value = 2 [(buf.validate.field).required = true];; } } + +// Represents a policy to be applied to a material or attestation +message Policy { + string api_version = 1 [(buf.validate.field).string.const = "workflowcontract.chainloop.dev/v1"]; + string kind = 2 [(buf.validate.field).string.const = "Policy"]; + + Metadata metadata = 3 [(buf.validate.field).required = true]; + PolicySpec spec = 4 [(buf.validate.field).required = true]; +} + +message Metadata { + // the name of the policy + string name = 3 [(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", + }, + }]; +} + +message PolicySpec { + oneof source { + // path to a policy script. It might consist of a URI reference + string path = 1; + + // embedded source code (only Rego supported currently) + string embedded = 2; + + option (buf.validate.oneof).required = true; + }; + + // stage at which this policy will be run. + // Only "push" is supported currently and this field will be ignored + PolicyStage stage = 3; + + // if set, it will match a material kind supported by Chainloop. + CraftingSchema.Material.MaterialType kind = 4; + + // buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX + // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX + enum PolicyStage { + UNSPECIFIED = 0; + PUSH = 1; + } +} diff --git a/app/controlplane/api/workflowcontract/v1/policy.pb.go b/app/controlplane/api/workflowcontract/v1/policy.pb.go deleted file mode 100644 index 9cad6ba83..000000000 --- a/app/controlplane/api/workflowcontract/v1/policy.pb.go +++ /dev/null @@ -1,470 +0,0 @@ -// -// 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. - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.31.0 -// protoc (unknown) -// source: workflowcontract/v1/policy.proto - -package v1 - -import ( - _ "buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX -// buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX -type PolicySpec_PolicyStage int32 - -const ( - PolicySpec_UNSPECIFIED PolicySpec_PolicyStage = 0 - PolicySpec_PUSH PolicySpec_PolicyStage = 1 -) - -// Enum value maps for PolicySpec_PolicyStage. -var ( - PolicySpec_PolicyStage_name = map[int32]string{ - 0: "UNSPECIFIED", - 1: "PUSH", - } - PolicySpec_PolicyStage_value = map[string]int32{ - "UNSPECIFIED": 0, - "PUSH": 1, - } -) - -func (x PolicySpec_PolicyStage) Enum() *PolicySpec_PolicyStage { - p := new(PolicySpec_PolicyStage) - *p = x - return p -} - -func (x PolicySpec_PolicyStage) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PolicySpec_PolicyStage) Descriptor() protoreflect.EnumDescriptor { - return file_workflowcontract_v1_policy_proto_enumTypes[0].Descriptor() -} - -func (PolicySpec_PolicyStage) Type() protoreflect.EnumType { - return &file_workflowcontract_v1_policy_proto_enumTypes[0] -} - -func (x PolicySpec_PolicyStage) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PolicySpec_PolicyStage.Descriptor instead. -func (PolicySpec_PolicyStage) EnumDescriptor() ([]byte, []int) { - return file_workflowcontract_v1_policy_proto_rawDescGZIP(), []int{2, 0} -} - -type Policy 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 *PolicySpec `protobuf:"bytes,4,opt,name=spec,proto3" json:"spec,omitempty"` -} - -func (x *Policy) Reset() { - *x = Policy{} - if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_policy_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Policy) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Policy) ProtoMessage() {} - -func (x *Policy) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_policy_proto_msgTypes[0] - 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 Policy.ProtoReflect.Descriptor instead. -func (*Policy) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_policy_proto_rawDescGZIP(), []int{0} -} - -func (x *Policy) GetApiVersion() string { - if x != nil { - return x.ApiVersion - } - return "" -} - -func (x *Policy) GetKind() string { - if x != nil { - return x.Kind - } - return "" -} - -func (x *Policy) GetMetadata() *Metadata { - if x != nil { - return x.Metadata - } - return nil -} - -func (x *Policy) GetSpec() *PolicySpec { - if x != nil { - return x.Spec - } - return nil -} - -type Metadata struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // the name of the policy - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` -} - -func (x *Metadata) Reset() { - *x = Metadata{} - if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_policy_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Metadata) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Metadata) ProtoMessage() {} - -func (x *Metadata) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_policy_proto_msgTypes[1] - 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 Metadata.ProtoReflect.Descriptor instead. -func (*Metadata) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_policy_proto_rawDescGZIP(), []int{1} -} - -func (x *Metadata) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -type PolicySpec struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Types that are assignable to Source: - // - // *PolicySpec_Path - // *PolicySpec_Embedded - Source isPolicySpec_Source `protobuf_oneof:"source"` - // stage at which this policy will be run. - // Only "push" is supported currently and this field will be ignored - Stage PolicySpec_PolicyStage `protobuf:"varint,3,opt,name=stage,proto3,enum=workflowcontract.v1.PolicySpec_PolicyStage" json:"stage,omitempty"` - // if set, it will match a material kind supported by Chainloop. - Kind CraftingSchema_Material_MaterialType `protobuf:"varint,4,opt,name=kind,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"kind,omitempty"` -} - -func (x *PolicySpec) Reset() { - *x = PolicySpec{} - if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_policy_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *PolicySpec) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PolicySpec) ProtoMessage() {} - -func (x *PolicySpec) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_policy_proto_msgTypes[2] - 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 PolicySpec.ProtoReflect.Descriptor instead. -func (*PolicySpec) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_policy_proto_rawDescGZIP(), []int{2} -} - -func (m *PolicySpec) GetSource() isPolicySpec_Source { - if m != nil { - return m.Source - } - return nil -} - -func (x *PolicySpec) GetPath() string { - if x, ok := x.GetSource().(*PolicySpec_Path); ok { - return x.Path - } - return "" -} - -func (x *PolicySpec) GetEmbedded() string { - if x, ok := x.GetSource().(*PolicySpec_Embedded); ok { - return x.Embedded - } - return "" -} - -func (x *PolicySpec) GetStage() PolicySpec_PolicyStage { - if x != nil { - return x.Stage - } - return PolicySpec_UNSPECIFIED -} - -func (x *PolicySpec) GetKind() CraftingSchema_Material_MaterialType { - if x != nil { - return x.Kind - } - return CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED -} - -type isPolicySpec_Source interface { - isPolicySpec_Source() -} - -type PolicySpec_Path struct { - // path to a policy script. It might consist of a URI reference - Path string `protobuf:"bytes,1,opt,name=path,proto3,oneof"` -} - -type PolicySpec_Embedded struct { - // embedded source code (only Rego supported currently) - Embedded string `protobuf:"bytes,2,opt,name=embedded,proto3,oneof"` -} - -func (*PolicySpec_Path) isPolicySpec_Source() {} - -func (*PolicySpec_Embedded) isPolicySpec_Source() {} - -var File_workflowcontract_v1_policy_proto protoreflect.FileDescriptor - -var file_workflowcontract_v1_policy_proto_rawDesc = []byte{ - 0x0a, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, - 0x63, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 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, 0x1a, 0x29, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x69, - 0x6e, 0x67, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 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, 0xa4, 0x01, 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, 0x22, - 0x8d, 0x02, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 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, 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0e, 0x32, 0x2b, 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, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 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, 0x52, 0x04, - 0x6b, 0x69, 0x6e, 0x64, 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, - 0x61, 0x67, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, 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, -} - -var ( - file_workflowcontract_v1_policy_proto_rawDescOnce sync.Once - file_workflowcontract_v1_policy_proto_rawDescData = file_workflowcontract_v1_policy_proto_rawDesc -) - -func file_workflowcontract_v1_policy_proto_rawDescGZIP() []byte { - file_workflowcontract_v1_policy_proto_rawDescOnce.Do(func() { - file_workflowcontract_v1_policy_proto_rawDescData = protoimpl.X.CompressGZIP(file_workflowcontract_v1_policy_proto_rawDescData) - }) - return file_workflowcontract_v1_policy_proto_rawDescData -} - -var file_workflowcontract_v1_policy_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_workflowcontract_v1_policy_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_workflowcontract_v1_policy_proto_goTypes = []interface{}{ - (PolicySpec_PolicyStage)(0), // 0: workflowcontract.v1.PolicySpec.PolicyStage - (*Policy)(nil), // 1: workflowcontract.v1.Policy - (*Metadata)(nil), // 2: workflowcontract.v1.Metadata - (*PolicySpec)(nil), // 3: workflowcontract.v1.PolicySpec - (CraftingSchema_Material_MaterialType)(0), // 4: workflowcontract.v1.CraftingSchema.Material.MaterialType -} -var file_workflowcontract_v1_policy_proto_depIdxs = []int32{ - 2, // 0: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata - 3, // 1: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec - 0, // 2: workflowcontract.v1.PolicySpec.stage:type_name -> workflowcontract.v1.PolicySpec.PolicyStage - 4, // 3: workflowcontract.v1.PolicySpec.kind:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 4, // [4:4] is the sub-list for method output_type - 4, // [4:4] is the sub-list for method input_type - 4, // [4:4] is the sub-list for extension type_name - 4, // [4:4] is the sub-list for extension extendee - 0, // [0:4] is the sub-list for field type_name -} - -func init() { file_workflowcontract_v1_policy_proto_init() } -func file_workflowcontract_v1_policy_proto_init() { - if File_workflowcontract_v1_policy_proto != nil { - return - } - file_workflowcontract_v1_crafting_schema_proto_init() - if !protoimpl.UnsafeEnabled { - file_workflowcontract_v1_policy_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_workflowcontract_v1_policy_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Metadata); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_workflowcontract_v1_policy_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PolicySpec); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - file_workflowcontract_v1_policy_proto_msgTypes[2].OneofWrappers = []interface{}{ - (*PolicySpec_Path)(nil), - (*PolicySpec_Embedded)(nil), - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_workflowcontract_v1_policy_proto_rawDesc, - NumEnums: 1, - NumMessages: 3, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_workflowcontract_v1_policy_proto_goTypes, - DependencyIndexes: file_workflowcontract_v1_policy_proto_depIdxs, - EnumInfos: file_workflowcontract_v1_policy_proto_enumTypes, - MessageInfos: file_workflowcontract_v1_policy_proto_msgTypes, - }.Build() - File_workflowcontract_v1_policy_proto = out.File - file_workflowcontract_v1_policy_proto_rawDesc = nil - file_workflowcontract_v1_policy_proto_goTypes = nil - file_workflowcontract_v1_policy_proto_depIdxs = nil -} diff --git a/app/controlplane/api/workflowcontract/v1/policy.proto b/app/controlplane/api/workflowcontract/v1/policy.proto deleted file mode 100644 index 1c8ab6799..000000000 --- a/app/controlplane/api/workflowcontract/v1/policy.proto +++ /dev/null @@ -1,68 +0,0 @@ -// -// 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. - -syntax = "proto3"; - -package workflowcontract.v1; - -import "buf/validate/validate.proto"; -import "workflowcontract/v1/crafting_schema.proto"; - -option go_package = "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1"; - -message Policy { - string api_version = 1 [(buf.validate.field).string.const = "workflowcontract.chainloop.dev/v1"]; - string kind = 2 [(buf.validate.field).string.const = "Policy"]; - - Metadata metadata = 3 [(buf.validate.field).required = true]; - PolicySpec spec = 4 [(buf.validate.field).required = true]; -} - -message Metadata { - // the name of the policy - string name = 3 [(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", - }, - }]; -} - -message PolicySpec { - oneof source { - // path to a policy script. It might consist of a URI reference - string path = 1; - - // embedded source code (only Rego supported currently) - string embedded = 2; - - option (buf.validate.oneof).required = true; - }; - - // stage at which this policy will be run. - // Only "push" is supported currently and this field will be ignored - PolicyStage stage = 3; - - // if set, it will match a material kind supported by Chainloop. - CraftingSchema.Material.MaterialType kind = 4; - - // buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - enum PolicyStage { - UNSPECIFIED = 0; - PUSH = 1; - } -} diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index 22bc2e87c..d8367f776 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -215,16 +215,21 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { return nil, err } - // Load and validate policies, if any + // Load, validate policies, and embed them in the schema for _, p := range schema.GetPolicies() { spec, err := LoadPolicySpec(p) if err != nil { return nil, fmt.Errorf("validating policy: %w", err) } - _, err = LoadPolicyScriptFromSpec(spec) + script, err := LoadPolicyScriptFromSpec(spec) if err != nil { return nil, fmt.Errorf("loading policy script: %w", err) } + + // embed the script in the policy (if not already) + spec.GetSpec().Source = &schemaapi.PolicySpec_Embedded{Embedded: string(script.Source)} + // Embed the policy in the schema (if not already) + p.Policy = &schemaapi.PolicyAttachment_Embedded{Embedded: spec} } return schema, nil @@ -232,6 +237,12 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { // LoadPolicySpec loads and validates a policy spec from a contract func LoadPolicySpec(attachment *schemaapi.PolicyAttachment) (*schemaapi.Policy, error) { + if attachment.GetEmbedded() != nil { + return attachment.GetEmbedded(), nil + } + + // if policy is not embedded in the contract, we'll look for it + // look for the referenced policy spec (note: loading by `name` is not supported yet) reference := attachment.GetRef() // this method understands env, http and https schemes, and defaults to file system. diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index b4c2bdc08..e8edd9c03 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -19,7 +19,6 @@ import ( "bufio" "bytes" "context" - "encoding/base64" "fmt" "github.com/rs/zerolog" @@ -98,7 +97,7 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation pv.state.Attestation.Policies = append(pv.state.Attestation.Policies, &v12.Policy{ Name: spec.Metadata.Name, Attachment: policyAtt, - Body: base64.StdEncoding.EncodeToString(script.Source), + Body: string(script.Source), Violations: policyViolationsToAttestationViolations(res), }) } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 11ecf8597..a7116ec88 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -17,7 +17,6 @@ package policies import ( "context" - "encoding/base64" "io/fs" "os" "testing" @@ -188,9 +187,7 @@ func (s *testSuite) TestAttestationResult() { s.Len(p.Violations, 0) s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) s.Equal("workflow", p.Name) - body, err := base64.StdEncoding.DecodeString(p.Body) - s.Require().NoError(err) - s.Contains(string(body), "package main") + s.Contains(p.Body, "package main") }) s.Run("failed attestation", func() { @@ -219,9 +216,7 @@ func (s *testSuite) TestAttestationResult() { p := att.Policies[0] s.Len(p.Violations, 1) - body, err := base64.StdEncoding.DecodeString(p.Body) - s.Require().NoError(err) - s.Contains(string(body), "package main") + s.Contains(p.Body, "package main") v := p.Violations[0] s.Equal(p.Name, v.Subject) s.Equal("incorrect runner", v.Message) From 793bd0980734f6653f7a8348f3d813f8bd9d8644 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Fri, 12 Jul 2024 09:55:29 +0200 Subject: [PATCH 31/73] store attestation result in predicate Signed-off-by: Jose I. Paris --- .../renderer/chainloop/chainloop.go | 43 ++++++++++++++++--- .../attestation/renderer/chainloop/v02.go | 36 +++++++++++++++- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/internal/attestation/renderer/chainloop/chainloop.go b/internal/attestation/renderer/chainloop/chainloop.go index c8521e8bb..2d1f56610 100644 --- a/internal/attestation/renderer/chainloop/chainloop.go +++ b/internal/attestation/renderer/chainloop/chainloop.go @@ -20,10 +20,13 @@ import ( "fmt" "time" - v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + structpb "github.com/golang/protobuf/ptypes/struct" "github.com/secure-systems-lab/go-securesystemslib/dsse" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + + v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" crv1 "github.com/google/go-containerregistry/pkg/v1" intoto "github.com/in-toto/attestation/go/v1" @@ -177,18 +180,22 @@ func ExtractPredicate(envelope *dsse.Envelope) (NormalizablePredicate, error) { // 2 - Extract the Chainloop predicate from the in-toto statement switch statement.PredicateType { case PredicateTypeV02: - var predicate *ProvenancePredicateV02 + var predicate ProvenancePredicateV02 if err = extractPredicate(statement, &predicate); err != nil { return nil, fmt.Errorf("extracting predicate: %w", err) } - return predicate, nil + return &predicate, nil default: return nil, fmt.Errorf("unsupported predicate type: %s", statement.PredicateType) } } -func extractPredicate(statement *intoto.Statement, v any) error { +func extractPredicate(statement *intoto.Statement, v *ProvenancePredicateV02) error { + // policies will be handled separately, as it contains a oneof + policiesField := statement.Predicate.GetFields()["policies"] + delete(statement.Predicate.Fields, "policies") + jsonPredicate, err := protojson.Marshal(statement.Predicate) if err != nil { return fmt.Errorf("un-marshaling predicate: %w", err) @@ -198,6 +205,32 @@ func extractPredicate(statement *intoto.Statement, v any) error { return fmt.Errorf("un-marshaling predicate: %w", err) } + policies := make([]*v1.Policy, 0) + for _, policyValue := range policiesField.GetListValue().GetValues() { + var policy v1.Policy + err := valueToProto(policyValue, &policy) + if err != nil { + return fmt.Errorf("un-marshaling policy: %w", err) + } + policies = append(policies, &policy) + } + + v.Policies = policies + + return nil +} + +func valueToProto(value *structpb.Value, m proto.Message) error { + jsonValue, err := protojson.Marshal(value) + if err != nil { + return fmt.Errorf("marshaling value: %w", err) + } + + err = protojson.Unmarshal(jsonValue, m) + if err != nil { + return fmt.Errorf("un-marshaling proto: %w", err) + } + return nil } diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index 696fd491b..8e56eaa03 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -25,6 +25,7 @@ import ( crv1 "github.com/google/go-containerregistry/pkg/v1" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" @@ -153,7 +154,6 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { p := ProvenancePredicateV02{ ProvenancePredicateCommon: predicateCommon(r.builder, r.att), Materials: normalizedMaterials, - Policies: r.att.Policies, } // transform to structpb.Struct in a two steps process @@ -169,9 +169,43 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { return nil, fmt.Errorf("error unmarshaling predicate: %w", err) } + // Policies have oneofs, which are not compatible with the regular json.Marshal. We need to do it separately + policyValues, err := policiesToValues(r.att.Policies) + if err != nil { + return nil, fmt.Errorf("error converting policies to values: %w", err) + } + // Store it in a ListValue struct. + predicate.Fields["policies"] = &structpb.Value{Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{Values: policyValues}}} + return predicate, nil } +func policiesToValues(policies []*v1.Policy) ([]*structpb.Value, error) { + values := make([]*structpb.Value, 0) + for _, pol := range policies { + policyValue, err := protoToValue(pol) + if err != nil { + return nil, fmt.Errorf("error converting policy to value: %w", err) + } + values = append(values, policyValue) + } + + return values, nil +} + +func protoToValue(m proto.Message) (*structpb.Value, error) { + jsonValue, err := protojson.Marshal(m) + if err != nil { + return nil, fmt.Errorf("error marshaling proto: %w", err) + } + value := &structpb.Value{} + if err := protojson.Unmarshal(jsonValue, value); err != nil { + return nil, fmt.Errorf("error unmarshaling json to value: %w", err) + } + + return value, nil +} + func outputMaterials(att *v1.Attestation, onlyOutput bool) ([]*intoto.ResourceDescriptor, error) { // Sort material keys to stabilize output keys := make([]string, 0, len(att.GetMaterials())) From 5844e99ce613aae2befa0a98dd5b4e0d439b899f Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Fri, 12 Jul 2024 10:44:26 +0200 Subject: [PATCH 32/73] add test and remove duplicated field Signed-off-by: Jose I. Paris --- .../frontend/attestation/v1/crafting_state.ts | 19 +-- .../api/attestation/v1/crafting_state.pb.go | 145 ++++++++---------- .../api/attestation/v1/crafting_state.proto | 5 +- internal/attestation/crafter/crafter_test.go | 6 + .../renderer/chainloop/chainloop.go | 13 -- pkg/policies/policies.go | 1 - pkg/policies/policies_test.go | 2 - 7 files changed, 77 insertions(+), 114 deletions(-) diff --git a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts index c8de72c81..e794e465d 100644 --- a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts +++ b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts @@ -106,8 +106,6 @@ export interface Policy { name: string; /** The attachment as in the contract, with arguments and any other metadata */ attachment?: PolicyAttachment; - /** The policy script body (rego) */ - body: string; /** The policy violations, if any */ violations: Policy_Violation[]; } @@ -1172,7 +1170,7 @@ export const Attestation_EnvVarsEntry = { }; function createBasePolicy(): Policy { - return { name: "", attachment: undefined, body: "", violations: [] }; + return { name: "", attachment: undefined, violations: [] }; } export const Policy = { @@ -1183,11 +1181,8 @@ export const Policy = { if (message.attachment !== undefined) { PolicyAttachment.encode(message.attachment, writer.uint32(18).fork()).ldelim(); } - if (message.body !== "") { - writer.uint32(26).string(message.body); - } for (const v of message.violations) { - Policy_Violation.encode(v!, writer.uint32(34).fork()).ldelim(); + Policy_Violation.encode(v!, writer.uint32(26).fork()).ldelim(); } return writer; }, @@ -1218,13 +1213,6 @@ export const Policy = { break; } - message.body = reader.string(); - continue; - case 4: - if (tag !== 34) { - break; - } - message.violations.push(Policy_Violation.decode(reader, reader.uint32())); continue; } @@ -1240,7 +1228,6 @@ export const Policy = { return { name: isSet(object.name) ? String(object.name) : "", attachment: isSet(object.attachment) ? PolicyAttachment.fromJSON(object.attachment) : undefined, - body: isSet(object.body) ? String(object.body) : "", violations: Array.isArray(object?.violations) ? object.violations.map((e: any) => Policy_Violation.fromJSON(e)) : [], @@ -1252,7 +1239,6 @@ export const Policy = { message.name !== undefined && (obj.name = message.name); message.attachment !== undefined && (obj.attachment = message.attachment ? PolicyAttachment.toJSON(message.attachment) : undefined); - message.body !== undefined && (obj.body = message.body); if (message.violations) { obj.violations = message.violations.map((e) => e ? Policy_Violation.toJSON(e) : undefined); } else { @@ -1271,7 +1257,6 @@ export const Policy = { message.attachment = (object.attachment !== undefined && object.attachment !== null) ? PolicyAttachment.fromPartial(object.attachment) : undefined; - message.body = object.body ?? ""; message.violations = object.violations?.map((e) => Policy_Violation.fromPartial(e)) || []; return message; }, diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go index 0b1f3a1f5..23fbbb0aa 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go @@ -171,10 +171,8 @@ type Policy struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` // The attachment as in the contract, with arguments and any other metadata Attachment *v1.PolicyAttachment `protobuf:"bytes,2,opt,name=attachment,proto3" json:"attachment,omitempty"` - // The policy script body (rego) - Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` // The policy violations, if any - Violations []*Policy_Violation `protobuf:"bytes,4,rep,name=violations,proto3" json:"violations,omitempty"` + Violations []*Policy_Violation `protobuf:"bytes,3,rep,name=violations,proto3" json:"violations,omitempty"` } func (x *Policy) Reset() { @@ -223,13 +221,6 @@ func (x *Policy) GetAttachment() *v1.PolicyAttachment { return nil } -func (x *Policy) GetBody() string { - if x != nil { - return x.Body - } - return "" -} - func (x *Policy) GetViolations() []*Policy_Violation { if x != nil { return x.Violations @@ -1086,7 +1077,7 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x56, 0x61, 0x72, 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, 0xa0, 0x03, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x84, 0x03, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 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, @@ -1101,73 +1092,71 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 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, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x61, - 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x4f, 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x07, 0x73, - 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, - 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, - 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, - 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, - 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, - 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, - 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, - 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, - 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, - 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, - 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, - 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, 0x52, 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, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, - 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0a, 0x76, 0x69, 0x6f, + 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, + 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x4f, 0x0a, 0x09, 0x56, + 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, + 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, + 0x01, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, + 0xc8, 0x01, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, 0x02, 0x0a, + 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, + 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, + 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, + 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, + 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, + 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, + 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, + 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x07, 0x72, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, + 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, + 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, + 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, + 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, 0x10, 0x57, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, + 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, + 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, + 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, + 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, + 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, + 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, + 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto index a181e4260..99ca57d79 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto @@ -105,10 +105,9 @@ message Policy { }]; // The attachment as in the contract, with arguments and any other metadata workflowcontract.v1.PolicyAttachment attachment = 2 [(buf.validate.field).required = true]; - // The policy script body (rego) - string body = 3 [(buf.validate.field).required = true]; + // The policy violations, if any - repeated Violation violations = 4; + repeated Violation violations = 3; message Violation { string subject = 1 [(buf.validate.field).required = true]; diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 7268361d5..4e887453b 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -258,6 +258,12 @@ func (s *crafterSuite) TestLoadSchema() { } } +func (s *crafterSuite) TestPolicyCompilation() { + schema, err := crafter.LoadSchema("testdata/contracts/with_rego.yaml") + s.NoError(err) + s.Contains(schema.Policies[0].GetEmbedded().GetSpec().GetEmbedded(), "package main") +} + func (s *crafterSuite) TestResolveEnvVars() { testCases := []struct { name string diff --git a/internal/attestation/renderer/chainloop/chainloop.go b/internal/attestation/renderer/chainloop/chainloop.go index 2d1f56610..8bb9e0c9d 100644 --- a/internal/attestation/renderer/chainloop/chainloop.go +++ b/internal/attestation/renderer/chainloop/chainloop.go @@ -25,7 +25,6 @@ import ( "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" - v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" crv1 "github.com/google/go-containerregistry/pkg/v1" @@ -76,18 +75,6 @@ type ProvenancePredicateCommon struct { RunnerURL string `json:"runnerURL,omitempty"` // Custom annotations Annotations map[string]string `json:"annotations,omitempty"` - // Applied policies - Policies []PolicyPredicate `json:"policies,omitempty"` -} - -// PolicyPredicate represents a policy that has been run against an attestation -type PolicyPredicate struct { - Name string `json:"name"` - Stage string `json:"stage,omitempty"` - // Base64 body of the policy script - Body string `json:"body"` - // optional parameters set as policy inputs - Arguments []v12.PolicyAttachment_PolicyArgument `json:"arguments,omitempty"` } type Metadata struct { diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index e8edd9c03..024182231 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -97,7 +97,6 @@ func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation pv.state.Attestation.Policies = append(pv.state.Attestation.Policies, &v12.Policy{ Name: spec.Metadata.Name, Attachment: policyAtt, - Body: string(script.Source), Violations: policyViolationsToAttestationViolations(res), }) } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index a7116ec88..a0e28e523 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -187,7 +187,6 @@ func (s *testSuite) TestAttestationResult() { s.Len(p.Violations, 0) s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) s.Equal("workflow", p.Name) - s.Contains(p.Body, "package main") }) s.Run("failed attestation", func() { @@ -216,7 +215,6 @@ func (s *testSuite) TestAttestationResult() { p := att.Policies[0] s.Len(p.Violations, 1) - s.Contains(p.Body, "package main") v := p.Violations[0] s.Equal(p.Name, v.Subject) s.Equal("incorrect runner", v.Message) From 8dd32be31c044adbce781d782c368481d334ed16 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Fri, 12 Jul 2024 10:47:51 +0200 Subject: [PATCH 33/73] go mod tidy Signed-off-by: Jose I. Paris --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4ab16bd6b..10b6e9803 100644 --- a/go.mod +++ b/go.mod @@ -263,7 +263,7 @@ require ( github.com/go-playground/form/v4 v4.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 // indirect + github.com/golang/protobuf v1.5.4 github.com/golang/snappy v0.0.4 // indirect github.com/google/certificate-transparency-go v1.1.8 // indirect github.com/google/go-cmp v0.6.0 From 672a6effc98e1967adeabe9279d7bdde22e159fd Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Fri, 12 Jul 2024 11:00:04 +0200 Subject: [PATCH 34/73] fix test Signed-off-by: Jose I. Paris --- .../renderer/chainloop/testdata/attestation.output-2.v0.2.json | 1 + .../renderer/chainloop/testdata/attestation.output.v0.2.json | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json b/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json index 7d18b9a0e..3edaffd22 100644 --- a/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json +++ b/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json @@ -110,6 +110,7 @@ "workflowRunID": "f97a0680-e64b-478a-9eea-df8864fa27f8", "organization": "my-org" }, + "policies": [], "runnerType": "RUNNER_TYPE_UNSPECIFIED" } } diff --git a/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json b/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json index fc3cb78b6..0c82f74ec 100644 --- a/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json +++ b/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json @@ -73,6 +73,7 @@ "workflowID": "54ea7c5c-7592-48ac-9a9f-084b72447184", "workflowRunID": "" }, + "policies": [], "runnerType": "GITHUB_ACTION" } } From 0184ac1ff64ea7ddbd2e19b3e917e74830804823 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Fri, 12 Jul 2024 13:25:30 +0200 Subject: [PATCH 35/73] no need to fix pbstruct transformation server side Signed-off-by: Jose I. Paris --- .../renderer/chainloop/chainloop.go | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/internal/attestation/renderer/chainloop/chainloop.go b/internal/attestation/renderer/chainloop/chainloop.go index 8bb9e0c9d..23ddcf2ff 100644 --- a/internal/attestation/renderer/chainloop/chainloop.go +++ b/internal/attestation/renderer/chainloop/chainloop.go @@ -20,10 +20,8 @@ import ( "fmt" "time" - structpb "github.com/golang/protobuf/ptypes/struct" "github.com/secure-systems-lab/go-securesystemslib/dsse" "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" @@ -179,10 +177,6 @@ func ExtractPredicate(envelope *dsse.Envelope) (NormalizablePredicate, error) { } func extractPredicate(statement *intoto.Statement, v *ProvenancePredicateV02) error { - // policies will be handled separately, as it contains a oneof - policiesField := statement.Predicate.GetFields()["policies"] - delete(statement.Predicate.Fields, "policies") - jsonPredicate, err := protojson.Marshal(statement.Predicate) if err != nil { return fmt.Errorf("un-marshaling predicate: %w", err) @@ -192,32 +186,6 @@ func extractPredicate(statement *intoto.Statement, v *ProvenancePredicateV02) er return fmt.Errorf("un-marshaling predicate: %w", err) } - policies := make([]*v1.Policy, 0) - for _, policyValue := range policiesField.GetListValue().GetValues() { - var policy v1.Policy - err := valueToProto(policyValue, &policy) - if err != nil { - return fmt.Errorf("un-marshaling policy: %w", err) - } - policies = append(policies, &policy) - } - - v.Policies = policies - - return nil -} - -func valueToProto(value *structpb.Value, m proto.Message) error { - jsonValue, err := protojson.Marshal(value) - if err != nil { - return fmt.Errorf("marshaling value: %w", err) - } - - err = protojson.Unmarshal(jsonValue, m) - if err != nil { - return fmt.Errorf("un-marshaling proto: %w", err) - } - return nil } From d42906a78409d616cd9e32d5b8683ac4249c718e Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Fri, 12 Jul 2024 13:43:27 +0200 Subject: [PATCH 36/73] go mod tidy Signed-off-by: Jose I. Paris --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 10b6e9803..4ab16bd6b 100644 --- a/go.mod +++ b/go.mod @@ -263,7 +263,7 @@ require ( github.com/go-playground/form/v4 v4.2.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.4 + github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/certificate-transparency-go v1.1.8 // indirect github.com/google/go-cmp v0.6.0 From d73f34ccbeca8ef43318bb83fad869aa8700b97c Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Mon, 15 Jul 2024 19:58:30 +0200 Subject: [PATCH 37/73] refactor for new and better specs Signed-off-by: Jose I. Paris --- app/cli/cmd/attestation_push.go | 9 +- app/cli/internal/action/attestation_push.go | 57 +- .../frontend/attestation/v1/crafting_state.ts | 40 +- .../workflowcontract/v1/crafting_schema.ts | 139 ++++- .../workflowcontract/v1/crafting_schema.pb.go | 512 +++++++++------- .../workflowcontract/v1/crafting_schema.proto | 15 +- .../api/attestation/v1/crafting_state.pb.go | 205 +++---- .../api/attestation/v1/crafting_state.proto | 11 +- internal/attestation/crafter/crafter.go | 133 +---- .../crafter/materials/materials.go | 36 +- .../attestation/renderer/chainloop/v02.go | 42 +- internal/attestation/renderer/renderer.go | 21 +- .../attestation/renderer/renderer_test.go | 11 +- pkg/policies/policies.go | 272 +++++---- pkg/policies/policies_test.go | 560 ++++++++++-------- pkg/policies/testdata/missing_rego.yaml | 1 + pkg/policies/testdata/sbom_syft.yaml | 1 + .../testdata/sbom_syft_not_typed.yaml | 6 + pkg/policies/testdata/statement.json | 247 ++++++++ pkg/policies/testdata/statement_gitlab.json | 247 ++++++++ .../testdata/statement_missing_runner.json | 245 ++++++++ pkg/policies/testdata/workflow.rego | 5 +- pkg/policies/testdata/workflow.yaml | 1 + pkg/policies/testdata/workflow_embedded.yaml | 14 +- 24 files changed, 1927 insertions(+), 903 deletions(-) create mode 100644 pkg/policies/testdata/sbom_syft_not_typed.yaml create mode 100644 pkg/policies/testdata/statement.json create mode 100644 pkg/policies/testdata/statement_gitlab.json create mode 100644 pkg/policies/testdata/statement_missing_runner.json diff --git a/app/cli/cmd/attestation_push.go b/app/cli/cmd/attestation_push.go index 4cf437a64..39330a9e9 100644 --- a/app/cli/cmd/attestation_push.go +++ b/app/cli/cmd/attestation_push.go @@ -19,11 +19,11 @@ import ( "errors" "fmt" - "github.com/chainloop-dev/chainloop/app/cli/internal/action" "github.com/spf13/cobra" - "github.com/spf13/viper" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + "github.com/chainloop-dev/chainloop/app/cli/internal/action" ) func newAttestationPushCmd() *cobra.Command { @@ -65,10 +65,7 @@ func newAttestationPushCmd() *cobra.Command { a, err := action.NewAttestationPush(&action.AttestationPushOpts{ ActionsOpts: actionOpts, KeyPath: pkPath, BundlePath: bundle, CLIVersion: info.Version, CLIDigest: info.Digest, - SignServerCAPath: signServerCAPath, - CASURI: viper.GetString(confOptions.CASAPI.viperKey), - CASCAPath: viper.GetString(confOptions.CASCA.viperKey), - ConnectionInsecure: flagInsecure, + SignServerCAPath: signServerCAPath, }) if err != nil { return fmt.Errorf("failed to load action: %w", err) diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index 6203cb020..1148c3702 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -21,14 +21,14 @@ import ( "fmt" "time" + "github.com/secure-systems-lab/go-securesystemslib/dsse" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/timestamppb" + pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" "github.com/chainloop-dev/chainloop/internal/attestation/renderer" "github.com/chainloop-dev/chainloop/internal/attestation/signer" - "github.com/chainloop-dev/chainloop/pkg/policies" - "github.com/secure-systems-lab/go-securesystemslib/dsse" - "google.golang.org/grpc" - "google.golang.org/protobuf/types/known/timestamppb" ) type AttestationPushOpts struct { @@ -36,11 +36,6 @@ type AttestationPushOpts struct { KeyPath, CLIVersion, CLIDigest, BundlePath string SignServerCAPath string - - CASURI string - CASCAPath string // optional CA certificate for the CAS connection - // CAS connection insecure flag - ConnectionInsecure bool } type AttestationResult struct { @@ -54,12 +49,6 @@ type AttestationPush struct { c *crafter.Crafter keyPath, cliVersion, cliDigest, bundlePath string signServerCAPath string - - // CAS options - casURI string - // optional CA certificate for the CAS connection - casCAPath string - connectionInsecure bool } func NewAttestationPush(cfg *AttestationPushOpts) (*AttestationPush, error) { @@ -69,16 +58,13 @@ func NewAttestationPush(cfg *AttestationPushOpts) (*AttestationPush, error) { } return &AttestationPush{ - ActionsOpts: cfg.ActionsOpts, - c: c, - keyPath: cfg.KeyPath, - cliVersion: cfg.CLIVersion, - cliDigest: cfg.CLIDigest, - bundlePath: cfg.BundlePath, - signServerCAPath: cfg.SignServerCAPath, - casURI: cfg.CASURI, - casCAPath: cfg.CASCAPath, - connectionInsecure: cfg.ConnectionInsecure, + ActionsOpts: cfg.ActionsOpts, + c: c, + keyPath: cfg.KeyPath, + cliVersion: cfg.CLIVersion, + cliDigest: cfg.CLIDigest, + bundlePath: cfg.BundlePath, + signServerCAPath: cfg.SignServerCAPath, }, nil } @@ -159,32 +145,13 @@ func (action *AttestationPush) Run(ctx context.Context, attestationID string, ru return nil, fmt.Errorf("creating signer: %w", err) } - // Apply policies - pv := policies.NewPolicyVerifier(action.c.CraftingState, &policies.CASConnecitonOpts{ - Insecure: action.connectionInsecure, - CpConn: action.CPConnection, - CasAPI: action.casURI, - CasCA: action.casCAPath, - }, &action.Logger) - violations, err := pv.Verify(ctx) - if err != nil { - return nil, fmt.Errorf("verifying policies: %w", err) - } - - // Log violations - if len(violations) > 0 { - for _, v := range violations { - action.Logger.Error().Msgf("policy violation [%s]: %s", v.Subject, v.Violation) - } - } - renderer, err := renderer.NewAttestationRenderer(action.c.CraftingState, action.cliVersion, action.cliDigest, sig, renderer.WithLogger(action.Logger), renderer.WithBundleOutputPath(action.bundlePath)) if err != nil { return nil, err } - envelope, err := renderer.Render() + envelope, err := renderer.Render(ctx) if err != nil { return nil, err } diff --git a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts index e794e465d..91ad3ab44 100644 --- a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts +++ b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts @@ -9,7 +9,6 @@ import { CraftingSchema_Runner_RunnerType, craftingSchema_Runner_RunnerTypeFromJSON, craftingSchema_Runner_RunnerTypeToJSON, - PolicyAttachment, } from "../../workflowcontract/v1/crafting_schema"; export const protobufPackage = "attestation.v1"; @@ -100,12 +99,13 @@ export interface Attestation_EnvVarsEntry { value: string; } -/** A policy executed against an attestation */ +/** A policy executed against an attestation or material */ export interface Policy { /** The policy name from the policy spec */ name: string; - /** The attachment as in the contract, with arguments and any other metadata */ - attachment?: PolicyAttachment; + materialName: string; + /** The body script of the policy */ + body: string; /** The policy violations, if any */ violations: Policy_Violation[]; } @@ -1170,7 +1170,7 @@ export const Attestation_EnvVarsEntry = { }; function createBasePolicy(): Policy { - return { name: "", attachment: undefined, violations: [] }; + return { name: "", materialName: "", body: "", violations: [] }; } export const Policy = { @@ -1178,11 +1178,14 @@ export const Policy = { if (message.name !== "") { writer.uint32(10).string(message.name); } - if (message.attachment !== undefined) { - PolicyAttachment.encode(message.attachment, writer.uint32(18).fork()).ldelim(); + if (message.materialName !== "") { + writer.uint32(18).string(message.materialName); + } + if (message.body !== "") { + writer.uint32(26).string(message.body); } for (const v of message.violations) { - Policy_Violation.encode(v!, writer.uint32(26).fork()).ldelim(); + Policy_Violation.encode(v!, writer.uint32(34).fork()).ldelim(); } return writer; }, @@ -1206,13 +1209,20 @@ export const Policy = { break; } - message.attachment = PolicyAttachment.decode(reader, reader.uint32()); + message.materialName = reader.string(); continue; case 3: if (tag !== 26) { break; } + message.body = reader.string(); + continue; + case 4: + if (tag !== 34) { + break; + } + message.violations.push(Policy_Violation.decode(reader, reader.uint32())); continue; } @@ -1227,7 +1237,8 @@ export const Policy = { fromJSON(object: any): Policy { return { name: isSet(object.name) ? String(object.name) : "", - attachment: isSet(object.attachment) ? PolicyAttachment.fromJSON(object.attachment) : undefined, + materialName: isSet(object.materialName) ? String(object.materialName) : "", + body: isSet(object.body) ? String(object.body) : "", violations: Array.isArray(object?.violations) ? object.violations.map((e: any) => Policy_Violation.fromJSON(e)) : [], @@ -1237,8 +1248,8 @@ export const Policy = { toJSON(message: Policy): unknown { const obj: any = {}; message.name !== undefined && (obj.name = message.name); - message.attachment !== undefined && - (obj.attachment = message.attachment ? PolicyAttachment.toJSON(message.attachment) : undefined); + message.materialName !== undefined && (obj.materialName = message.materialName); + message.body !== undefined && (obj.body = message.body); if (message.violations) { obj.violations = message.violations.map((e) => e ? Policy_Violation.toJSON(e) : undefined); } else { @@ -1254,9 +1265,8 @@ export const Policy = { fromPartial, I>>(object: I): Policy { const message = createBasePolicy(); message.name = object.name ?? ""; - message.attachment = (object.attachment !== undefined && object.attachment !== null) - ? PolicyAttachment.fromPartial(object.attachment) - : undefined; + message.materialName = object.materialName ?? ""; + message.body = object.body ?? ""; message.violations = object.violations?.map((e) => Policy_Violation.fromPartial(e)) || []; return message; }, 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 ffa9c1ac1..33eb29927 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -19,7 +19,8 @@ export interface CraftingSchema { * It works in addition to the annotations defined in the materials and the runner */ annotations: Annotation[]; - policies: PolicyAttachment[]; + /** Policies to apply to this schema */ + policies?: Policies; } export interface CraftingSchema_Runner { @@ -238,6 +239,13 @@ export interface Annotation { value: string; } +export interface Policies { + /** Policies to be applied to materials */ + materials: PolicyAttachment[]; + /** Policies to be applied to attestation metadata */ + attestation: PolicyAttachment[]; +} + /** A policy to be applied to this contract */ export interface PolicyAttachment { /** policy reference, it might be in URI format. */ @@ -300,8 +308,11 @@ export interface PolicySpec { * Only "push" is supported currently and this field will be ignored */ stage: PolicySpec_PolicyStage; - /** if set, it will match a material kind supported by Chainloop. */ - kind: CraftingSchema_Material_MaterialType; + /** + * if set, it will match any material supported by Chainloop + * except those not having a schema + */ + type: CraftingSchema_Material_MaterialType; } /** @@ -342,7 +353,14 @@ export function policySpec_PolicyStageToJSON(object: PolicySpec_PolicyStage): st } function createBaseCraftingSchema(): CraftingSchema { - return { schemaVersion: "", materials: [], envAllowList: [], runner: undefined, annotations: [], policies: [] }; + return { + schemaVersion: "", + materials: [], + envAllowList: [], + runner: undefined, + annotations: [], + policies: undefined, + }; } export const CraftingSchema = { @@ -362,8 +380,8 @@ export const CraftingSchema = { for (const v of message.annotations) { Annotation.encode(v!, writer.uint32(42).fork()).ldelim(); } - for (const v of message.policies) { - PolicyAttachment.encode(v!, writer.uint32(50).fork()).ldelim(); + if (message.policies !== undefined) { + Policies.encode(message.policies, writer.uint32(50).fork()).ldelim(); } return writer; }, @@ -415,7 +433,7 @@ export const CraftingSchema = { break; } - message.policies.push(PolicyAttachment.decode(reader, reader.uint32())); + message.policies = Policies.decode(reader, reader.uint32()); continue; } if ((tag & 7) === 4 || tag === 0) { @@ -435,7 +453,7 @@ export const CraftingSchema = { envAllowList: Array.isArray(object?.envAllowList) ? object.envAllowList.map((e: any) => String(e)) : [], runner: isSet(object.runner) ? CraftingSchema_Runner.fromJSON(object.runner) : undefined, annotations: Array.isArray(object?.annotations) ? object.annotations.map((e: any) => Annotation.fromJSON(e)) : [], - policies: Array.isArray(object?.policies) ? object.policies.map((e: any) => PolicyAttachment.fromJSON(e)) : [], + policies: isSet(object.policies) ? Policies.fromJSON(object.policies) : undefined, }; }, @@ -459,11 +477,7 @@ export const CraftingSchema = { } else { obj.annotations = []; } - if (message.policies) { - obj.policies = message.policies.map((e) => e ? PolicyAttachment.toJSON(e) : undefined); - } else { - obj.policies = []; - } + message.policies !== undefined && (obj.policies = message.policies ? Policies.toJSON(message.policies) : undefined); return obj; }, @@ -480,7 +494,9 @@ export const CraftingSchema = { ? CraftingSchema_Runner.fromPartial(object.runner) : undefined; message.annotations = object.annotations?.map((e) => Annotation.fromPartial(e)) || []; - message.policies = object.policies?.map((e) => PolicyAttachment.fromPartial(e)) || []; + message.policies = (object.policies !== undefined && object.policies !== null) + ? Policies.fromPartial(object.policies) + : undefined; return message; }, }; @@ -726,6 +742,87 @@ export const Annotation = { }, }; +function createBasePolicies(): Policies { + return { materials: [], attestation: [] }; +} + +export const Policies = { + encode(message: Policies, 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): Policies { + const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBasePolicies(); + 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): Policies { + 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: Policies): 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): Policies { + return Policies.fromPartial(base ?? {}); + }, + + fromPartial, I>>(object: I): Policies { + const message = createBasePolicies(); + message.materials = object.materials?.map((e) => PolicyAttachment.fromPartial(e)) || []; + message.attestation = object.attestation?.map((e) => PolicyAttachment.fromPartial(e)) || []; + return message; + }, +}; + function createBasePolicyAttachment(): PolicyAttachment { return { ref: undefined, name: undefined, embedded: undefined, selector: undefined, disabled: false, with: [] }; } @@ -1149,7 +1246,7 @@ export const Metadata = { }; function createBasePolicySpec(): PolicySpec { - return { path: undefined, embedded: undefined, stage: 0, kind: 0 }; + return { path: undefined, embedded: undefined, stage: 0, type: 0 }; } export const PolicySpec = { @@ -1163,8 +1260,8 @@ export const PolicySpec = { if (message.stage !== 0) { writer.uint32(24).int32(message.stage); } - if (message.kind !== 0) { - writer.uint32(32).int32(message.kind); + if (message.type !== 0) { + writer.uint32(32).int32(message.type); } return writer; }, @@ -1202,7 +1299,7 @@ export const PolicySpec = { break; } - message.kind = reader.int32() as any; + message.type = reader.int32() as any; continue; } if ((tag & 7) === 4 || tag === 0) { @@ -1218,7 +1315,7 @@ export const PolicySpec = { path: isSet(object.path) ? String(object.path) : undefined, embedded: isSet(object.embedded) ? String(object.embedded) : undefined, stage: isSet(object.stage) ? policySpec_PolicyStageFromJSON(object.stage) : 0, - kind: isSet(object.kind) ? craftingSchema_Material_MaterialTypeFromJSON(object.kind) : 0, + type: isSet(object.type) ? craftingSchema_Material_MaterialTypeFromJSON(object.type) : 0, }; }, @@ -1227,7 +1324,7 @@ export const PolicySpec = { message.path !== undefined && (obj.path = message.path); message.embedded !== undefined && (obj.embedded = message.embedded); message.stage !== undefined && (obj.stage = policySpec_PolicyStageToJSON(message.stage)); - message.kind !== undefined && (obj.kind = craftingSchema_Material_MaterialTypeToJSON(message.kind)); + message.type !== undefined && (obj.type = craftingSchema_Material_MaterialTypeToJSON(message.type)); return obj; }, @@ -1240,7 +1337,7 @@ export const PolicySpec = { message.path = object.path ?? undefined; message.embedded = object.embedded ?? undefined; message.stage = object.stage ?? 0; - message.kind = object.kind ?? 0; + message.type = object.type ?? 0; return message; }, }; diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index 996f3fb4e..225f9f50e 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -237,7 +237,7 @@ func (x PolicySpec_PolicyStage) Number() protoreflect.EnumNumber { // Deprecated: Use PolicySpec_PolicyStage.Descriptor instead. func (PolicySpec_PolicyStage) EnumDescriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{5, 0} + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{6, 0} } // Schema definition provided by the user to the tool @@ -255,8 +255,9 @@ type CraftingSchema struct { // List of annotations that can be used to add metadata to the attestation // this metadata can be used later on by the integrations engine to filter and interpolate data // It works in addition to the annotations defined in the materials and the runner - Annotations []*Annotation `protobuf:"bytes,5,rep,name=annotations,proto3" json:"annotations,omitempty"` - Policies []*PolicyAttachment `protobuf:"bytes,6,rep,name=policies,proto3" json:"policies,omitempty"` + 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"` } func (x *CraftingSchema) Reset() { @@ -326,7 +327,7 @@ func (x *CraftingSchema) GetAnnotations() []*Annotation { return nil } -func (x *CraftingSchema) GetPolicies() []*PolicyAttachment { +func (x *CraftingSchema) GetPolicies() *Policies { if x != nil { return x.Policies } @@ -389,6 +390,63 @@ func (x *Annotation) GetValue() string { return "" } +type Policies struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Policies to be applied to materials + Materials []*PolicyAttachment `protobuf:"bytes,1,rep,name=materials,proto3" json:"materials,omitempty"` + // Policies to be applied to attestation metadata + Attestation []*PolicyAttachment `protobuf:"bytes,2,rep,name=attestation,proto3" json:"attestation,omitempty"` +} + +func (x *Policies) Reset() { + *x = Policies{} + if protoimpl.UnsafeEnabled { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policies) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policies) ProtoMessage() {} + +func (x *Policies) ProtoReflect() protoreflect.Message { + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] + 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 Policies.ProtoReflect.Descriptor instead. +func (*Policies) Descriptor() ([]byte, []int) { + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{2} +} + +func (x *Policies) GetMaterials() []*PolicyAttachment { + if x != nil { + return x.Materials + } + return nil +} + +func (x *Policies) GetAttestation() []*PolicyAttachment { + if x != nil { + return x.Attestation + } + return nil +} + // A policy to be applied to this contract type PolicyAttachment struct { state protoimpl.MessageState @@ -412,7 +470,7 @@ type PolicyAttachment struct { func (x *PolicyAttachment) Reset() { *x = PolicyAttachment{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -425,7 +483,7 @@ func (x *PolicyAttachment) String() string { func (*PolicyAttachment) ProtoMessage() {} func (x *PolicyAttachment) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[2] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -438,7 +496,7 @@ func (x *PolicyAttachment) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyAttachment.ProtoReflect.Descriptor instead. func (*PolicyAttachment) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{2} + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{3} } func (m *PolicyAttachment) GetPolicy() isPolicyAttachment_Policy { @@ -530,7 +588,7 @@ type Policy struct { func (x *Policy) Reset() { *x = Policy{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -543,7 +601,7 @@ func (x *Policy) String() string { func (*Policy) ProtoMessage() {} func (x *Policy) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[3] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -556,7 +614,7 @@ func (x *Policy) ProtoReflect() protoreflect.Message { // Deprecated: Use Policy.ProtoReflect.Descriptor instead. func (*Policy) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{3} + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{4} } func (x *Policy) GetApiVersion() string { @@ -599,7 +657,7 @@ type Metadata struct { func (x *Metadata) Reset() { *x = Metadata{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[4] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -612,7 +670,7 @@ func (x *Metadata) String() string { func (*Metadata) ProtoMessage() {} func (x *Metadata) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[4] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -625,7 +683,7 @@ func (x *Metadata) ProtoReflect() protoreflect.Message { // Deprecated: Use Metadata.ProtoReflect.Descriptor instead. func (*Metadata) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{4} + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{5} } func (x *Metadata) GetName() string { @@ -648,14 +706,15 @@ type PolicySpec struct { // stage at which this policy will be run. // Only "push" is supported currently and this field will be ignored Stage PolicySpec_PolicyStage `protobuf:"varint,3,opt,name=stage,proto3,enum=workflowcontract.v1.PolicySpec_PolicyStage" json:"stage,omitempty"` - // if set, it will match a material kind supported by Chainloop. - Kind CraftingSchema_Material_MaterialType `protobuf:"varint,4,opt,name=kind,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"kind,omitempty"` + // if set, it will match any material supported by Chainloop + // except those not having a schema + Type CraftingSchema_Material_MaterialType `protobuf:"varint,4,opt,name=type,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"type,omitempty"` } func (x *PolicySpec) Reset() { *x = PolicySpec{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[5] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -668,7 +727,7 @@ func (x *PolicySpec) String() string { func (*PolicySpec) ProtoMessage() {} func (x *PolicySpec) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[5] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -681,7 +740,7 @@ func (x *PolicySpec) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicySpec.ProtoReflect.Descriptor instead. func (*PolicySpec) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{5} + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{6} } func (m *PolicySpec) GetSource() isPolicySpec_Source { @@ -712,9 +771,9 @@ func (x *PolicySpec) GetStage() PolicySpec_PolicyStage { return PolicySpec_UNSPECIFIED } -func (x *PolicySpec) GetKind() CraftingSchema_Material_MaterialType { +func (x *PolicySpec) GetType() CraftingSchema_Material_MaterialType { if x != nil { - return x.Kind + return x.Type } return CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED } @@ -748,7 +807,7 @@ type CraftingSchema_Runner struct { func (x *CraftingSchema_Runner) Reset() { *x = CraftingSchema_Runner{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[6] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -761,7 +820,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[6] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -802,7 +861,7 @@ type CraftingSchema_Material struct { func (x *CraftingSchema_Material) Reset() { *x = CraftingSchema_Material{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[7] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -815,7 +874,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[7] + 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 { @@ -878,7 +937,7 @@ type PolicyAttachment_MaterialSelector struct { func (x *PolicyAttachment_MaterialSelector) Reset() { *x = PolicyAttachment_MaterialSelector{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[8] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -891,7 +950,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[8] + 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 { @@ -904,7 +963,7 @@ func (x *PolicyAttachment_MaterialSelector) ProtoReflect() protoreflect.Message // Deprecated: Use PolicyAttachment_MaterialSelector.ProtoReflect.Descriptor instead. func (*PolicyAttachment_MaterialSelector) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{2, 0} + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{3, 0} } func (x *PolicyAttachment_MaterialSelector) GetName() string { @@ -927,7 +986,7 @@ type PolicyAttachment_PolicyArgument struct { func (x *PolicyAttachment_PolicyArgument) Reset() { *x = PolicyAttachment_PolicyArgument{} if protoimpl.UnsafeEnabled { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] + mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -940,7 +999,7 @@ func (x *PolicyAttachment_PolicyArgument) String() string { func (*PolicyAttachment_PolicyArgument) ProtoMessage() {} func (x *PolicyAttachment_PolicyArgument) ProtoReflect() protoreflect.Message { - mi := &file_workflowcontract_v1_crafting_schema_proto_msgTypes[9] + 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 { @@ -953,7 +1012,7 @@ func (x *PolicyAttachment_PolicyArgument) ProtoReflect() protoreflect.Message { // Deprecated: Use PolicyAttachment_PolicyArgument.ProtoReflect.Descriptor instead. func (*PolicyAttachment_PolicyArgument) Descriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{2, 1} + return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{3, 1} } func (x *PolicyAttachment_PolicyArgument) GetName() string { @@ -978,7 +1037,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, 0xdb, 0x09, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xd3, 0x09, 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, @@ -998,155 +1057,165 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0x12, 0x41, 0x0a, 0x08, 0x70, - 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, + 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x39, 0x0a, 0x08, 0x70, + 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, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, - 0x6d, 0x65, 0x6e, 0x74, 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, 0xd5, 0x04, 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, 0x24, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xba, 0x48, 0x0d, 0x72, - 0x0b, 0x32, 0x09, 0x5e, 0x5b, 0x5c, 0x77, 0x7c, 0x2d, 0x5d, 0x2b, 0x24, 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, + 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, 0xd5, 0x04, 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, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x10, 0xba, 0x48, 0x0d, 0x72, 0x0b, 0x32, 0x09, 0x5e, 0x5b, 0x5c, 0x77, 0x7c, + 0x2d, 0x5d, 0x2b, 0x24, 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, 0xcf, 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, 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, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xcf, 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, 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, 0xc5, 0x04, 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, 0x99, 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, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x39, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, 0x18, 0x06, 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, 0x48, 0x0a, 0x04, - 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 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, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, - 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 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, 0x1a, 0x4a, - 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, - 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, - 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, - 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 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, 0xa4, 0x01, 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, 0x22, 0x8d, 0x02, 0x0a, 0x0a, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 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, 0x41, - 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, + 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, 0xc5, 0x04, 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, 0x99, 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, 0x48, 0x00, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, + 0x18, 0x06, 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, + 0x48, 0x0a, 0x04, 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 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, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, - 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x6b, 0x69, 0x6e, 0x64, 0x18, 0x04, 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, 0x52, 0x04, 0x6b, 0x69, 0x6e, 0x64, - 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, - 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, 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, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 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, 0x1a, 0x4a, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, + 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 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, 0xa4, 0x01, 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, 0x22, 0x9c, + 0x02, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 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, 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x2b, 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, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, + 0x74, 0x61, 0x67, 0x65, 0x12, 0x5c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 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, 0x74, 0x79, + 0x70, 0x65, 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, + 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, 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, } var ( @@ -1162,42 +1231,45 @@ func file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP() []byte { } var file_workflowcontract_v1_crafting_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 3) -var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 11) 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 (PolicySpec_PolicyStage)(0), // 2: workflowcontract.v1.PolicySpec.PolicyStage (*CraftingSchema)(nil), // 3: workflowcontract.v1.CraftingSchema (*Annotation)(nil), // 4: workflowcontract.v1.Annotation - (*PolicyAttachment)(nil), // 5: workflowcontract.v1.PolicyAttachment - (*Policy)(nil), // 6: workflowcontract.v1.Policy - (*Metadata)(nil), // 7: workflowcontract.v1.Metadata - (*PolicySpec)(nil), // 8: workflowcontract.v1.PolicySpec - (*CraftingSchema_Runner)(nil), // 9: workflowcontract.v1.CraftingSchema.Runner - (*CraftingSchema_Material)(nil), // 10: workflowcontract.v1.CraftingSchema.Material - (*PolicyAttachment_MaterialSelector)(nil), // 11: workflowcontract.v1.PolicyAttachment.MaterialSelector - (*PolicyAttachment_PolicyArgument)(nil), // 12: workflowcontract.v1.PolicyAttachment.PolicyArgument + (*Policies)(nil), // 5: workflowcontract.v1.Policies + (*PolicyAttachment)(nil), // 6: workflowcontract.v1.PolicyAttachment + (*Policy)(nil), // 7: workflowcontract.v1.Policy + (*Metadata)(nil), // 8: workflowcontract.v1.Metadata + (*PolicySpec)(nil), // 9: workflowcontract.v1.PolicySpec + (*CraftingSchema_Runner)(nil), // 10: workflowcontract.v1.CraftingSchema.Runner + (*CraftingSchema_Material)(nil), // 11: workflowcontract.v1.CraftingSchema.Material + (*PolicyAttachment_MaterialSelector)(nil), // 12: workflowcontract.v1.PolicyAttachment.MaterialSelector + (*PolicyAttachment_PolicyArgument)(nil), // 13: workflowcontract.v1.PolicyAttachment.PolicyArgument } var file_workflowcontract_v1_crafting_schema_proto_depIdxs = []int32{ - 10, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material - 9, // 1: workflowcontract.v1.CraftingSchema.runner:type_name -> workflowcontract.v1.CraftingSchema.Runner + 11, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material + 10, // 1: workflowcontract.v1.CraftingSchema.runner:type_name -> workflowcontract.v1.CraftingSchema.Runner 4, // 2: workflowcontract.v1.CraftingSchema.annotations:type_name -> workflowcontract.v1.Annotation - 5, // 3: workflowcontract.v1.CraftingSchema.policies:type_name -> workflowcontract.v1.PolicyAttachment - 6, // 4: workflowcontract.v1.PolicyAttachment.embedded:type_name -> workflowcontract.v1.Policy - 11, // 5: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector - 12, // 6: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.PolicyArgument - 7, // 7: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata - 8, // 8: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec - 2, // 9: workflowcontract.v1.PolicySpec.stage:type_name -> workflowcontract.v1.PolicySpec.PolicyStage - 1, // 10: workflowcontract.v1.PolicySpec.kind:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 0, // 11: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 1, // 12: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 4, // 13: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation - 14, // [14:14] is the sub-list for method output_type - 14, // [14:14] is the sub-list for method input_type - 14, // [14:14] is the sub-list for extension type_name - 14, // [14:14] is the sub-list for extension extendee - 0, // [0:14] is the sub-list for field type_name + 5, // 3: workflowcontract.v1.CraftingSchema.policies:type_name -> workflowcontract.v1.Policies + 6, // 4: workflowcontract.v1.Policies.materials:type_name -> workflowcontract.v1.PolicyAttachment + 6, // 5: workflowcontract.v1.Policies.attestation:type_name -> workflowcontract.v1.PolicyAttachment + 7, // 6: workflowcontract.v1.PolicyAttachment.embedded:type_name -> workflowcontract.v1.Policy + 12, // 7: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector + 13, // 8: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.PolicyArgument + 8, // 9: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata + 9, // 10: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec + 2, // 11: workflowcontract.v1.PolicySpec.stage:type_name -> workflowcontract.v1.PolicySpec.PolicyStage + 1, // 12: workflowcontract.v1.PolicySpec.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 0, // 13: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 1, // 14: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 4, // 15: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation + 16, // [16:16] is the sub-list for method output_type + 16, // [16:16] is the sub-list for method input_type + 16, // [16:16] is the sub-list for extension type_name + 16, // [16:16] is the sub-list for extension extendee + 0, // [0:16] is the sub-list for field type_name } func init() { file_workflowcontract_v1_crafting_schema_proto_init() } @@ -1231,7 +1303,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PolicyAttachment); i { + switch v := v.(*Policies); i { case 0: return &v.state case 1: @@ -1243,7 +1315,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy); i { + switch v := v.(*PolicyAttachment); i { case 0: return &v.state case 1: @@ -1255,7 +1327,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Metadata); i { + switch v := v.(*Policy); i { case 0: return &v.state case 1: @@ -1267,7 +1339,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PolicySpec); i { + switch v := v.(*Metadata); i { case 0: return &v.state case 1: @@ -1279,7 +1351,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingSchema_Runner); i { + switch v := v.(*PolicySpec); i { case 0: return &v.state case 1: @@ -1291,7 +1363,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } file_workflowcontract_v1_crafting_schema_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CraftingSchema_Material); i { + switch v := v.(*CraftingSchema_Runner); i { case 0: return &v.state case 1: @@ -1303,7 +1375,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.(*PolicyAttachment_MaterialSelector); i { + switch v := v.(*CraftingSchema_Material); i { case 0: return &v.state case 1: @@ -1315,6 +1387,18 @@ 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.(*PolicyAttachment_MaterialSelector); 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.(*PolicyAttachment_PolicyArgument); i { case 0: return &v.state @@ -1327,12 +1411,12 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } } } - file_workflowcontract_v1_crafting_schema_proto_msgTypes[2].OneofWrappers = []interface{}{ + file_workflowcontract_v1_crafting_schema_proto_msgTypes[3].OneofWrappers = []interface{}{ (*PolicyAttachment_Ref)(nil), (*PolicyAttachment_Name)(nil), (*PolicyAttachment_Embedded)(nil), } - file_workflowcontract_v1_crafting_schema_proto_msgTypes[5].OneofWrappers = []interface{}{ + file_workflowcontract_v1_crafting_schema_proto_msgTypes[6].OneofWrappers = []interface{}{ (*PolicySpec_Path)(nil), (*PolicySpec_Embedded)(nil), } @@ -1342,7 +1426,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_workflowcontract_v1_crafting_schema_proto_rawDesc, NumEnums: 3, - NumMessages: 10, + NumMessages: 11, 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 c9a65204d..223c7d531 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -34,7 +34,8 @@ message CraftingSchema { // It works in addition to the annotations defined in the materials and the runner repeated Annotation annotations = 5; - repeated PolicyAttachment policies = 6; + // Policies to apply to this schema + Policies policies = 6; message Runner { RunnerType type = 1 [ @@ -106,6 +107,13 @@ message Annotation { string value = 2; } +message Policies { + // Policies to be applied to materials + repeated PolicyAttachment materials = 1; + // Policies to be applied to attestation metadata + repeated PolicyAttachment attestation = 2; +} + // A policy to be applied to this contract message PolicyAttachment { oneof policy { @@ -183,8 +191,9 @@ message PolicySpec { // Only "push" is supported currently and this field will be ignored PolicyStage stage = 3; - // if set, it will match a material kind supported by Chainloop. - CraftingSchema.Material.MaterialType kind = 4; + // if set, it will match any material supported by Chainloop + // except those not having a schema + CraftingSchema.Material.MaterialType type = 4 [(buf.validate.field).enum = { not_in: [1, 2, 3, 10, 11]}]; // buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go index 23fbbb0aa..28b2abe73 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go @@ -161,18 +161,19 @@ func (x *Attestation) GetPolicies() []*Policy { return nil } -// A policy executed against an attestation +// A policy executed against an attestation or material type Policy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The policy name from the policy spec - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // The attachment as in the contract, with arguments and any other metadata - Attachment *v1.PolicyAttachment `protobuf:"bytes,2,opt,name=attachment,proto3" json:"attachment,omitempty"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + MaterialName string `protobuf:"bytes,2,opt,name=material_name,json=materialName,proto3" json:"material_name,omitempty"` + // The body script of the policy + Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` // The policy violations, if any - Violations []*Policy_Violation `protobuf:"bytes,3,rep,name=violations,proto3" json:"violations,omitempty"` + Violations []*Policy_Violation `protobuf:"bytes,4,rep,name=violations,proto3" json:"violations,omitempty"` } func (x *Policy) Reset() { @@ -214,11 +215,18 @@ func (x *Policy) GetName() string { return "" } -func (x *Policy) GetAttachment() *v1.PolicyAttachment { +func (x *Policy) GetMaterialName() string { if x != nil { - return x.Attachment + return x.MaterialName } - return nil + return "" +} + +func (x *Policy) GetBody() string { + if x != nil { + return x.Body + } + return "" } func (x *Policy) GetViolations() []*Policy_Violation { @@ -1077,7 +1085,7 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x56, 0x61, 0x72, 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, 0x84, 0x03, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf6, 0x02, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 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, @@ -1087,76 +1095,75 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 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, 0x4d, 0x0a, 0x0a, 0x61, 0x74, - 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 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, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x0a, 0x61, - 0x74, 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x40, 0x0a, 0x0a, 0x76, 0x69, 0x6f, - 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x4f, 0x0a, 0x09, 0x56, - 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x07, 0x73, 0x75, 0x62, 0x6a, - 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, - 0x01, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, - 0xc8, 0x01, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, 0x02, 0x0a, - 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, - 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x65, - 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, - 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, - 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x2e, 0x0a, - 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, 0x37, 0x0a, - 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, - 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, 0x07, 0x72, - 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, - 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, - 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, - 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, 0x72, 0x61, - 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, 0x10, 0x57, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, 0x77, 0x6f, - 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, - 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, - 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, 0x0a, 0x0f, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0e, - 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2b, - 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0c, 0x6f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, 0x2f, 0x61, - 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, - 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, + 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, + 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x76, + 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x4f, 0x0a, + 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x07, 0x73, 0x75, + 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, + 0xc8, 0x01, 0x01, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, + 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, + 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, + 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, + 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, + 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, + 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, + 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, + 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, + 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, + 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, + 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, + 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, + 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, + 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, + 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, + 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, + 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, + 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1190,9 +1197,8 @@ var file_attestation_v1_crafting_state_proto_goTypes = []interface{}{ (*Commit_Remote)(nil), // 14: attestation.v1.Commit.Remote (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp (v1.CraftingSchema_Runner_RunnerType)(0), // 16: workflowcontract.v1.CraftingSchema.Runner.RunnerType - (*v1.PolicyAttachment)(nil), // 17: workflowcontract.v1.PolicyAttachment - (*v1.CraftingSchema)(nil), // 18: workflowcontract.v1.CraftingSchema - (v1.CraftingSchema_Material_MaterialType)(0), // 19: workflowcontract.v1.CraftingSchema.Material.MaterialType + (*v1.CraftingSchema)(nil), // 17: workflowcontract.v1.CraftingSchema + (v1.CraftingSchema_Material_MaterialType)(0), // 18: workflowcontract.v1.CraftingSchema.Material.MaterialType } var file_attestation_v1_crafting_state_proto_depIdxs = []int32{ 15, // 0: attestation.v1.Attestation.initialized_at:type_name -> google.protobuf.Timestamp @@ -1204,24 +1210,23 @@ var file_attestation_v1_crafting_state_proto_depIdxs = []int32{ 16, // 6: attestation.v1.Attestation.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType 2, // 7: attestation.v1.Attestation.head:type_name -> attestation.v1.Commit 1, // 8: attestation.v1.Attestation.policies:type_name -> attestation.v1.Policy - 17, // 9: attestation.v1.Policy.attachment:type_name -> workflowcontract.v1.PolicyAttachment - 13, // 10: attestation.v1.Policy.violations:type_name -> attestation.v1.Policy.Violation - 15, // 11: attestation.v1.Commit.date:type_name -> google.protobuf.Timestamp - 14, // 12: attestation.v1.Commit.remotes:type_name -> attestation.v1.Commit.Remote - 18, // 13: attestation.v1.CraftingState.input_schema:type_name -> workflowcontract.v1.CraftingSchema - 0, // 14: attestation.v1.CraftingState.attestation:type_name -> attestation.v1.Attestation - 7, // 15: attestation.v1.Attestation.MaterialsEntry.value:type_name -> attestation.v1.Attestation.Material - 10, // 16: attestation.v1.Attestation.Material.string:type_name -> attestation.v1.Attestation.Material.KeyVal - 11, // 17: attestation.v1.Attestation.Material.container_image:type_name -> attestation.v1.Attestation.Material.ContainerImage - 12, // 18: attestation.v1.Attestation.Material.artifact:type_name -> attestation.v1.Attestation.Material.Artifact - 15, // 19: attestation.v1.Attestation.Material.added_at:type_name -> google.protobuf.Timestamp - 19, // 20: attestation.v1.Attestation.Material.material_type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 9, // 21: attestation.v1.Attestation.Material.annotations:type_name -> attestation.v1.Attestation.Material.AnnotationsEntry - 22, // [22:22] is the sub-list for method output_type - 22, // [22:22] is the sub-list for method input_type - 22, // [22:22] is the sub-list for extension type_name - 22, // [22:22] is the sub-list for extension extendee - 0, // [0:22] is the sub-list for field type_name + 13, // 9: attestation.v1.Policy.violations:type_name -> attestation.v1.Policy.Violation + 15, // 10: attestation.v1.Commit.date:type_name -> google.protobuf.Timestamp + 14, // 11: attestation.v1.Commit.remotes:type_name -> attestation.v1.Commit.Remote + 17, // 12: attestation.v1.CraftingState.input_schema:type_name -> workflowcontract.v1.CraftingSchema + 0, // 13: attestation.v1.CraftingState.attestation:type_name -> attestation.v1.Attestation + 7, // 14: attestation.v1.Attestation.MaterialsEntry.value:type_name -> attestation.v1.Attestation.Material + 10, // 15: attestation.v1.Attestation.Material.string:type_name -> attestation.v1.Attestation.Material.KeyVal + 11, // 16: attestation.v1.Attestation.Material.container_image:type_name -> attestation.v1.Attestation.Material.ContainerImage + 12, // 17: attestation.v1.Attestation.Material.artifact:type_name -> attestation.v1.Attestation.Material.Artifact + 15, // 18: attestation.v1.Attestation.Material.added_at:type_name -> google.protobuf.Timestamp + 18, // 19: attestation.v1.Attestation.Material.material_type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 9, // 20: attestation.v1.Attestation.Material.annotations:type_name -> attestation.v1.Attestation.Material.AnnotationsEntry + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name } func init() { file_attestation_v1_crafting_state_proto_init() } diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto index 99ca57d79..e1daab4c4 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto @@ -93,7 +93,7 @@ message Attestation { repeated Policy policies = 10; } -// A policy executed against an attestation +// A policy executed against an attestation or material message Policy { // The policy name from the policy spec string name = 1 [(buf.validate.field) = { @@ -103,11 +103,14 @@ message Policy { id: "name.dns-1123", }, }]; - // The attachment as in the contract, with arguments and any other metadata - workflowcontract.v1.PolicyAttachment attachment = 2 [(buf.validate.field).required = true]; + + string material_name = 2; + + // The body script of the policy + string body = 3 [(buf.validate.field).required = true]; // The policy violations, if any - repeated Violation violations = 3; + repeated Violation violations = 4; message Violation { string subject = 1 [(buf.validate.field).required = true]; diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index d8367f776..7f2ab600d 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -27,23 +27,20 @@ import ( "strings" "time" - "cuelang.org/go/cue/cuecontext" "github.com/bufbuild/protovalidate-go" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/google/go-containerregistry/pkg/authn" "github.com/rs/zerolog" - "github.com/sigstore/cosign/v2/pkg/blob" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/timestamppb" - "sigs.k8s.io/yaml" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter/materials" "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/chainloop-dev/chainloop/internal/ociauth" - "github.com/chainloop-dev/chainloop/pkg/policies/engine" + "github.com/chainloop-dev/chainloop/pkg/policies" ) // StateManager is an interface for managing the state of the crafting process @@ -156,33 +153,6 @@ func (c *Crafter) AlreadyInitialized(ctx context.Context, stateID string) (bool, return c.stateManager.Initialized(ctx, stateID) } -// LoadJSONBytes Extracts raw data in JSON format from different sources, i.e cue or yaml files -func LoadJSONBytes(rawData []byte, extension string) ([]byte, error) { - var jsonRawData []byte - var err error - - switch extension { - case ".yaml", ".yml": - jsonRawData, err = yaml.YAMLToJSON(rawData) - if err != nil { - return nil, err - } - case ".cue": - ctx := cuecontext.New() - v := ctx.CompileBytes(rawData) - jsonRawData, err = v.MarshalJSON() - if err != nil { - return nil, err - } - case ".json": - jsonRawData = rawData - default: - return nil, errors.New("unsupported file format") - } - - return jsonRawData, nil -} - func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { // Extract json formatted data content, err := loadFileOrURL(pathOrURI) @@ -190,7 +160,7 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { return nil, err } - jsonSchemaRaw, err := LoadJSONBytes(content, filepath.Ext(pathOrURI)) + jsonSchemaRaw, err := materials.LoadJSONBytes(content, filepath.Ext(pathOrURI)) if err != nil { return nil, err } @@ -216,14 +186,25 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { } // Load, validate policies, and embed them in the schema - for _, p := range schema.GetPolicies() { - spec, err := LoadPolicySpec(p) + if err = validateAndPreloadPolicies(schema.GetPolicies().GetMaterials()); err != nil { + return nil, fmt.Errorf("validating policies: %w", err) + } + if err = validateAndPreloadPolicies(schema.GetPolicies().GetAttestation()); err != nil { + return nil, fmt.Errorf("validating policies: %w", err) + } + + return schema, nil +} + +func validateAndPreloadPolicies(pols []*schemaapi.PolicyAttachment) error { + for _, p := range pols { + spec, err := policies.LoadPolicySpec(p) if err != nil { - return nil, fmt.Errorf("validating policy: %w", err) + return fmt.Errorf("validating policy: %w", err) } - script, err := LoadPolicyScriptFromSpec(spec) + script, err := policies.LoadPolicyScriptFromSpec(spec) if err != nil { - return nil, fmt.Errorf("loading policy script: %w", err) + return fmt.Errorf("loading policy script: %w", err) } // embed the script in the policy (if not already) @@ -232,66 +213,7 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { p.Policy = &schemaapi.PolicyAttachment_Embedded{Embedded: spec} } - return schema, nil -} - -// LoadPolicySpec loads and validates a policy spec from a contract -func LoadPolicySpec(attachment *schemaapi.PolicyAttachment) (*schemaapi.Policy, error) { - if attachment.GetEmbedded() != nil { - return attachment.GetEmbedded(), nil - } - - // if policy is not embedded in the contract, we'll look for it - - // look for the referenced policy spec (note: loading by `name` is not supported yet) - reference := attachment.GetRef() - // this method understands env, http and https schemes, and defaults to file system. - rawData, err := blob.LoadFileOrURL(reference) - if err != nil { - return nil, fmt.Errorf("loading policy spec: %w", err) - } - jsonContent, err := LoadJSONBytes(rawData, filepath.Ext(reference)) - if err != nil { - return nil, fmt.Errorf("loading policy spec: %w", err) - } - var policy schemaapi.Policy - if err := protojson.Unmarshal(jsonContent, &policy); err != nil { - return nil, fmt.Errorf("unmarshalling policy spec: %w", err) - } - // Validate just in case - validator, err := protovalidate.New() - if err != nil { - return nil, fmt.Errorf("validating policy spec: %w", err) - } - err = validator.Validate(&policy) - if err != nil { - return nil, fmt.Errorf("validating policy spec: %w", err) - } - - return &policy, nil -} - -// LoadPolicyScriptFromSpec loads a policy referenced from the spec -func LoadPolicyScriptFromSpec(spec *schemaapi.Policy) (*engine.Policy, error) { - var content []byte - var err error - - switch source := spec.GetSpec().GetSource().(type) { - case *schemaapi.PolicySpec_Embedded: - content = []byte(source.Embedded) - case *schemaapi.PolicySpec_Path: - content, err = blob.LoadFileOrURL(source.Path) - if err != nil { - return nil, fmt.Errorf("loading policy content: %w", err) - } - default: - return nil, fmt.Errorf("policy spec is empty") - } - - return &engine.Policy{ - Name: spec.GetMetadata().GetName(), - Source: content, - }, nil + return nil } // Initialize the temporary file with the content of the schema @@ -656,13 +578,20 @@ func (c *Crafter) addMaterial(ctx context.Context, m *schemaapi.CraftingSchema_M return fmt.Errorf("validation error: %w", err) } + // Validate policies + pv := policies.NewPolicyVerifier(c.CraftingState.InputSchema, c.logger) + policyResults, err := pv.VerifyMaterial(ctx, mt, value) + if err != nil { + return fmt.Errorf("error applying policies to material: %w", err) + } + // store policy results + c.CraftingState.Attestation.Policies = append(c.CraftingState.Attestation.Policies, policyResults...) + // 5 - Attach it to state - if mt != nil { - if c.CraftingState.Attestation.Materials == nil { - c.CraftingState.Attestation.Materials = map[string]*api.Attestation_Material{m.Name: mt} - } - c.CraftingState.Attestation.Materials[m.Name] = mt + if c.CraftingState.Attestation.Materials == nil { + c.CraftingState.Attestation.Materials = map[string]*api.Attestation_Material{m.Name: mt} } + c.CraftingState.Attestation.Materials[m.Name] = mt // 6 - Persist state if err := c.stateManager.Write(ctx, attestationID, c.CraftingState); err != nil { diff --git a/internal/attestation/crafter/materials/materials.go b/internal/attestation/crafter/materials/materials.go index 426d0bef2..45793effe 100644 --- a/internal/attestation/crafter/materials/materials.go +++ b/internal/attestation/crafter/materials/materials.go @@ -24,14 +24,17 @@ import ( "time" "code.cloudfoundry.org/bytefmt" + "cuelang.org/go/cue/cuecontext" "github.com/bufbuild/protovalidate-go" - schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/google/go-containerregistry/pkg/authn" cr_v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/rs/zerolog" "google.golang.org/protobuf/types/known/timestamppb" + "sigs.k8s.io/yaml" + + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/casclient" ) var ( @@ -207,3 +210,30 @@ func Craft(ctx context.Context, materialSchema *schemaapi.CraftingSchema_Materia return m, nil } + +// LoadJSONBytes Extracts raw data in JSON format from different sources, i.e cue or yaml files +func LoadJSONBytes(rawData []byte, extension string) ([]byte, error) { + var jsonRawData []byte + var err error + + switch extension { + case ".yaml", ".yml": + jsonRawData, err = yaml.YAMLToJSON(rawData) + if err != nil { + return nil, err + } + case ".cue": + ctx := cuecontext.New() + v := ctx.CompileBytes(rawData) + jsonRawData, err = v.MarshalJSON() + if err != nil { + return nil, err + } + case ".json": + jsonRawData = rawData + default: + return nil, errors.New("unsupported file format") + } + + return jsonRawData, nil +} diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index 8e56eaa03..9cd67b8d5 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -25,7 +25,6 @@ import ( crv1 "github.com/google/go-containerregistry/pkg/v1" "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/structpb" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" @@ -41,7 +40,12 @@ const PredicateTypeV02 = "chainloop.dev/attestation/v0.2" type ProvenancePredicateV02 struct { *ProvenancePredicateCommon Materials []*intoto.ResourceDescriptor `json:"materials,omitempty"` - Policies []*v1.Policy `json:"policies,omitempty"` + Policies map[string]*PolicyEvaluation `json:"policies,omitempty"` +} + +type PolicyEvaluation struct { + Material string `json:"material,omitempty"` + Violations map[string]string `json:"violations,omitempty"` } type RendererV02 struct { @@ -169,43 +173,9 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { return nil, fmt.Errorf("error unmarshaling predicate: %w", err) } - // Policies have oneofs, which are not compatible with the regular json.Marshal. We need to do it separately - policyValues, err := policiesToValues(r.att.Policies) - if err != nil { - return nil, fmt.Errorf("error converting policies to values: %w", err) - } - // Store it in a ListValue struct. - predicate.Fields["policies"] = &structpb.Value{Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{Values: policyValues}}} - return predicate, nil } -func policiesToValues(policies []*v1.Policy) ([]*structpb.Value, error) { - values := make([]*structpb.Value, 0) - for _, pol := range policies { - policyValue, err := protoToValue(pol) - if err != nil { - return nil, fmt.Errorf("error converting policy to value: %w", err) - } - values = append(values, policyValue) - } - - return values, nil -} - -func protoToValue(m proto.Message) (*structpb.Value, error) { - jsonValue, err := protojson.Marshal(m) - if err != nil { - return nil, fmt.Errorf("error marshaling proto: %w", err) - } - value := &structpb.Value{} - if err := protojson.Unmarshal(jsonValue, value); err != nil { - return nil, fmt.Errorf("error unmarshaling json to value: %w", err) - } - - return value, nil -} - func outputMaterials(att *v1.Attestation, onlyOutput bool) ([]*intoto.ResourceDescriptor, error) { // Sort material keys to stabilize output keys := make([]string, 0, len(att.GetMaterials())) diff --git a/internal/attestation/renderer/renderer.go b/internal/attestation/renderer/renderer.go index d9f1f253e..ac7d6ce8f 100644 --- a/internal/attestation/renderer/renderer.go +++ b/internal/attestation/renderer/renderer.go @@ -17,6 +17,7 @@ package renderer import ( "bytes" + "context" "encoding/base64" "encoding/json" "encoding/pem" @@ -24,9 +25,6 @@ import ( "fmt" "os" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop" - chainloopsigner "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" intoto "github.com/in-toto/attestation/go/v1" "github.com/rs/zerolog" "github.com/secure-systems-lab/go-securesystemslib/dsse" @@ -36,11 +34,17 @@ import ( sigstoresigner "github.com/sigstore/sigstore/pkg/signature" sigdsee "github.com/sigstore/sigstore/pkg/signature/dsse" "google.golang.org/protobuf/encoding/protojson" + + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop" + chainloopsigner "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" ) type AttestationRenderer struct { logger zerolog.Logger att *v1.Attestation + schema *schemaapi.CraftingSchema renderer r signer sigstoresigner.Signer dsseSigner sigstoresigner.Signer @@ -73,6 +77,7 @@ func NewAttestationRenderer(state *v1.CraftingState, builderVersion, builderDige r := &AttestationRenderer{ logger: zerolog.Nop(), att: state.GetAttestation(), + schema: state.GetInputSchema(), dsseSigner: sigdsee.WrapSigner(signer, "application/vnd.in-toto+json"), signer: signer, renderer: chainloop.NewChainloopRendererV02(state.GetAttestation(), builderVersion, builderDigest), @@ -87,7 +92,7 @@ func NewAttestationRenderer(state *v1.CraftingState, builderVersion, builderDige // Attestation (dsee envelope) -> { message: { Statement(in-toto): [subject, predicate] }, signature: "sig" }. // NOTE: It currently only supports cosign key based signing. -func (ab *AttestationRenderer) Render() (*dsse.Envelope, error) { +func (ab *AttestationRenderer) Render(ctx context.Context) (*dsse.Envelope, error) { ab.logger.Debug().Msg("generating in-toto statement") statement, err := ab.renderer.Statement() @@ -99,6 +104,14 @@ func (ab *AttestationRenderer) Render() (*dsse.Envelope, error) { return nil, fmt.Errorf("validating intoto statement: %w", err) } + // validate attestation-level policies + //pv := policies.NewPolicyVerifier(ab.schema, &ab.logger) + //polcyResult, err := pv.VerifyStatement(ctx, statement) + //if err != nil { + // return nil, fmt.Errorf("applying policies to statement: %w", err) + //} + // insert policy results into statement + rawStatement, err := protojson.Marshal(statement) if err != nil { return nil, err diff --git a/internal/attestation/renderer/renderer_test.go b/internal/attestation/renderer/renderer_test.go index 549d6ba1c..41bcfc348 100644 --- a/internal/attestation/renderer/renderer_test.go +++ b/internal/attestation/renderer/renderer_test.go @@ -25,14 +25,15 @@ import ( "os" "testing" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" - "github.com/chainloop-dev/chainloop/internal/attestation/signer/cosign" "github.com/rs/zerolog" "github.com/secure-systems-lab/go-securesystemslib/dsse" "github.com/sigstore/sigstore/pkg/signature" sigdsee "github.com/sigstore/sigstore/pkg/signature/dsse" "github.com/stretchr/testify/suite" + + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" + "github.com/chainloop-dev/chainloop/internal/attestation/signer/cosign" ) type rendererSuite struct { @@ -68,7 +69,7 @@ func (s *rendererSuite) TestRender() { renderer, err := NewAttestationRenderer(s.cs, "", "", s.sv) s.Require().NoError(err) - envelope, err := renderer.Render() + envelope, err := renderer.Render(context.TODO()) s.NoError(err) _, err = s.dsseVerifier.Verify(context.TODO(), envelope) @@ -81,7 +82,7 @@ func (s *rendererSuite) TestRender() { renderer, err := NewAttestationRenderer(s.cs, "", "", doubleWrapper) s.Require().NoError(err) - envelope, err := renderer.Render() + envelope, err := renderer.Render(context.TODO()) s.NoError(err) _, err = s.dsseVerifier.Verify(context.TODO(), envelope) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 024182231..84edbd327 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -16,143 +16,188 @@ package policies import ( - "bufio" - "bytes" "context" + "errors" "fmt" + "os" + "path/filepath" + "github.com/bufbuild/protovalidate-go" + intoto "github.com/in-toto/attestation/go/v1" "github.com/rs/zerolog" - "google.golang.org/grpc" + "github.com/sigstore/cosign/v2/pkg/blob" "google.golang.org/protobuf/encoding/protojson" - pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" - v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - "github.com/chainloop-dev/chainloop/internal/attestation/crafter" v12 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/casclient" - "github.com/chainloop-dev/chainloop/internal/grpcconn" - + "github.com/chainloop-dev/chainloop/internal/attestation/crafter/materials" "github.com/chainloop-dev/chainloop/pkg/policies/engine" "github.com/chainloop-dev/chainloop/pkg/policies/engine/rego" ) type PolicyVerifier struct { - state *v12.CraftingState - casOpts *CASConnecitonOpts - logger *zerolog.Logger + schema *v1.CraftingSchema + logger *zerolog.Logger } -type CASConnecitonOpts struct { - CasAPI, CasCA string - Insecure bool - CpConn *grpc.ClientConn -} - -func NewPolicyVerifier(state *v12.CraftingState, opts *CASConnecitonOpts, logger *zerolog.Logger) *PolicyVerifier { +func NewPolicyVerifier(schema *v1.CraftingSchema, logger *zerolog.Logger) *PolicyVerifier { // only Rego engine is currently supported - return &PolicyVerifier{state: state, casOpts: opts, logger: logger} + return &PolicyVerifier{schema: schema, logger: logger} } -// Verify verifies that the statement is compliant with the policies present in the schema -func (pv *PolicyVerifier) Verify(ctx context.Context) ([]*engine.PolicyViolation, error) { - violations := make([]*engine.PolicyViolation, 0) - policies := pv.state.GetInputSchema().GetPolicies() - for _, policyAtt := range policies { - if policyAtt.Disabled { - // policy is disabled - pv.logger.Warn().Msgf("policy [name: %s, ref: %s] disabled", policyAtt.GetName(), policyAtt.GetRef()) - continue +// VerifyMaterial applies all required policies to a material +func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Attestation_Material, artifactPath string) ([]*v12.Policy, error) { + result := make([]*v12.Policy, 0) + policies, err := pv.requiredPoliciesForMaterial(material) + if err != nil { + return nil, fmt.Errorf("error getting required policies for material: %w", err) + } + for _, policy := range policies { + // 1. load the policy spec + spec, err := LoadPolicySpec(policy) + if err != nil { + return nil, fmt.Errorf("failed to load policy spec: %w", err) + } + + // load the policy script (rego) + script, err := LoadPolicyScriptFromSpec(spec) + if err != nil { + return nil, fmt.Errorf("failed to load policy content: %w", err) + } + + // Load material content + subject, err := getMaterialContent(material, artifactPath) + if err != nil { + return nil, fmt.Errorf("failed to load material content: %w", err) + } + + pv.logger.Debug().Msgf("evaluating policy %s", spec.Metadata.Name) + + // verify the policy + ng := getPolicyEngine(spec) + res, err := ng.Verify(ctx, script, subject) + if err != nil { + return nil, fmt.Errorf("failed to verify policy: %w", err) } + result = append(result, &v12.Policy{ + Name: spec.GetMetadata().GetName(), + MaterialName: material.GetArtifact().GetId(), + Body: string(script.Source), + Violations: engineViolationsToApiViolations(res), + }) + } + + return result, nil +} + +// VerifyStatement verifies that the statement is compliant with the policies present in the schema +func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto.Statement) ([]*v12.Policy, error) { + result := make([]*v12.Policy, 0) + policies := pv.schema.GetPolicies().GetAttestation() + for _, policyAtt := range policies { // 1. load the policy spec - spec, err := crafter.LoadPolicySpec(policyAtt) + spec, err := LoadPolicySpec(policyAtt) if err != nil { return nil, fmt.Errorf("failed to load policy spec: %w", err) } + // it's expected statements can only be validated by policy of type ATTESTATION + if spec.GetSpec().GetType() != v1.CraftingSchema_Material_ATTESTATION { + continue + } + // 2. load the policy script (rego) - script, err := crafter.LoadPolicyScriptFromSpec(spec) + script, err := LoadPolicyScriptFromSpec(spec) if err != nil { return nil, fmt.Errorf("failed to load policy content: %w", err) } - // 3. load the affected material (or the whole attestation) - material, err := pv.loadSubject(ctx, policyAtt, spec) + pv.logger.Debug().Msgf("evaluating policy %s", spec.Metadata.Name) + + material, err := protojson.Marshal(statement) if err != nil { - return nil, fmt.Errorf("failed to load policy subject: %w", err) + return nil, fmt.Errorf("failed to load material content: %w", err) } - pv.logger.Debug().Msgf("evaluating policy %s", spec.Metadata.Name) - // 4. verify the policy ng := getPolicyEngine(spec) res, err := ng.Verify(ctx, script, material) if err != nil { return nil, fmt.Errorf("failed to verify policy: %w", err) } - violations = append(violations, res...) // 5. Store result in the attestation itself (for the renderer to include them in the predicate) - pv.state.Attestation.Policies = append(pv.state.Attestation.Policies, &v12.Policy{ + result = append(result, &v12.Policy{ Name: spec.Metadata.Name, - Attachment: policyAtt, + Body: string(script.Source), Violations: policyViolationsToAttestationViolations(res), }) } - return violations, nil + return result, nil } -// load the subject of the policy. -func (pv *PolicyVerifier) loadSubject(ctx context.Context, attachment *v1.PolicyAttachment, spec *v1.Policy) ([]byte, error) { - state := pv.state +func engineViolationsToApiViolations(input []*engine.PolicyViolation) []*v12.Policy_Violation { + res := make([]*v12.Policy_Violation, 0) + for _, v := range input { + res = append(res, &v12.Policy_Violation{ + Subject: v.Subject, + Message: v.Violation, + }) + } - // Load the affected material or attestation, and checks if the expected name and type match - name := attachment.GetSelector().GetName() - // if name selector is not set, the subject will become the full crafting state - if name == "" { - return protojson.Marshal(state.GetAttestation()) + return res +} + +func getMaterialContent(material *v12.Attestation_Material, artifactPath string) ([]byte, error) { + if material.InlineCas { + return material.GetArtifact().GetContent(), nil } - // if name is set, we want a specific material - for k, m := range state.GetAttestation().GetMaterials() { - if k == name { - if spec.GetSpec().GetKind() != v1.CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED && spec.GetSpec().GetKind() != m.GetMaterialType() { - // If policy wasn't meant to be evaluated against this type of material, raise an error - return nil, fmt.Errorf("invalid material type: %s, policy expected: %s", m.GetMaterialType(), spec.GetSpec().GetKind()) - } - return pv.getMaterialPayload(ctx, m) - } + if artifactPath == "" { + return nil, errors.New("artifact path required") } - return nil, fmt.Errorf("no material found with name %s", name) + // read content from local filesystem + return os.ReadFile(artifactPath) } -// Gets the material payload from the CAS -func (pv *PolicyVerifier) getMaterialPayload(ctx context.Context, m *v12.Attestation_Material) ([]byte, error) { - if m.InlineCas { - return m.GetArtifact().GetContent(), nil - } +func (pv *PolicyVerifier) requiredPoliciesForMaterial(material *v12.Attestation_Material) ([]*v1.PolicyAttachment, error) { + result := make([]*v1.PolicyAttachment, 0) + policies := pv.schema.GetPolicies().GetMaterials() - // Use the CAS to look for the material - var b bytes.Buffer - w := bufio.NewWriter(&b) + for _, policyAtt := range policies { + // load the policy spec + spec, err := LoadPolicySpec(policyAtt) + if err != nil { + return nil, fmt.Errorf("failed to load policy spec: %w", err) + } - client, err := pv.getCASClient(pb.CASCredentialsServiceGetRequest_ROLE_DOWNLOADER, m.GetArtifact().GetDigest()) - if err != nil { - return nil, err - } - err = client.Download(ctx, w, m.GetArtifact().GetDigest()) - if err != nil { - return nil, fmt.Errorf("failed to download artifact: %w", err) - } - err = w.Flush() - if err != nil { - return nil, fmt.Errorf("failed to download artifact: %w", err) + specType := spec.GetSpec().GetType() + materialType := material.GetMaterialType() + filteredName := policyAtt.GetSelector().GetName() + + // if spec has a type, and it's different to the material type, skip + if specType != v1.CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED && specType != materialType { + // types don't match, continue + continue + } + + if filteredName != "" && filteredName != material.GetArtifact().GetId() { + // a filer exists and doesn't match + continue + } + + // no type nor name to match, we can't guess anything + if specType == v1.CraftingSchema_Material_MATERIAL_TYPE_UNSPECIFIED && filteredName == "" { + continue + } + + result = append(result, policyAtt) } - return b.Bytes(), nil + return result, nil } // getPolicyEngine returns a PolicyEngine implementation to evaluate a given policy. @@ -171,34 +216,61 @@ func policyViolationsToAttestationViolations(violations []*engine.PolicyViolatio return } -// We need to create a connection for every single artifact, because it depends on the digest -func (pv *PolicyVerifier) getCASClient(role pb.CASCredentialsServiceGetRequest_Role, digest string) (*casclient.Client, error) { - // Retrieve temporary credentials for uploading - client := pb.NewCASCredentialsServiceClient(pv.casOpts.CpConn) - resp, err := client.Get(context.Background(), &pb.CASCredentialsServiceGetRequest{ - Role: role, - Digest: digest, - }) - if err != nil { - return nil, err +// LoadPolicySpec loads and validates a policy spec from a contract +func LoadPolicySpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { + if attachment.GetEmbedded() != nil { + return attachment.GetEmbedded(), nil } - if pv.casOpts.Insecure { - pv.logger.Warn().Msg("API contacted in insecure mode") - } + // if policy is not embedded in the contract, we'll look for it - var opts = []grpcconn.Option{ - grpcconn.WithInsecure(pv.casOpts.Insecure), + // look for the referenced policy spec (note: loading by `name` is not supported yet) + reference := attachment.GetRef() + // this method understands env, http and https schemes, and defaults to file system. + rawData, err := blob.LoadFileOrURL(reference) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) } - - if pv.casOpts.CasCA != "" { - opts = append(opts, grpcconn.WithCAFile(pv.casOpts.CasCA)) + jsonContent, err := materials.LoadJSONBytes(rawData, filepath.Ext(reference)) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) } - - conn, err := grpcconn.New(pv.casOpts.CasAPI, resp.Result.Token, opts...) + var policy v1.Policy + if err := protojson.Unmarshal(jsonContent, &policy); err != nil { + return nil, fmt.Errorf("unmarshalling policy spec: %w", err) + } + // Validate just in case + validator, err := protovalidate.New() if err != nil { - return nil, fmt.Errorf("failed to create cas client: %w", err) + return nil, fmt.Errorf("validating policy spec: %w", err) + } + err = validator.Validate(&policy) + if err != nil { + return nil, fmt.Errorf("validating policy spec: %w", err) + } + + return &policy, nil +} + +// LoadPolicyScriptFromSpec loads a policy referenced from the spec +func LoadPolicyScriptFromSpec(spec *v1.Policy) (*engine.Policy, error) { + var content []byte + var err error + + switch source := spec.GetSpec().GetSource().(type) { + case *v1.PolicySpec_Embedded: + content = []byte(source.Embedded) + case *v1.PolicySpec_Path: + content, err = blob.LoadFileOrURL(source.Path) + if err != nil { + return nil, fmt.Errorf("loading policy content: %w", err) + } + default: + return nil, fmt.Errorf("policy spec is empty") } - return casclient.New(conn, casclient.WithLogger(*pv.logger)), nil + return &engine.Policy{ + Name: spec.GetMetadata().GetName(), + Source: content, + }, nil } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index a0e28e523..b96ecd710 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -21,9 +21,10 @@ import ( "os" "testing" + intoto "github.com/in-toto/attestation/go/v1" "github.com/rs/zerolog" "github.com/stretchr/testify/suite" - "golang.org/x/exp/slices" + "google.golang.org/protobuf/encoding/protojson" v12 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" @@ -32,354 +33,429 @@ import ( func (s *testSuite) TestVerifyAttestations() { cases := []struct { name string - state *v1.CraftingState + schema *v12.CraftingSchema + statement string + npolicies int violations int wantErr error }{ { name: "happy path, test attestation properties", - state: &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, }, }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, - }, }, + statement: "testdata/statement.json", + npolicies: 1, }, { name: "wrong runner", + npolicies: 1, violations: 1, - state: &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ + statement: "testdata/statement_gitlab.json", + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, }, }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, - }, }, }, { name: "missing runner", + npolicies: 1, violations: 1, - state: &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, }, }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - }, }, + statement: "testdata/statement_missing_runner.json", }, { name: "wrong policy", wantErr: &fs.PathError{}, - state: &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/wrong_policy.yaml"}}, }, }, }, + statement: "testdata/statement.json", }, { name: "missing rego policy", wantErr: &fs.PathError{}, - state: &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/missing_rego.yaml"}}, }, }, }, + statement: "testdata/statement.json", }, { name: "embedded rego policy", - state: &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow_embedded.yaml"}}, }, }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - }, }, + statement: "testdata/statement.json", + npolicies: 1, }, { name: "embedded rego policy violations", - state: &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow_embedded.yaml"}}, }, }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "wrongname", - }, - }, }, + npolicies: 1, violations: 1, + statement: "testdata/statement_missing_runner.json", }, } for _, tc := range cases { s.Run(tc.name, func() { - verifier := NewPolicyVerifier(tc.state, nil, &s.logger) + verifier := NewPolicyVerifier(tc.schema, &s.logger) + stContent, err := os.ReadFile(tc.statement) + s.Require().NoError(err) + var statement intoto.Statement + err = protojson.Unmarshal(stContent, &statement) + s.Require().NoError(err) - res, err := verifier.Verify(context.TODO()) + res, err := verifier.VerifyStatement(context.TODO(), &statement) if tc.wantErr != nil { // #nosec G601 s.ErrorAs(err, &tc.wantErr) return } s.Require().NoError(err) - if tc.violations > 0 { - s.Len(res, tc.violations) + s.Len(res, tc.npolicies) + if tc.npolicies > 0 { + s.Len(res[0].Violations, tc.violations) } }) } } -func (s *testSuite) TestAttestationResult() { - s.Run("successful attestation", func() { - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ - {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, - }, - }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, - }, - } - - verifier := NewPolicyVerifier(state, nil, &s.logger) - - res, err := verifier.Verify(context.TODO()) - s.Require().NoError(err) - s.Len(res, 0) - - att := state.GetAttestation() - s.Len(att.Policies, 1) - - p := att.Policies[0] - s.Len(p.Violations, 0) - s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) - s.Equal("workflow", p.Name) - }) - - s.Run("failed attestation", func() { - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ - {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, - }, - }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, - }, - } - - verifier := NewPolicyVerifier(state, nil, &s.logger) - - res, err := verifier.Verify(context.TODO()) - s.Require().NoError(err) - s.Len(res, 1) - - att := state.GetAttestation() - s.Len(att.Policies, 1) - - p := att.Policies[0] - s.Len(p.Violations, 1) - v := p.Violations[0] - s.Equal(p.Name, v.Subject) - s.Equal("incorrect runner", v.Message) - }) - - s.Run("multiple successful policies", func() { - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ - {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, - {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, - }, - }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, - Materials: map[string]*v1.Attestation_Material{ - "vex": { - MaterialType: v12.CraftingSchema_Material_OPENVEX, +// +//func (s *testSuite) TestAttestationResult() { +// s.Run("successful attestation", func() { +// schema := &v12.CraftingSchema{ +// Policies: []*v12.PolicyAttachment{ +// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, +// }, +// } +// statement := &v1.Attestation{ +// Workflow: &v1.WorkflowMetadata{ +// Name: "policytest", +// }, +// RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, +// } +// +// verifier := NewPolicyVerifier(schema, &s.logger) +// +// res, err := verifier.VerifyStatement(context.TODO(), nil) +// s.Require().NoError(err) +// s.Len(res, 0) +// +// att := state.GetAttestation() +// s.Len(att.Policies, 1) +// +// p := att.Policies[0] +// s.Len(p.Violations, 0) +// s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) +// s.Equal("workflow", p.Name) +// }) +// +// s.Run("failed attestation", func() { +// state := &v1.CraftingState{ +// InputSchema: &v12.CraftingSchema{ +// Policies: []*v12.PolicyAttachment{ +// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, +// }, +// }, +// Attestation: &v1.Attestation{ +// Workflow: &v1.WorkflowMetadata{ +// Name: "policytest", +// }, +// RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, +// }, +// } +// +// verifier := NewPolicyVerifier(state, &s.logger) +// +// res, err := verifier.VerifyStatement(context.TODO()) +// s.Require().NoError(err) +// s.Len(res, 1) +// +// att := state.GetAttestation() +// s.Len(att.Policies, 1) +// +// p := att.Policies[0] +// s.Len(p.Violations, 1) +// v := p.Violations[0] +// s.Equal(p.Name, v.Subject) +// s.Equal("incorrect runner", v.Message) +// }) +// +// s.Run("multiple successful policies", func() { +// state := &v1.CraftingState{ +// InputSchema: &v12.CraftingSchema{ +// Policies: []*v12.PolicyAttachment{ +// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, +// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, +// }, +// }, +// Attestation: &v1.Attestation{ +// Workflow: &v1.WorkflowMetadata{ +// Name: "policytest", +// }, +// RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, +// Materials: map[string]*v1.Attestation_Material{ +// "vex": { +// MaterialType: v12.CraftingSchema_Material_OPENVEX, +// }, +// }, +// }, +// } +// +// verifier := NewPolicyVerifier(state, &s.logger) +// +// res, err := verifier.VerifyStatement(context.TODO()) +// s.Require().NoError(err) +// s.Len(res, 0) +// att := state.GetAttestation() +// s.Len(att.Policies, 2) +// s.Len(att.Policies[0].Violations, 0) +// s.Len(att.Policies[1].Violations, 0) +// }) +// +// s.Run("partial success", func() { +// state := &v1.CraftingState{ +// InputSchema: &v12.CraftingSchema{ +// Policies: []*v12.PolicyAttachment{ +// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, +// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, +// }, +// }, +// Attestation: &v1.Attestation{ +// Workflow: &v1.WorkflowMetadata{ +// Name: "policytest", +// }, +// RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, +// Materials: map[string]*v1.Attestation_Material{ +// "vex": { +// MaterialType: v12.CraftingSchema_Material_OPENVEX, +// }, +// }, +// }, +// } +// +// verifier := NewPolicyVerifier(state, &s.logger) +// +// res, err := verifier.VerifyStatement(context.TODO()) +// s.Require().NoError(err) +// s.Greater(len(res), 0) +// att := state.GetAttestation() +// s.Len(att.Policies, 2) +// +// // Check that only 1 policy failed +// index := slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { +// return p.Name == "workflow" +// }) +// p := att.Policies[index] +// s.Len(p.Violations, 1) +// +// index = slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { +// return p.Name == "materials" +// }) +// p = att.Policies[index] +// s.Len(p.Violations, 0) +// }) +//} + +func (s *testSuite) TestMaterialSelectionCriteria() { + attNoFilterPolicyTyped := &v12.PolicyAttachment{ + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, + } + attFilteredPolicyTyped := &v12.PolicyAttachment{ + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, + Selector: &v12.PolicyAttachment_MaterialSelector{Name: "sbom"}, + } + attFilteredPolicyNotTyped := &v12.PolicyAttachment{ + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft_not_typed.yaml"}, + Selector: &v12.PolicyAttachment_MaterialSelector{Name: "custom-material"}, + } + testcases := []struct { + name string + policies []*v12.PolicyAttachment + material *v1.Attestation_Material + wantErr bool + result int + }{ + { + name: "attachment with no filter, policy with type, matched material", + policies: []*v12.PolicyAttachment{attNoFilterPolicyTyped}, + material: &v1.Attestation_Material{MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON}, + result: 1, + }, + { + name: "attachment with no filter, policy with type, non matched material", + policies: []*v12.PolicyAttachment{attNoFilterPolicyTyped}, + material: &v1.Attestation_Material{MaterialType: v12.CraftingSchema_Material_SBOM_CYCLONEDX_JSON}, + result: 0, + }, + { + name: "attachment with filter, policy with type, matched material", + policies: []*v12.PolicyAttachment{attFilteredPolicyTyped}, + material: &v1.Attestation_Material{ + M: &v1.Attestation_Material_Artifact_{ + Artifact: &v1.Attestation_Material_Artifact{ + Id: "sbom", }, }, - }, - } - - verifier := NewPolicyVerifier(state, nil, &s.logger) - - res, err := verifier.Verify(context.TODO()) - s.Require().NoError(err) - s.Len(res, 0) - att := state.GetAttestation() - s.Len(att.Policies, 2) - s.Len(att.Policies[0].Violations, 0) - s.Len(att.Policies[1].Violations, 0) - }) - - s.Run("partial success", func() { - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Policies: []*v12.PolicyAttachment{ - {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, - {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, + MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON}, + result: 1, + }, + { + name: "attachment with filter, policy with type, unmatched material", + policies: []*v12.PolicyAttachment{attFilteredPolicyTyped}, + material: &v1.Attestation_Material{ + M: &v1.Attestation_Material_Artifact_{ + Artifact: &v1.Attestation_Material_Artifact{ + Id: "not-the-sbom-you-expect", + }, }, - }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", + MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON}, + result: 0, + }, + { + name: "attachment with no filter, policy without type, matched material", + policies: []*v12.PolicyAttachment{attFilteredPolicyNotTyped}, + material: &v1.Attestation_Material{ + M: &v1.Attestation_Material_Artifact_{ + Artifact: &v1.Attestation_Material_Artifact{ + Id: "custom-material", + }, }, - RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, - Materials: map[string]*v1.Attestation_Material{ - "vex": { - MaterialType: v12.CraftingSchema_Material_OPENVEX, + MaterialType: v12.CraftingSchema_Material_ATTESTATION}, + result: 1, + }, + { + name: "attachment with no filter, policy without type, unmatched material", + policies: []*v12.PolicyAttachment{attFilteredPolicyNotTyped}, + material: &v1.Attestation_Material{ + M: &v1.Attestation_Material_Artifact_{ + Artifact: &v1.Attestation_Material_Artifact{ + Id: "not-the-material-you-expect", }, }, - }, - } - - verifier := NewPolicyVerifier(state, nil, &s.logger) - - res, err := verifier.Verify(context.TODO()) - s.Require().NoError(err) - s.Greater(len(res), 0) - att := state.GetAttestation() - s.Len(att.Policies, 2) - - // Check that only 1 policy failed - index := slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { - return p.Name == "workflow" - }) - p := att.Policies[index] - s.Len(p.Violations, 1) + MaterialType: v12.CraftingSchema_Material_ATTESTATION}, + result: 0, + }, + } - index = slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { - return p.Name == "materials" + for _, tc := range testcases { + s.Run(tc.name, func() { + schema := &v12.CraftingSchema{ + Policies: &v12.Policies{ + Materials: tc.policies, + }, + } + pv := NewPolicyVerifier(schema, &s.logger) + atts, err := pv.requiredPoliciesForMaterial(tc.material) + s.Require().NoError(err) + s.Require().Len(atts, tc.result) }) - p = att.Policies[index] - s.Len(p.Violations, 0) - }) + } } -func (s *testSuite) TestInlineMaterial() { +func (s *testSuite) TestValidInlineMaterial() { content, err := os.ReadFile("testdata/sbom-spdx.json") s.Require().NoError(err) - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Materials: []*v12.CraftingSchema_Material{ - { - Name: "sbom", - Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, - }, - }, - Policies: []*v12.PolicyAttachment{ - { - Selector: &v12.PolicyAttachment_MaterialSelector{Name: "sbom"}, - Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, - }, + schema := &v12.CraftingSchema{ + Materials: []*v12.CraftingSchema_Material{ + { + Name: "sbom", + Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, }, }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - Materials: map[string]*v1.Attestation_Material{ - "sbom": { - MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, - M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ - Content: content, - }, - }, - InlineCas: true, + Policies: &v12.Policies{ + Materials: []*v12.PolicyAttachment{ + { + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, }, }, + Attestation: nil, }, } - verifier := NewPolicyVerifier(state, nil, &s.logger) + material := &v1.Attestation_Material{ + M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ + Content: content, + }}, + MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + InlineCas: true, + } - res, err := verifier.Verify(context.TODO()) - s.Require().NoError(err) - s.Len(res, 0) + verifier := NewPolicyVerifier(schema, &s.logger) - att := state.GetAttestation() - s.Len(att.Policies, 1) - s.Len(att.Policies[0].Violations, 0) + res, err := verifier.VerifyMaterial(context.TODO(), material, "") + s.Require().NoError(err) + s.Len(res, 1) + s.Equal("made-with-syft", res[0].Name) + s.Len(res[0].Violations, 0) } func (s *testSuite) TestInvalidInlineMaterial() { - state := &v1.CraftingState{ - InputSchema: &v12.CraftingSchema{ - Materials: []*v12.CraftingSchema_Material{ - { - Name: "sbom", - Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, - }, - }, - Policies: []*v12.PolicyAttachment{ - { - Selector: &v12.PolicyAttachment_MaterialSelector{Name: "sbom"}, - Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, - }, + schema := &v12.CraftingSchema{ + Materials: []*v12.CraftingSchema_Material{ + { + Name: "sbom", + Type: v12.CraftingSchema_Material_SBOM_SPDX_JSON, }, }, - Attestation: &v1.Attestation{ - Workflow: &v1.WorkflowMetadata{ - Name: "policytest", - }, - Materials: map[string]*v1.Attestation_Material{ - "sbom": { - MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, - M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ - Content: []byte(`{"this": { "is": "not", "a": "sbom"}}`), - }, - }, - InlineCas: true, + Policies: &v12.Policies{ + Materials: []*v12.PolicyAttachment{ + { + Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, }, }, + Attestation: nil, }, } + material := &v1.Attestation_Material{ + M: &v1.Attestation_Material_Artifact_{Artifact: &v1.Attestation_Material_Artifact{ + Content: []byte(`{"this": { "is": "not", "a": "sbom"}}`), + }}, + MaterialType: v12.CraftingSchema_Material_SBOM_SPDX_JSON, + InlineCas: true, + } - verifier := NewPolicyVerifier(state, nil, &s.logger) + verifier := NewPolicyVerifier(schema, &s.logger) - res, err := verifier.Verify(context.TODO()) + res, err := verifier.VerifyMaterial(context.TODO(), material, "") s.Require().NoError(err) s.Len(res, 1) + s.Equal("made-with-syft", res[0].Name) + s.Len(res[0].Violations, 1) + s.Equal("made-with-syft", res[0].Violations[0].Subject) + s.Equal("Not made with syft", res[0].Violations[0].Message) } type testSuite struct { diff --git a/pkg/policies/testdata/missing_rego.yaml b/pkg/policies/testdata/missing_rego.yaml index 0f326aa1e..df8b6ba5c 100644 --- a/pkg/policies/testdata/missing_rego.yaml +++ b/pkg/policies/testdata/missing_rego.yaml @@ -3,4 +3,5 @@ kind: Policy metadata: name: missing-rego spec: + type: ATTESTATION path: this_is_a_missing.rego diff --git a/pkg/policies/testdata/sbom_syft.yaml b/pkg/policies/testdata/sbom_syft.yaml index 4fa4d9a1a..ef90f448b 100644 --- a/pkg/policies/testdata/sbom_syft.yaml +++ b/pkg/policies/testdata/sbom_syft.yaml @@ -3,4 +3,5 @@ kind: Policy metadata: name: made-with-syft spec: + type: SBOM_SPDX_JSON path: testdata/sbom_syft.rego diff --git a/pkg/policies/testdata/sbom_syft_not_typed.yaml b/pkg/policies/testdata/sbom_syft_not_typed.yaml new file mode 100644 index 000000000..4fa4d9a1a --- /dev/null +++ b/pkg/policies/testdata/sbom_syft_not_typed.yaml @@ -0,0 +1,6 @@ +apiVersion: workflowcontract.chainloop.dev/v1 +kind: Policy +metadata: + name: made-with-syft +spec: + path: testdata/sbom_syft.rego diff --git a/pkg/policies/testdata/statement.json b/pkg/policies/testdata/statement.json new file mode 100644 index 000000000..6103b25e0 --- /dev/null +++ b/pkg/policies/testdata/statement.json @@ -0,0 +1,247 @@ +{ + "_type": "https://in-toto.io/Statement/v1", + "subject": [ + { + "name": "chainloop.workflow.chainloop-vault-release", + "digest": { + "sha256": "9ae495a85891eb1130fefc17bc89940c9aa96acb8355c26a3e0d73a5097d41d4" + } + }, + { + "name": "git.head", + "digest": { + "sha1": "53f95f066b620172301e2a3879e7d593da05727e" + }, + "annotations": { + "author.email": "devel@chainloop.dev", + "author.name": "Developer", + "date": "2024-07-12T10:16:04Z", + "message": "chore(vulns): fix CVEs in base image (#1088)\n\nSigned-off-by: Jose I. Paris ", + "remotes": [ + { + "name": "origin", + "url": "https://github.com/chainloop-dev/chainloop" + } + ] + } + } + ], + "predicateType": "chainloop.dev/attestation/v0.2", + "predicate": { + "buildType": "chainloop.dev/workflowrun/v0.1", + "builder": { + "id": "chainloop.dev/cli/0.90.1@sha256:431a0765636854095f0c78d01b61eb5558abe7c8de1608aa93eef1530deee0b6" + }, + "env": { + "GITHUB_ACTOR": "jiparis", + "GITHUB_REF": "refs/tags/v0.93.7", + "GITHUB_REPOSITORY": "chainloop-dev/chainloop", + "GITHUB_REPOSITORY_OWNER": "chainloop-dev", + "GITHUB_RUN_ID": "9906853011", + "GITHUB_SHA": "53f95f066b620172301e2a3879e7d593da05727e", + "RUNNER_NAME": "GitHub Actions 193", + "RUNNER_OS": "Linux" + }, + "materials": [ + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782291120414953", + "chainloop.material.type": "SBOM_CYCLONEDX_JSON" + }, + "digest": { + "sha256": "bc449b71c4a47f2f69b514f27e1d61250ff0af0cc554a68d331b40042d90a3da" + }, + "name": "cas.cyclonedx.json" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782293352471920", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "972ca204670aee23ed070619333fb04410ed996bf3c063ff88d35de0702fd478" + }, + "name": "chainloop-cli-0.93.7-darwin-amd64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782295934163620", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "27e4efa094adef0dc5375da7bce70437dde9d35d1e20598240debfc318f374da" + }, + "name": "chainloop-cli-0.93.7-darwin-amd64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782297645680131", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "389ea065be2dd50d07b27619b8594d4738b2c86481db969f62dd549e579af1e2" + }, + "name": "chainloop-cli-0.93.7-darwin-arm64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782300158976415", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "47d5c22ee0f56bf3e7eed5c283fe66e5f61a7a9e913b9af1550dd07e71ac09e1" + }, + "name": "chainloop-cli-0.93.7-darwin-arm64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782301800977382", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "a57b0b11a51b8ebbc9d421bd68e6e82fd021f4e87742780ef30f0aaca0bdd1c2" + }, + "name": "chainloop-cli-0.93.7-linux-amd64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782304541799505", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "754dea96fc2addc0fdb70f725686fd4b5e01a1aa69a1ed0726e4d08866400d42" + }, + "name": "chainloop-cli-0.93.7-linux-amd64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782306140039811", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "c63ee103397001d2e9727d30d02a4ce4e55b7e32da55f042a414c7424b42b21d" + }, + "name": "chainloop-cli-0.93.7-linux-arm64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782308650938558", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "b5c7c73c9d4cd325b8da64135c28685715e8e19f6b48357eaf1a02e693734f37" + }, + "name": "chainloop-cli-0.93.7-linux-arm64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782309843066922", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "897f1dfc64736dd66ea8881ab07689d59e1bc147c45da0baa1de416834a46a3d" + }, + "name": "checksums.txt" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782311062937592", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "2f804aa3b95a81802c24e384e5e87e86f02ec23d043c9c4d3aa9243ee866b60b" + }, + "name": "checksums.txt.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782311526704542", + "chainloop.material.type": "SBOM_CYCLONEDX_JSON" + }, + "digest": { + "sha256": "8b53305ead21a9ede6e0e3aee2fcc04f04796716e1a2b566ce03f3f8cbc2b130" + }, + "name": "controlplane.cyclonedx.json" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782313410977824", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "91c0b92358109bfc31ea4c58902d9b7f4f582ff9c4782fb276a685e914d3cc82" + }, + "name": "cosign.pub" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782315689903312", + "chainloop.material.type": "HELM_CHART" + }, + "digest": { + "sha256": "7cbbda1e5ab71fef561c0f123f5f584c8e0de523d4da80379599ce7a05c04c1f" + }, + "name": "chainloop-0.93.7.tar.gz" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782317669410353", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "4a8eb6f9ae76460b682e7e9eb5504df9f7f2b2250d9c5cb63204442e265e2c5a" + }, + "name": "ghcr.io/chainloop-dev/chainloop/control-plane" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782318334142313", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "4d329b2aee79b35ec5e6c462be5d8000565d5ccd13602427cd889fc91c187fc8" + }, + "name": "ghcr.io/chainloop-dev/chainloop/artifact-cas" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782319034635257", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "571a5543151d651cbc62679c3f50c2e6cadfd2ff20279374c6d6106b3f70560f" + }, + "name": "ghcr.io/chainloop-dev/chainloop/cli" + } + ], + "metadata": { + "finishedAt": "2024-07-12T11:05:19.808858785Z", + "initializedAt": "2024-07-12T11:04:48.604833219Z", + "name": "chainloop-vault-release", + "organization": "read-only-demo", + "project": "chainloop", + "team": "", + "workflowID": "2acc7ee5-21d1-4500-9ca4-2d25748a1ce0", + "workflowRunID": "37dd3d94-06e3-483f-83c2-18b1137e73ee" + }, + "runnerType": "GITHUB_ACTION", + "runnerURL": "https://github.com/chainloop-dev/chainloop/actions/runs/9906853011" + } +} \ No newline at end of file diff --git a/pkg/policies/testdata/statement_gitlab.json b/pkg/policies/testdata/statement_gitlab.json new file mode 100644 index 000000000..affd5a8f9 --- /dev/null +++ b/pkg/policies/testdata/statement_gitlab.json @@ -0,0 +1,247 @@ +{ + "_type": "https://in-toto.io/Statement/v1", + "subject": [ + { + "name": "chainloop.workflow.chainloop-vault-release", + "digest": { + "sha256": "9ae495a85891eb1130fefc17bc89940c9aa96acb8355c26a3e0d73a5097d41d4" + } + }, + { + "name": "git.head", + "digest": { + "sha1": "53f95f066b620172301e2a3879e7d593da05727e" + }, + "annotations": { + "author.email": "devel@chainloop.dev", + "author.name": "Developer", + "date": "2024-07-12T10:16:04Z", + "message": "chore(vulns): fix CVEs in base image (#1088)\n\nSigned-off-by: Jose I. Paris ", + "remotes": [ + { + "name": "origin", + "url": "https://github.com/chainloop-dev/chainloop" + } + ] + } + } + ], + "predicateType": "chainloop.dev/attestation/v0.2", + "predicate": { + "buildType": "chainloop.dev/workflowrun/v0.1", + "builder": { + "id": "chainloop.dev/cli/0.90.1@sha256:431a0765636854095f0c78d01b61eb5558abe7c8de1608aa93eef1530deee0b6" + }, + "env": { + "GITHUB_ACTOR": "jiparis", + "GITHUB_REF": "refs/tags/v0.93.7", + "GITHUB_REPOSITORY": "chainloop-dev/chainloop", + "GITHUB_REPOSITORY_OWNER": "chainloop-dev", + "GITHUB_RUN_ID": "9906853011", + "GITHUB_SHA": "53f95f066b620172301e2a3879e7d593da05727e", + "RUNNER_NAME": "GitHub Actions 193", + "RUNNER_OS": "Linux" + }, + "materials": [ + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782291120414953", + "chainloop.material.type": "SBOM_CYCLONEDX_JSON" + }, + "digest": { + "sha256": "bc449b71c4a47f2f69b514f27e1d61250ff0af0cc554a68d331b40042d90a3da" + }, + "name": "cas.cyclonedx.json" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782293352471920", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "972ca204670aee23ed070619333fb04410ed996bf3c063ff88d35de0702fd478" + }, + "name": "chainloop-cli-0.93.7-darwin-amd64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782295934163620", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "27e4efa094adef0dc5375da7bce70437dde9d35d1e20598240debfc318f374da" + }, + "name": "chainloop-cli-0.93.7-darwin-amd64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782297645680131", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "389ea065be2dd50d07b27619b8594d4738b2c86481db969f62dd549e579af1e2" + }, + "name": "chainloop-cli-0.93.7-darwin-arm64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782300158976415", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "47d5c22ee0f56bf3e7eed5c283fe66e5f61a7a9e913b9af1550dd07e71ac09e1" + }, + "name": "chainloop-cli-0.93.7-darwin-arm64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782301800977382", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "a57b0b11a51b8ebbc9d421bd68e6e82fd021f4e87742780ef30f0aaca0bdd1c2" + }, + "name": "chainloop-cli-0.93.7-linux-amd64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782304541799505", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "754dea96fc2addc0fdb70f725686fd4b5e01a1aa69a1ed0726e4d08866400d42" + }, + "name": "chainloop-cli-0.93.7-linux-amd64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782306140039811", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "c63ee103397001d2e9727d30d02a4ce4e55b7e32da55f042a414c7424b42b21d" + }, + "name": "chainloop-cli-0.93.7-linux-arm64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782308650938558", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "b5c7c73c9d4cd325b8da64135c28685715e8e19f6b48357eaf1a02e693734f37" + }, + "name": "chainloop-cli-0.93.7-linux-arm64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782309843066922", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "897f1dfc64736dd66ea8881ab07689d59e1bc147c45da0baa1de416834a46a3d" + }, + "name": "checksums.txt" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782311062937592", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "2f804aa3b95a81802c24e384e5e87e86f02ec23d043c9c4d3aa9243ee866b60b" + }, + "name": "checksums.txt.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782311526704542", + "chainloop.material.type": "SBOM_CYCLONEDX_JSON" + }, + "digest": { + "sha256": "8b53305ead21a9ede6e0e3aee2fcc04f04796716e1a2b566ce03f3f8cbc2b130" + }, + "name": "controlplane.cyclonedx.json" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782313410977824", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "91c0b92358109bfc31ea4c58902d9b7f4f582ff9c4782fb276a685e914d3cc82" + }, + "name": "cosign.pub" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782315689903312", + "chainloop.material.type": "HELM_CHART" + }, + "digest": { + "sha256": "7cbbda1e5ab71fef561c0f123f5f584c8e0de523d4da80379599ce7a05c04c1f" + }, + "name": "chainloop-0.93.7.tar.gz" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782317669410353", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "4a8eb6f9ae76460b682e7e9eb5504df9f7f2b2250d9c5cb63204442e265e2c5a" + }, + "name": "ghcr.io/chainloop-dev/chainloop/control-plane" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782318334142313", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "4d329b2aee79b35ec5e6c462be5d8000565d5ccd13602427cd889fc91c187fc8" + }, + "name": "ghcr.io/chainloop-dev/chainloop/artifact-cas" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782319034635257", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "571a5543151d651cbc62679c3f50c2e6cadfd2ff20279374c6d6106b3f70560f" + }, + "name": "ghcr.io/chainloop-dev/chainloop/cli" + } + ], + "metadata": { + "finishedAt": "2024-07-12T11:05:19.808858785Z", + "initializedAt": "2024-07-12T11:04:48.604833219Z", + "name": "chainloop-vault-release", + "organization": "read-only-demo", + "project": "chainloop", + "team": "", + "workflowID": "2acc7ee5-21d1-4500-9ca4-2d25748a1ce0", + "workflowRunID": "37dd3d94-06e3-483f-83c2-18b1137e73ee" + }, + "runnerType": "GITLAB", + "runnerURL": "https://github.com/chainloop-dev/chainloop/actions/runs/9906853011" + } +} \ No newline at end of file diff --git a/pkg/policies/testdata/statement_missing_runner.json b/pkg/policies/testdata/statement_missing_runner.json new file mode 100644 index 000000000..99dec26c4 --- /dev/null +++ b/pkg/policies/testdata/statement_missing_runner.json @@ -0,0 +1,245 @@ +{ + "_type": "https://in-toto.io/Statement/v1", + "subject": [ + { + "name": "chainloop.workflow.chainloop-vault-release", + "digest": { + "sha256": "9ae495a85891eb1130fefc17bc89940c9aa96acb8355c26a3e0d73a5097d41d4" + } + }, + { + "name": "git.head", + "digest": { + "sha1": "53f95f066b620172301e2a3879e7d593da05727e" + }, + "annotations": { + "author.email": "devel@chainloop.dev", + "author.name": "Developer", + "date": "2024-07-12T10:16:04Z", + "message": "chore(vulns): fix CVEs in base image (#1088)\n\nSigned-off-by: Jose I. Paris ", + "remotes": [ + { + "name": "origin", + "url": "https://github.com/chainloop-dev/chainloop" + } + ] + } + } + ], + "predicateType": "chainloop.dev/attestation/v0.2", + "predicate": { + "buildType": "chainloop.dev/workflowrun/v0.1", + "builder": { + "id": "chainloop.dev/cli/0.90.1@sha256:431a0765636854095f0c78d01b61eb5558abe7c8de1608aa93eef1530deee0b6" + }, + "env": { + "GITHUB_ACTOR": "jiparis", + "GITHUB_REF": "refs/tags/v0.93.7", + "GITHUB_REPOSITORY": "chainloop-dev/chainloop", + "GITHUB_REPOSITORY_OWNER": "chainloop-dev", + "GITHUB_RUN_ID": "9906853011", + "GITHUB_SHA": "53f95f066b620172301e2a3879e7d593da05727e", + "RUNNER_NAME": "GitHub Actions 193", + "RUNNER_OS": "Linux" + }, + "materials": [ + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782291120414953", + "chainloop.material.type": "SBOM_CYCLONEDX_JSON" + }, + "digest": { + "sha256": "bc449b71c4a47f2f69b514f27e1d61250ff0af0cc554a68d331b40042d90a3da" + }, + "name": "cas.cyclonedx.json" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782293352471920", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "972ca204670aee23ed070619333fb04410ed996bf3c063ff88d35de0702fd478" + }, + "name": "chainloop-cli-0.93.7-darwin-amd64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782295934163620", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "27e4efa094adef0dc5375da7bce70437dde9d35d1e20598240debfc318f374da" + }, + "name": "chainloop-cli-0.93.7-darwin-amd64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782297645680131", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "389ea065be2dd50d07b27619b8594d4738b2c86481db969f62dd549e579af1e2" + }, + "name": "chainloop-cli-0.93.7-darwin-arm64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782300158976415", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "47d5c22ee0f56bf3e7eed5c283fe66e5f61a7a9e913b9af1550dd07e71ac09e1" + }, + "name": "chainloop-cli-0.93.7-darwin-arm64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782301800977382", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "a57b0b11a51b8ebbc9d421bd68e6e82fd021f4e87742780ef30f0aaca0bdd1c2" + }, + "name": "chainloop-cli-0.93.7-linux-amd64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782304541799505", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "754dea96fc2addc0fdb70f725686fd4b5e01a1aa69a1ed0726e4d08866400d42" + }, + "name": "chainloop-cli-0.93.7-linux-amd64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782306140039811", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "c63ee103397001d2e9727d30d02a4ce4e55b7e32da55f042a414c7424b42b21d" + }, + "name": "chainloop-cli-0.93.7-linux-arm64.tar.gz" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782308650938558", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "b5c7c73c9d4cd325b8da64135c28685715e8e19f6b48357eaf1a02e693734f37" + }, + "name": "chainloop-cli-0.93.7-linux-arm64.tar.gz.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782309843066922", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "897f1dfc64736dd66ea8881ab07689d59e1bc147c45da0baa1de416834a46a3d" + }, + "name": "checksums.txt" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782311062937592", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "2f804aa3b95a81802c24e384e5e87e86f02ec23d043c9c4d3aa9243ee866b60b" + }, + "name": "checksums.txt.sig" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782311526704542", + "chainloop.material.type": "SBOM_CYCLONEDX_JSON" + }, + "digest": { + "sha256": "8b53305ead21a9ede6e0e3aee2fcc04f04796716e1a2b566ce03f3f8cbc2b130" + }, + "name": "controlplane.cyclonedx.json" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782313410977824", + "chainloop.material.type": "ARTIFACT" + }, + "digest": { + "sha256": "91c0b92358109bfc31ea4c58902d9b7f4f582ff9c4782fb276a685e914d3cc82" + }, + "name": "cosign.pub" + }, + { + "annotations": { + "chainloop.material.cas": true, + "chainloop.material.name": "material-1720782315689903312", + "chainloop.material.type": "HELM_CHART" + }, + "digest": { + "sha256": "7cbbda1e5ab71fef561c0f123f5f584c8e0de523d4da80379599ce7a05c04c1f" + }, + "name": "chainloop-0.93.7.tar.gz" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782317669410353", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "4a8eb6f9ae76460b682e7e9eb5504df9f7f2b2250d9c5cb63204442e265e2c5a" + }, + "name": "ghcr.io/chainloop-dev/chainloop/control-plane" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782318334142313", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "4d329b2aee79b35ec5e6c462be5d8000565d5ccd13602427cd889fc91c187fc8" + }, + "name": "ghcr.io/chainloop-dev/chainloop/artifact-cas" + }, + { + "annotations": { + "chainloop.material.image.tag": "v0.93.7", + "chainloop.material.name": "material-1720782319034635257", + "chainloop.material.type": "CONTAINER_IMAGE" + }, + "digest": { + "sha256": "571a5543151d651cbc62679c3f50c2e6cadfd2ff20279374c6d6106b3f70560f" + }, + "name": "ghcr.io/chainloop-dev/chainloop/cli" + } + ], + "metadata": { + "finishedAt": "2024-07-12T11:05:19.808858785Z", + "initializedAt": "2024-07-12T11:04:48.604833219Z", + "name": "chainloop-vault-release", + "organization": "read-only-demo", + "project": "chainloop", + "team": "", + "workflowID": "2acc7ee5-21d1-4500-9ca4-2d25748a1ce0", + "workflowRunID": "37dd3d94-06e3-483f-83c2-18b1137e73ee" + } + } +} \ No newline at end of file diff --git a/pkg/policies/testdata/workflow.rego b/pkg/policies/testdata/workflow.rego index 403fa3c4d..74eac1353 100644 --- a/pkg/policies/testdata/workflow.rego +++ b/pkg/policies/testdata/workflow.rego @@ -14,9 +14,10 @@ deny[msg] { is_workflow { - input.workflow.name == "policytest" + input.predicate.metadata.name == "chainloop-vault-release" } is_github { - input.runnerType == "GITHUB_ACTION" + input.predicate.runnerType == "GITHUB_ACTION" + input.predicate.env.GITHUB_SHA } \ No newline at end of file diff --git a/pkg/policies/testdata/workflow.yaml b/pkg/policies/testdata/workflow.yaml index 60aa90267..c4f6c0179 100644 --- a/pkg/policies/testdata/workflow.yaml +++ b/pkg/policies/testdata/workflow.yaml @@ -3,4 +3,5 @@ kind: Policy metadata: name: workflow spec: + type: ATTESTATION path: testdata/workflow.rego diff --git a/pkg/policies/testdata/workflow_embedded.yaml b/pkg/policies/testdata/workflow_embedded.yaml index 6e02a4062..ceb1585e4 100644 --- a/pkg/policies/testdata/workflow_embedded.yaml +++ b/pkg/policies/testdata/workflow_embedded.yaml @@ -3,6 +3,7 @@ kind: Policy metadata: name: workflow spec: + type: ATTESTATION embedded: | package main deny[msg] { @@ -10,6 +11,17 @@ spec: msg := "incorrect workflow" } + deny[msg] { + not is_github + msg := "incorrect runner" + } + is_workflow { - input.workflow.name == "policytest" + input.predicate.metadata.name == "chainloop-vault-release" + } + + is_github { + input.predicate.runnerType == "GITHUB_ACTION" + input.predicate.env.GITHUB_SHA } + From 5d25595bb2bc068308e6f08896a45cb5ac8a0133 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Mon, 15 Jul 2024 20:07:19 +0200 Subject: [PATCH 38/73] fix tests Signed-off-by: Jose I. Paris --- app/controlplane/api/workflowcontract/v1/policy_test.go | 5 +++-- internal/attestation/crafter/crafter_test.go | 2 +- .../attestation/crafter/testdata/contracts/with_rego.yaml | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controlplane/api/workflowcontract/v1/policy_test.go b/app/controlplane/api/workflowcontract/v1/policy_test.go index 537f00897..8fcd5ea0e 100644 --- a/app/controlplane/api/workflowcontract/v1/policy_test.go +++ b/app/controlplane/api/workflowcontract/v1/policy_test.go @@ -21,9 +21,10 @@ import ( "testing" "github.com/bufbuild/protovalidate-go" - v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" ) func TestValidatePolicy(t *testing.T) { @@ -85,7 +86,7 @@ func TestValidatePolicy(t *testing.T) { { desc: "filter material type", policy: &v1.Policy{ApiVersion: "workflowcontract.chainloop.dev/v1", Kind: "Policy", - Metadata: &v1.Metadata{Name: "my-policy"}, Spec: &v1.PolicySpec{Source: &v1.PolicySpec_Path{Path: "policy.rego"}, Kind: v1.CraftingSchema_Material_ATTESTATION}}, + Metadata: &v1.Metadata{Name: "my-policy"}, Spec: &v1.PolicySpec{Source: &v1.PolicySpec_Path{Path: "policy.rego"}, Type: v1.CraftingSchema_Material_ATTESTATION}}, wantErr: false, }, } diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 4e887453b..6ebf0642f 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -261,7 +261,7 @@ func (s *crafterSuite) TestLoadSchema() { func (s *crafterSuite) TestPolicyCompilation() { schema, err := crafter.LoadSchema("testdata/contracts/with_rego.yaml") s.NoError(err) - s.Contains(schema.Policies[0].GetEmbedded().GetSpec().GetEmbedded(), "package main") + s.Contains(schema.Policies.GetAttestation()[0].GetEmbedded().GetSpec().GetEmbedded(), "package main") } func (s *crafterSuite) TestResolveEnvVars() { diff --git a/internal/attestation/crafter/testdata/contracts/with_rego.yaml b/internal/attestation/crafter/testdata/contracts/with_rego.yaml index ed68d31ad..edea0403d 100644 --- a/internal/attestation/crafter/testdata/contracts/with_rego.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_rego.yaml @@ -1,3 +1,4 @@ schemaVersion: "v1" policies: - - ref: testdata/contracts/policy_rego.yaml + attestation: + - ref: testdata/contracts/policy_rego.yaml From 792d357ab09d91e73efcf899b7468da5a25956d7 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Mon, 15 Jul 2024 20:08:25 +0200 Subject: [PATCH 39/73] fix test data Signed-off-by: Jose I. Paris --- .../crafter/testdata/contracts/with_missing_policy.yaml | 3 ++- .../crafter/testdata/contracts/with_policy_embedded.yaml | 3 ++- .../crafter/testdata/contracts/with_policy_missing_rego.yaml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml b/internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml index 9a1450fa1..febaded54 100644 --- a/internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_missing_policy.yaml @@ -1,3 +1,4 @@ schemaVersion: "v1" policies: - - ref: idontexist.yaml + attestation: + - ref: idontexist.yaml diff --git a/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml b/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml index a20b3f6f4..74fdb60c1 100644 --- a/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml @@ -1,3 +1,4 @@ schemaVersion: "v1" policies: - - ref: testdata/contracts/policy_embedded.yaml + attestation: + - ref: testdata/contracts/policy_embedded.yaml diff --git a/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml b/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml index 4bef873de..a4a5479d9 100644 --- a/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml @@ -1,3 +1,4 @@ schemaVersion: "v1" policies: - - ref: testdata/contracts/policy_missing_rego.yaml + attestation: + - ref: testdata/contracts/policy_missing_rego.yaml From d7e1c3b9a06cff4de29a2e3459f147a031c6c987 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Mon, 15 Jul 2024 23:19:24 +0200 Subject: [PATCH 40/73] fix linter Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 84edbd327..d255076c4 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -84,7 +84,7 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte Name: spec.GetMetadata().GetName(), MaterialName: material.GetArtifact().GetId(), Body: string(script.Source), - Violations: engineViolationsToApiViolations(res), + Violations: engineViolationsToAPIViolations(res), }) } @@ -138,7 +138,7 @@ func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto return result, nil } -func engineViolationsToApiViolations(input []*engine.PolicyViolation) []*v12.Policy_Violation { +func engineViolationsToAPIViolations(input []*engine.PolicyViolation) []*v12.Policy_Violation { res := make([]*v12.Policy_Violation, 0) for _, v := range input { res = append(res, &v12.Policy_Violation{ From a2d660adf70f7d1ddaa5baf174727e521a1ebe0e Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 00:26:26 +0200 Subject: [PATCH 41/73] store attestation Signed-off-by: Jose I. Paris --- .../api/attestation/v1/crafting_state.proto | 2 +- .../attestation/renderer/chainloop/v02.go | 21 ++++++--- internal/attestation/renderer/renderer.go | 47 ++++++++++++++++--- pkg/policies/policies.go | 4 +- 4 files changed, 59 insertions(+), 15 deletions(-) diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto index e1daab4c4..8dd7536fa 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto @@ -89,7 +89,7 @@ message Attestation { // Head Commit of the environment where the attestation was executed (optional) Commit head = 9; - // Policies that this attestation was validated against + // Policies that materials in this attestation were validated against repeated Policy policies = 10; } diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index 9cd67b8d5..bc50bc873 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -40,12 +40,8 @@ const PredicateTypeV02 = "chainloop.dev/attestation/v0.2" type ProvenancePredicateV02 struct { *ProvenancePredicateCommon Materials []*intoto.ResourceDescriptor `json:"materials,omitempty"` - Policies map[string]*PolicyEvaluation `json:"policies,omitempty"` -} - -type PolicyEvaluation struct { - Material string `json:"material,omitempty"` - Violations map[string]string `json:"violations,omitempty"` + // Map materials and policies + Policies map[string][]*v1.Policy `json:"policies,omitempty"` } type RendererV02 struct { @@ -155,9 +151,12 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { return nil, fmt.Errorf("error normalizing materials: %w", err) } + policies := policiesFromMaterials(r.att) + p := ProvenancePredicateV02{ ProvenancePredicateCommon: predicateCommon(r.builder, r.att), Materials: normalizedMaterials, + Policies: policies, } // transform to structpb.Struct in a two steps process @@ -176,6 +175,16 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { return predicate, nil } +// collect all policies grouped by material +func policiesFromMaterials(att *v1.Attestation) map[string][]*v1.Policy { + result := map[string][]*v1.Policy{} + for _, p := range att.GetPolicies() { + result[p.MaterialName] = append(result[p.MaterialName], p) + } + + return result +} + func outputMaterials(att *v1.Attestation, onlyOutput bool) ([]*intoto.ResourceDescriptor, error) { // Sort material keys to stabilize output keys := make([]string, 0, len(att.GetMaterials())) diff --git a/internal/attestation/renderer/renderer.go b/internal/attestation/renderer/renderer.go index ac7d6ce8f..577df3c7d 100644 --- a/internal/attestation/renderer/renderer.go +++ b/internal/attestation/renderer/renderer.go @@ -34,11 +34,13 @@ import ( sigstoresigner "github.com/sigstore/sigstore/pkg/signature" sigdsee "github.com/sigstore/sigstore/pkg/signature/dsse" "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/structpb" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop" chainloopsigner "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" + "github.com/chainloop-dev/chainloop/pkg/policies" ) type AttestationRenderer struct { @@ -105,12 +107,16 @@ func (ab *AttestationRenderer) Render(ctx context.Context) (*dsse.Envelope, erro } // validate attestation-level policies - //pv := policies.NewPolicyVerifier(ab.schema, &ab.logger) - //polcyResult, err := pv.VerifyStatement(ctx, statement) - //if err != nil { - // return nil, fmt.Errorf("applying policies to statement: %w", err) - //} - // insert policy results into statement + pv := policies.NewPolicyVerifier(ab.schema, &ab.logger) + policyResults, err := pv.VerifyStatement(ctx, statement) + if err != nil { + return nil, fmt.Errorf("applying policies to statement: %w", err) + } + + // insert attestation level policy results into statement + if err = addPolicyResults(statement, policyResults); err != nil { + return nil, fmt.Errorf("adding policy results to statement: %w", err) + } rawStatement, err := protojson.Marshal(statement) if err != nil { @@ -147,6 +153,35 @@ func (ab *AttestationRenderer) Render(ctx context.Context) (*dsse.Envelope, erro return &dsseEnvelope, nil } +func addPolicyResults(statement *intoto.Statement, policyResults []*v1.Policy) error { + predicate := statement.Predicate + jsonPredicate, err := protojson.Marshal(predicate) + if err != nil { + return fmt.Errorf("marshalling predicate: %w", err) + } + var p chainloop.ProvenancePredicateV02 + err = json.Unmarshal(jsonPredicate, &p) + if err != nil { + return fmt.Errorf("unmarshalling predicate: %w", err) + } + p.Policies["ATTESTATION"] = policyResults + + // marshall back to structpb + jsonPredicate, err = json.Marshal(p) + if err != nil { + return fmt.Errorf("marshalling predicate: %w", err) + } + var finalPredicate structpb.Struct + err = protojson.Unmarshal(jsonPredicate, &finalPredicate) + if err != nil { + return fmt.Errorf("unmarshalling predicate: %w", err) + } + + statement.Predicate = &finalPredicate + + return nil +} + func (ab *AttestationRenderer) envelopeToBundle(dsseEnvelope dsse.Envelope) (*protobundle.Bundle, error) { // DSSE Envelope is already base64 encoded, we need to decode to prevent it from being encoded twice payload, err := base64.StdEncoding.DecodeString(dsseEnvelope.Payload) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index d255076c4..e27b91bf9 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -71,7 +71,7 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte return nil, fmt.Errorf("failed to load material content: %w", err) } - pv.logger.Debug().Msgf("evaluating policy %s", spec.Metadata.Name) + pv.logger.Info().Msgf("evaluating policy '%s' against material '%s'", spec.Metadata.Name, material.GetArtifact().GetId()) // verify the policy ng := getPolicyEngine(spec) @@ -113,7 +113,7 @@ func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto return nil, fmt.Errorf("failed to load policy content: %w", err) } - pv.logger.Debug().Msgf("evaluating policy %s", spec.Metadata.Name) + pv.logger.Info().Msgf("evaluating policy '%s' on attestation", spec.Metadata.Name) material, err := protojson.Marshal(statement) if err != nil { From 1c1d2485e0f3476c1239495a653a3c962dbfb6bf Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 09:51:18 +0200 Subject: [PATCH 42/73] fix test Signed-off-by: Jose I. Paris --- pkg/policies/policies_test.go | 157 ++++----------------------- pkg/policies/testdata/materials.yaml | 1 + 2 files changed, 20 insertions(+), 138 deletions(-) diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index b96ecd710..3fb484ad7 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -126,6 +126,20 @@ func (s *testSuite) TestVerifyAttestations() { violations: 1, statement: "testdata/statement_missing_runner.json", }, + { + name: "multiple policies", + schema: &v12.CraftingSchema{ + Policies: &v12.Policies{ + Attestation: []*v12.PolicyAttachment{ + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow_embedded.yaml"}}, + {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, + }, + }, + }, + npolicies: 2, + violations: 1, + statement: "testdata/statement.json", + }, } for _, tc := range cases { @@ -146,149 +160,16 @@ func (s *testSuite) TestVerifyAttestations() { s.Require().NoError(err) s.Len(res, tc.npolicies) if tc.npolicies > 0 { - s.Len(res[0].Violations, tc.violations) + violations := 0 + for _, pol := range res { + violations = violations + len(pol.Violations) + } + s.Equal(tc.violations, violations) } }) } } -// -//func (s *testSuite) TestAttestationResult() { -// s.Run("successful attestation", func() { -// schema := &v12.CraftingSchema{ -// Policies: []*v12.PolicyAttachment{ -// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, -// }, -// } -// statement := &v1.Attestation{ -// Workflow: &v1.WorkflowMetadata{ -// Name: "policytest", -// }, -// RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, -// } -// -// verifier := NewPolicyVerifier(schema, &s.logger) -// -// res, err := verifier.VerifyStatement(context.TODO(), nil) -// s.Require().NoError(err) -// s.Len(res, 0) -// -// att := state.GetAttestation() -// s.Len(att.Policies, 1) -// -// p := att.Policies[0] -// s.Len(p.Violations, 0) -// s.Equal("testdata/workflow.yaml", p.Attachment.GetRef()) -// s.Equal("workflow", p.Name) -// }) -// -// s.Run("failed attestation", func() { -// state := &v1.CraftingState{ -// InputSchema: &v12.CraftingSchema{ -// Policies: []*v12.PolicyAttachment{ -// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, -// }, -// }, -// Attestation: &v1.Attestation{ -// Workflow: &v1.WorkflowMetadata{ -// Name: "policytest", -// }, -// RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, -// }, -// } -// -// verifier := NewPolicyVerifier(state, &s.logger) -// -// res, err := verifier.VerifyStatement(context.TODO()) -// s.Require().NoError(err) -// s.Len(res, 1) -// -// att := state.GetAttestation() -// s.Len(att.Policies, 1) -// -// p := att.Policies[0] -// s.Len(p.Violations, 1) -// v := p.Violations[0] -// s.Equal(p.Name, v.Subject) -// s.Equal("incorrect runner", v.Message) -// }) -// -// s.Run("multiple successful policies", func() { -// state := &v1.CraftingState{ -// InputSchema: &v12.CraftingSchema{ -// Policies: []*v12.PolicyAttachment{ -// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, -// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, -// }, -// }, -// Attestation: &v1.Attestation{ -// Workflow: &v1.WorkflowMetadata{ -// Name: "policytest", -// }, -// RunnerType: v12.CraftingSchema_Runner_GITHUB_ACTION, -// Materials: map[string]*v1.Attestation_Material{ -// "vex": { -// MaterialType: v12.CraftingSchema_Material_OPENVEX, -// }, -// }, -// }, -// } -// -// verifier := NewPolicyVerifier(state, &s.logger) -// -// res, err := verifier.VerifyStatement(context.TODO()) -// s.Require().NoError(err) -// s.Len(res, 0) -// att := state.GetAttestation() -// s.Len(att.Policies, 2) -// s.Len(att.Policies[0].Violations, 0) -// s.Len(att.Policies[1].Violations, 0) -// }) -// -// s.Run("partial success", func() { -// state := &v1.CraftingState{ -// InputSchema: &v12.CraftingSchema{ -// Policies: []*v12.PolicyAttachment{ -// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/workflow.yaml"}}, -// {Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/materials.yaml"}}, -// }, -// }, -// Attestation: &v1.Attestation{ -// Workflow: &v1.WorkflowMetadata{ -// Name: "policytest", -// }, -// RunnerType: v12.CraftingSchema_Runner_DAGGER_PIPELINE, -// Materials: map[string]*v1.Attestation_Material{ -// "vex": { -// MaterialType: v12.CraftingSchema_Material_OPENVEX, -// }, -// }, -// }, -// } -// -// verifier := NewPolicyVerifier(state, &s.logger) -// -// res, err := verifier.VerifyStatement(context.TODO()) -// s.Require().NoError(err) -// s.Greater(len(res), 0) -// att := state.GetAttestation() -// s.Len(att.Policies, 2) -// -// // Check that only 1 policy failed -// index := slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { -// return p.Name == "workflow" -// }) -// p := att.Policies[index] -// s.Len(p.Violations, 1) -// -// index = slices.IndexFunc(att.Policies, func(p *v1.Policy) bool { -// return p.Name == "materials" -// }) -// p = att.Policies[index] -// s.Len(p.Violations, 0) -// }) -//} - func (s *testSuite) TestMaterialSelectionCriteria() { attNoFilterPolicyTyped := &v12.PolicyAttachment{ Policy: &v12.PolicyAttachment_Ref{Ref: "testdata/sbom_syft.yaml"}, diff --git a/pkg/policies/testdata/materials.yaml b/pkg/policies/testdata/materials.yaml index 15a851a8d..c7cbba94b 100644 --- a/pkg/policies/testdata/materials.yaml +++ b/pkg/policies/testdata/materials.yaml @@ -3,4 +3,5 @@ kind: Policy metadata: name: materials spec: + type: ATTESTATION path: testdata/materials.rego From 69b5715806fac37642aab05282ae109f43b90a93 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 09:53:43 +0200 Subject: [PATCH 43/73] fix rego Signed-off-by: Jose I. Paris --- pkg/policies/testdata/materials.rego | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/policies/testdata/materials.rego b/pkg/policies/testdata/materials.rego index a31b6d1c3..63bd77ba9 100644 --- a/pkg/policies/testdata/materials.rego +++ b/pkg/policies/testdata/materials.rego @@ -13,8 +13,8 @@ deny[msg] { # Collect all material types kinds contains kind { - some material in input.materials - kind := material.materialType + some material in input.predicate.materials + kind := material.annotations["chainloop.material.type"] } has_vex { From bcf6a94c013db3ea0d375313d803951850204902 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 09:57:42 +0200 Subject: [PATCH 44/73] add err to closures Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index 7f2ab600d..03ce6e37b 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -176,20 +176,20 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { } // Proto validations - if err = validator.Validate(schema); err != nil { + if err := validator.Validate(schema); err != nil { return nil, err } // Custom Validations - if err = schema.ValidateUniqueMaterialName(); err != nil { + if err := schema.ValidateUniqueMaterialName(); err != nil { return nil, err } // Load, validate policies, and embed them in the schema - if err = validateAndPreloadPolicies(schema.GetPolicies().GetMaterials()); err != nil { + if err := validateAndPreloadPolicies(schema.GetPolicies().GetMaterials()); err != nil { return nil, fmt.Errorf("validating policies: %w", err) } - if err = validateAndPreloadPolicies(schema.GetPolicies().GetAttestation()); err != nil { + if err := validateAndPreloadPolicies(schema.GetPolicies().GetAttestation()); err != nil { return nil, fmt.Errorf("validating policies: %w", err) } From 72b275fda5295712c6ade6a33571df65fa342e3f Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 10:14:46 +0200 Subject: [PATCH 45/73] lint Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter_test.go | 2 ++ pkg/policies/policies_test.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 6ebf0642f..3522eb3d7 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -223,6 +223,7 @@ func (s *crafterSuite) TestLoadSchema() { { name: "policies", contractPath: "testdata/contracts/with_policy_embedded.yaml", + want: want, }, { name: "missing policy", @@ -237,6 +238,7 @@ func (s *crafterSuite) TestLoadSchema() { { name: "rego policy", contractPath: "testdata/contracts/with_rego.yaml", + want: want, }, } diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 3fb484ad7..419e4b3fd 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -162,7 +162,7 @@ func (s *testSuite) TestVerifyAttestations() { if tc.npolicies > 0 { violations := 0 for _, pol := range res { - violations = violations + len(pol.Violations) + violations += len(pol.Violations) } s.Equal(tc.violations, violations) } From a5b4cad03f7860e782b38a66e7c2b641c3057958 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 10:21:25 +0200 Subject: [PATCH 46/73] update generated code after comment change Signed-off-by: Jose I. Paris --- .../api/gen/frontend/attestation/v1/crafting_state.ts | 2 +- .../attestation/crafter/api/attestation/v1/crafting_state.pb.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts index 91ad3ab44..32afc5d31 100644 --- a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts +++ b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts @@ -26,7 +26,7 @@ export interface Attestation { runnerType: CraftingSchema_Runner_RunnerType; /** Head Commit of the environment where the attestation was executed (optional) */ head?: Commit; - /** Policies that this attestation was validated against */ + /** Policies that materials in this attestation were validated against */ policies: Policy[]; } diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go index 28b2abe73..8809f1586 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go @@ -55,7 +55,7 @@ type Attestation struct { RunnerType v1.CraftingSchema_Runner_RunnerType `protobuf:"varint,8,opt,name=runner_type,json=runnerType,proto3,enum=workflowcontract.v1.CraftingSchema_Runner_RunnerType" json:"runner_type,omitempty"` // Head Commit of the environment where the attestation was executed (optional) Head *Commit `protobuf:"bytes,9,opt,name=head,proto3" json:"head,omitempty"` - // Policies that this attestation was validated against + // Policies that materials in this attestation were validated against Policies []*Policy `protobuf:"bytes,10,rep,name=policies,proto3" json:"policies,omitempty"` } From 8ef5b5769571c73629729d12c53b0915e21edc4a Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 10:25:09 +0200 Subject: [PATCH 47/73] fix tests Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 3522eb3d7..6ebf0642f 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -223,7 +223,6 @@ func (s *crafterSuite) TestLoadSchema() { { name: "policies", contractPath: "testdata/contracts/with_policy_embedded.yaml", - want: want, }, { name: "missing policy", @@ -238,7 +237,6 @@ func (s *crafterSuite) TestLoadSchema() { { name: "rego policy", contractPath: "testdata/contracts/with_rego.yaml", - want: want, }, } From 151150e658eaaafedf74ae7ec6eb9f9cdab1220f Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 11:39:20 +0200 Subject: [PATCH 48/73] fix panic Signed-off-by: Jose I. Paris --- internal/attestation/renderer/renderer.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/attestation/renderer/renderer.go b/internal/attestation/renderer/renderer.go index 577df3c7d..2cefd8331 100644 --- a/internal/attestation/renderer/renderer.go +++ b/internal/attestation/renderer/renderer.go @@ -164,6 +164,9 @@ func addPolicyResults(statement *intoto.Statement, policyResults []*v1.Policy) e if err != nil { return fmt.Errorf("unmarshalling predicate: %w", err) } + if p.Policies == nil { + p.Policies = make(map[string][]*v1.Policy) + } p.Policies["ATTESTATION"] = policyResults // marshall back to structpb From 536750471b64e127a102269f76c9bbb443422bf0 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 11:56:34 +0200 Subject: [PATCH 49/73] fix tests Signed-off-by: Jose I. Paris --- .../renderer/chainloop/testdata/attestation.output-2.v0.2.json | 1 - .../renderer/chainloop/testdata/attestation.output.v0.2.json | 1 - 2 files changed, 2 deletions(-) diff --git a/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json b/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json index 3edaffd22..7d18b9a0e 100644 --- a/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json +++ b/internal/attestation/renderer/chainloop/testdata/attestation.output-2.v0.2.json @@ -110,7 +110,6 @@ "workflowRunID": "f97a0680-e64b-478a-9eea-df8864fa27f8", "organization": "my-org" }, - "policies": [], "runnerType": "RUNNER_TYPE_UNSPECIFIED" } } diff --git a/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json b/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json index 0c82f74ec..fc3cb78b6 100644 --- a/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json +++ b/internal/attestation/renderer/chainloop/testdata/attestation.output.v0.2.json @@ -73,7 +73,6 @@ "workflowID": "54ea7c5c-7592-48ac-9a9f-084b72447184", "workflowRunID": "" }, - "policies": [], "runnerType": "GITHUB_ACTION" } } From d98dbeceffe5ed0eb2e098eb21331432b69e3186 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 13:09:10 +0200 Subject: [PATCH 50/73] extract attestation material properly Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index e27b91bf9..263e89bbb 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -17,6 +17,8 @@ package policies import ( "context" + "encoding/base64" + "encoding/json" "errors" "fmt" "os" @@ -25,6 +27,7 @@ import ( "github.com/bufbuild/protovalidate-go" intoto "github.com/in-toto/attestation/go/v1" "github.com/rs/zerolog" + "github.com/secure-systems-lab/go-securesystemslib/dsse" "github.com/sigstore/cosign/v2/pkg/blob" "google.golang.org/protobuf/encoding/protojson" @@ -151,16 +154,33 @@ func engineViolationsToAPIViolations(input []*engine.PolicyViolation) []*v12.Pol } func getMaterialContent(material *v12.Attestation_Material, artifactPath string) ([]byte, error) { + var rawMaterial []byte + var err error if material.InlineCas { - return material.GetArtifact().GetContent(), nil + rawMaterial = material.GetArtifact().GetContent() + } else if artifactPath == "" { + return nil, errors.New("artifact path required") + } else { + // read content from local filesystem + rawMaterial, err = os.ReadFile(artifactPath) + if err != nil { + return nil, fmt.Errorf("failed to read material content: %w", err) + } } + // special case for ATTESTATION materials, the statement needs to be extracted from the dsse wrapper. + if material.MaterialType == v1.CraftingSchema_Material_ATTESTATION { + var envelope dsse.Envelope + if err := json.Unmarshal(rawMaterial, &envelope); err != nil { + return nil, fmt.Errorf("failed to unmarshal attestation material: %w", err) + } - if artifactPath == "" { - return nil, errors.New("artifact path required") + _, err = base64.StdEncoding.Decode(rawMaterial, []byte(envelope.Payload)) + if err != nil { + return nil, fmt.Errorf("failed to decode attestation material: %w", err) + } } - // read content from local filesystem - return os.ReadFile(artifactPath) + return rawMaterial, nil } func (pv *PolicyVerifier) requiredPoliciesForMaterial(material *v12.Attestation_Material) ([]*v1.PolicyAttachment, error) { From 23281ed4c1108c2b4f65ad07351ad4952fedf78c Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 13:22:02 +0200 Subject: [PATCH 51/73] nolint Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 263e89bbb..93e4f2a0e 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -156,6 +156,8 @@ func engineViolationsToAPIViolations(input []*engine.PolicyViolation) []*v12.Pol func getMaterialContent(material *v12.Attestation_Material, artifactPath string) ([]byte, error) { var rawMaterial []byte var err error + + // nolint: gocritic if material.InlineCas { rawMaterial = material.GetArtifact().GetContent() } else if artifactPath == "" { From 7bd729836987f0808fde7f47713665da57c7f211 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 14:32:22 +0200 Subject: [PATCH 52/73] Undo import changes Signed-off-by: Jose I. Paris --- app/cli/cmd/attestation_push.go | 3 +-- app/cli/internal/action/attestation_add.go | 3 +-- app/cli/internal/action/attestation_push.go | 7 +++---- app/controlplane/api/workflowcontract/v1/policy_test.go | 3 +-- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/app/cli/cmd/attestation_push.go b/app/cli/cmd/attestation_push.go index 39330a9e9..4c1631874 100644 --- a/app/cli/cmd/attestation_push.go +++ b/app/cli/cmd/attestation_push.go @@ -19,11 +19,10 @@ import ( "errors" "fmt" + "github.com/chainloop-dev/chainloop/app/cli/internal/action" "github.com/spf13/cobra" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" - - "github.com/chainloop-dev/chainloop/app/cli/internal/action" ) func newAttestationPushCmd() *cobra.Command { diff --git a/app/cli/internal/action/attestation_add.go b/app/cli/internal/action/attestation_add.go index 452dcc4de..1894f1679 100644 --- a/app/cli/internal/action/attestation_add.go +++ b/app/cli/internal/action/attestation_add.go @@ -20,13 +20,12 @@ import ( "errors" "fmt" - "google.golang.org/grpc" - pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/chainloop-dev/chainloop/internal/grpcconn" + "google.golang.org/grpc" ) type AttestationAddOpts struct { diff --git a/app/cli/internal/action/attestation_push.go b/app/cli/internal/action/attestation_push.go index 1148c3702..15956f77a 100644 --- a/app/cli/internal/action/attestation_push.go +++ b/app/cli/internal/action/attestation_push.go @@ -21,14 +21,13 @@ import ( "fmt" "time" - "github.com/secure-systems-lab/go-securesystemslib/dsse" - "google.golang.org/grpc" - "google.golang.org/protobuf/types/known/timestamppb" - pb "github.com/chainloop-dev/chainloop/app/controlplane/api/controlplane/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter" "github.com/chainloop-dev/chainloop/internal/attestation/renderer" "github.com/chainloop-dev/chainloop/internal/attestation/signer" + "github.com/secure-systems-lab/go-securesystemslib/dsse" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/timestamppb" ) type AttestationPushOpts struct { diff --git a/app/controlplane/api/workflowcontract/v1/policy_test.go b/app/controlplane/api/workflowcontract/v1/policy_test.go index 8fcd5ea0e..7d7b0cbfc 100644 --- a/app/controlplane/api/workflowcontract/v1/policy_test.go +++ b/app/controlplane/api/workflowcontract/v1/policy_test.go @@ -21,10 +21,9 @@ import ( "testing" "github.com/bufbuild/protovalidate-go" + v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - v1 "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" ) func TestValidatePolicy(t *testing.T) { From efe4c5d85a77120ea8d24efb6915dc33bdc62681 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 14:34:19 +0200 Subject: [PATCH 53/73] undo imports Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index 03ce6e37b..74902c9fc 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -28,19 +28,18 @@ import ( "time" "github.com/bufbuild/protovalidate-go" - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/google/go-containerregistry/pkg/authn" - "github.com/rs/zerolog" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/types/known/timestamppb" - schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/chainloop-dev/chainloop/internal/attestation/crafter/materials" "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/chainloop-dev/chainloop/internal/ociauth" "github.com/chainloop-dev/chainloop/pkg/policies" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/google/go-containerregistry/pkg/authn" + "github.com/rs/zerolog" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/types/known/timestamppb" ) // StateManager is an interface for managing the state of the crafting process From b90a6875a1db24d78a3930e827833a75213b361d Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 14:39:04 +0200 Subject: [PATCH 54/73] move imports Signed-off-by: Jose I. Paris --- internal/attestation/crafter/materials/materials.go | 7 +++---- internal/attestation/renderer/chainloop/chainloop.go | 3 +-- internal/attestation/renderer/chainloop/v02.go | 9 +++------ internal/attestation/renderer/renderer.go | 11 +++++------ internal/attestation/renderer/renderer_test.go | 7 +++---- 5 files changed, 15 insertions(+), 22 deletions(-) diff --git a/internal/attestation/crafter/materials/materials.go b/internal/attestation/crafter/materials/materials.go index 45793effe..d6743e218 100644 --- a/internal/attestation/crafter/materials/materials.go +++ b/internal/attestation/crafter/materials/materials.go @@ -26,15 +26,14 @@ import ( "code.cloudfoundry.org/bytefmt" "cuelang.org/go/cue/cuecontext" "github.com/bufbuild/protovalidate-go" + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/casclient" "github.com/google/go-containerregistry/pkg/authn" cr_v1 "github.com/google/go-containerregistry/pkg/v1" "github.com/rs/zerolog" "google.golang.org/protobuf/types/known/timestamppb" "sigs.k8s.io/yaml" - - schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - api "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/casclient" ) var ( diff --git a/internal/attestation/renderer/chainloop/chainloop.go b/internal/attestation/renderer/chainloop/chainloop.go index 23ddcf2ff..4688fb90e 100644 --- a/internal/attestation/renderer/chainloop/chainloop.go +++ b/internal/attestation/renderer/chainloop/chainloop.go @@ -20,11 +20,10 @@ import ( "fmt" "time" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" "github.com/secure-systems-lab/go-securesystemslib/dsse" "google.golang.org/protobuf/encoding/protojson" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - crv1 "github.com/google/go-containerregistry/pkg/v1" intoto "github.com/in-toto/attestation/go/v1" ) diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index bc50bc873..1366b250d 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -23,15 +23,12 @@ import ( "strings" "time" + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" crv1 "github.com/google/go-containerregistry/pkg/v1" + intoto "github.com/in-toto/attestation/go/v1" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" - - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - - intoto "github.com/in-toto/attestation/go/v1" - - schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" ) // Replace custom material type with https://github.com/in-toto/attestation/blob/main/spec/v1.0/resource_descriptor.md diff --git a/internal/attestation/renderer/renderer.go b/internal/attestation/renderer/renderer.go index 2cefd8331..67f46bcd8 100644 --- a/internal/attestation/renderer/renderer.go +++ b/internal/attestation/renderer/renderer.go @@ -25,6 +25,11 @@ import ( "fmt" "os" + schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop" + chainloopsigner "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" + "github.com/chainloop-dev/chainloop/pkg/policies" intoto "github.com/in-toto/attestation/go/v1" "github.com/rs/zerolog" "github.com/secure-systems-lab/go-securesystemslib/dsse" @@ -35,12 +40,6 @@ import ( sigdsee "github.com/sigstore/sigstore/pkg/signature/dsse" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/types/known/structpb" - - schemaapi "github.com/chainloop-dev/chainloop/app/controlplane/api/workflowcontract/v1" - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/attestation/renderer/chainloop" - chainloopsigner "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" - "github.com/chainloop-dev/chainloop/pkg/policies" ) type AttestationRenderer struct { diff --git a/internal/attestation/renderer/renderer_test.go b/internal/attestation/renderer/renderer_test.go index 41bcfc348..040da425d 100644 --- a/internal/attestation/renderer/renderer_test.go +++ b/internal/attestation/renderer/renderer_test.go @@ -25,15 +25,14 @@ import ( "os" "testing" + v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" + "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" + "github.com/chainloop-dev/chainloop/internal/attestation/signer/cosign" "github.com/rs/zerolog" "github.com/secure-systems-lab/go-securesystemslib/dsse" "github.com/sigstore/sigstore/pkg/signature" sigdsee "github.com/sigstore/sigstore/pkg/signature/dsse" "github.com/stretchr/testify/suite" - - v1 "github.com/chainloop-dev/chainloop/internal/attestation/crafter/api/attestation/v1" - "github.com/chainloop-dev/chainloop/internal/attestation/signer/chainloop" - "github.com/chainloop-dev/chainloop/internal/attestation/signer/cosign" ) type rendererSuite struct { From 3fbf828a170768d7147b785c6a5808dd03a2faee Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 14:41:08 +0200 Subject: [PATCH 55/73] do not embed on contract create Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index 74902c9fc..a5b536e7a 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -201,15 +201,10 @@ func validateAndPreloadPolicies(pols []*schemaapi.PolicyAttachment) error { if err != nil { return fmt.Errorf("validating policy: %w", err) } - script, err := policies.LoadPolicyScriptFromSpec(spec) + _, err = policies.LoadPolicyScriptFromSpec(spec) if err != nil { return fmt.Errorf("loading policy script: %w", err) } - - // embed the script in the policy (if not already) - spec.GetSpec().Source = &schemaapi.PolicySpec_Embedded{Embedded: string(script.Source)} - // Embed the policy in the schema (if not already) - p.Policy = &schemaapi.PolicyAttachment_Embedded{Embedded: spec} } return nil From 526e97f7230eb6cee79b30df38e3850b1379bdbd Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 14:49:32 +0200 Subject: [PATCH 56/73] encode body in attestation result Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 93e4f2a0e..01f2be99a 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -86,7 +86,7 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte result = append(result, &v12.Policy{ Name: spec.GetMetadata().GetName(), MaterialName: material.GetArtifact().GetId(), - Body: string(script.Source), + Body: base64.StdEncoding.EncodeToString(script.Source), Violations: engineViolationsToAPIViolations(res), }) } @@ -133,7 +133,7 @@ func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto // 5. Store result in the attestation itself (for the renderer to include them in the predicate) result = append(result, &v12.Policy{ Name: spec.Metadata.Name, - Body: string(script.Source), + Body: base64.StdEncoding.EncodeToString(script.Source), Violations: policyViolationsToAttestationViolations(res), }) } From c339fcf179e5d1df3a31e70da7ae540f5d6c038c Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 16:30:35 +0200 Subject: [PATCH 57/73] remove test Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 6ebf0642f..7268361d5 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -258,12 +258,6 @@ func (s *crafterSuite) TestLoadSchema() { } } -func (s *crafterSuite) TestPolicyCompilation() { - schema, err := crafter.LoadSchema("testdata/contracts/with_rego.yaml") - s.NoError(err) - s.Contains(schema.Policies.GetAttestation()[0].GetEmbedded().GetSpec().GetEmbedded(), "package main") -} - func (s *crafterSuite) TestResolveEnvVars() { testCases := []struct { name string From 1b8bc106e3a0add8106dd5999c501fee94c607d1 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 16:32:22 +0200 Subject: [PATCH 58/73] remove reference by name Signed-off-by: Jose I. Paris --- .../workflowcontract/v1/crafting_schema.ts | 21 +-- .../workflowcontract/v1/crafting_schema.pb.go | 164 ++++++++---------- .../workflowcontract/v1/crafting_schema.proto | 20 +-- 3 files changed, 81 insertions(+), 124 deletions(-) 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 33eb29927..713246a1b 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -252,10 +252,6 @@ export interface PolicyAttachment { ref?: | string | undefined; - /** reference to a policy already known by chainloop */ - name?: - | string - | undefined; /** meant to be used to embed the policy in the contract */ embedded?: | Policy @@ -824,7 +820,7 @@ export const Policies = { }; function createBasePolicyAttachment(): PolicyAttachment { - return { ref: undefined, name: undefined, embedded: undefined, selector: undefined, disabled: false, with: [] }; + return { ref: undefined, embedded: undefined, selector: undefined, disabled: false, with: [] }; } export const PolicyAttachment = { @@ -832,11 +828,8 @@ export const PolicyAttachment = { if (message.ref !== undefined) { writer.uint32(10).string(message.ref); } - if (message.name !== undefined) { - writer.uint32(18).string(message.name); - } if (message.embedded !== undefined) { - Policy.encode(message.embedded, writer.uint32(50).fork()).ldelim(); + Policy.encode(message.embedded, writer.uint32(18).fork()).ldelim(); } if (message.selector !== undefined) { PolicyAttachment_MaterialSelector.encode(message.selector, writer.uint32(26).fork()).ldelim(); @@ -869,13 +862,6 @@ export const PolicyAttachment = { break; } - message.name = reader.string(); - continue; - case 6: - if (tag !== 50) { - break; - } - message.embedded = Policy.decode(reader, reader.uint32()); continue; case 3: @@ -911,7 +897,6 @@ export const PolicyAttachment = { fromJSON(object: any): PolicyAttachment { return { ref: isSet(object.ref) ? String(object.ref) : undefined, - name: isSet(object.name) ? String(object.name) : undefined, embedded: isSet(object.embedded) ? Policy.fromJSON(object.embedded) : undefined, selector: isSet(object.selector) ? PolicyAttachment_MaterialSelector.fromJSON(object.selector) : undefined, disabled: isSet(object.disabled) ? Boolean(object.disabled) : false, @@ -922,7 +907,6 @@ export const PolicyAttachment = { toJSON(message: PolicyAttachment): unknown { const obj: any = {}; message.ref !== undefined && (obj.ref = message.ref); - message.name !== undefined && (obj.name = message.name); message.embedded !== undefined && (obj.embedded = message.embedded ? Policy.toJSON(message.embedded) : undefined); message.selector !== undefined && (obj.selector = message.selector ? PolicyAttachment_MaterialSelector.toJSON(message.selector) : undefined); @@ -942,7 +926,6 @@ export const PolicyAttachment = { fromPartial, I>>(object: I): PolicyAttachment { const message = createBasePolicyAttachment(); message.ref = object.ref ?? undefined; - message.name = object.name ?? undefined; message.embedded = (object.embedded !== undefined && object.embedded !== null) ? Policy.fromPartial(object.embedded) : undefined; diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index 225f9f50e..e9b176c6e 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -456,7 +456,6 @@ type PolicyAttachment struct { // Types that are assignable to Policy: // // *PolicyAttachment_Ref - // *PolicyAttachment_Name // *PolicyAttachment_Embedded Policy isPolicyAttachment_Policy `protobuf_oneof:"policy"` // rules to select a material or materials to be validated by the policy. @@ -513,13 +512,6 @@ func (x *PolicyAttachment) GetRef() string { return "" } -func (x *PolicyAttachment) GetName() string { - if x, ok := x.GetPolicy().(*PolicyAttachment_Name); ok { - return x.Name - } - return "" -} - func (x *PolicyAttachment) GetEmbedded() *Policy { if x, ok := x.GetPolicy().(*PolicyAttachment_Embedded); ok { return x.Embedded @@ -557,20 +549,13 @@ type PolicyAttachment_Ref struct { Ref string `protobuf:"bytes,1,opt,name=ref,proto3,oneof"` } -type PolicyAttachment_Name struct { - // reference to a policy already known by chainloop - Name string `protobuf:"bytes,2,opt,name=name,proto3,oneof"` -} - type PolicyAttachment_Embedded struct { // meant to be used to embed the policy in the contract - Embedded *Policy `protobuf:"bytes,6,opt,name=embedded,proto3,oneof"` + Embedded *Policy `protobuf:"bytes,2,opt,name=embedded,proto3,oneof"` } func (*PolicyAttachment_Ref) isPolicyAttachment_Policy() {} -func (*PolicyAttachment_Name) isPolicyAttachment_Policy() {} - func (*PolicyAttachment_Embedded) isPolicyAttachment_Policy() {} // Represents a policy to be applied to a material or attestation @@ -1129,11 +1114,51 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0xc5, 0x04, 0x0a, 0x10, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xa9, 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, 0x99, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x82, 0x01, 0xba, 0x48, 0x7f, 0xba, 0x01, 0x7c, + 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, 0x48, 0x0a, 0x04, 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 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, 0x41, 0x74, + 0x74, 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, + 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 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, 0x1a, 0x4a, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, + 0x72, 0x67, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 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, 0xa4, 0x01, 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, @@ -1141,81 +1166,31 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0x48, 0x00, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x08, 0x65, 0x6d, 0x62, 0x65, 0x64, 0x64, 0x65, 0x64, - 0x18, 0x06, 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, - 0x48, 0x0a, 0x04, 0x77, 0x69, 0x74, 0x68, 0x18, 0x05, 0x20, 0x03, 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, 0x41, 0x74, 0x74, 0x61, 0x63, 0x68, - 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x52, 0x04, 0x77, 0x69, 0x74, 0x68, 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, 0x1a, 0x4a, 0x0a, 0x0e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x72, 0x67, 0x75, 0x6d, - 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x1c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, - 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 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, 0xa4, 0x01, 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, 0x22, 0x9c, - 0x02, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 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, 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x2b, 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, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65, 0x52, 0x05, 0x73, - 0x74, 0x61, 0x67, 0x65, 0x12, 0x5c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 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, 0x74, 0x79, - 0x70, 0x65, 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, - 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, - 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, 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, + 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x5d, 0x29, 0x3f, 0x24, 0x27, 0x29, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x22, 0x9c, 0x02, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, + 0x63, 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, 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 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, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, + 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x5c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x04, 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, 0x74, 0x79, 0x70, 0x65, 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, + 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, } var ( @@ -1413,7 +1388,6 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { } file_workflowcontract_v1_crafting_schema_proto_msgTypes[3].OneofWrappers = []interface{}{ (*PolicyAttachment_Ref)(nil), - (*PolicyAttachment_Name)(nil), (*PolicyAttachment_Embedded)(nil), } file_workflowcontract_v1_crafting_schema_proto_msgTypes[6].OneofWrappers = []interface{}{ diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 223c7d531..3837c4fed 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -120,17 +120,17 @@ message PolicyAttachment { // policy reference, it might be in URI format. string ref = 1 [(buf.validate.field).string.min_len = 1]; - // 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", - }, - }]; - // meant to be used to embed the policy in the contract - Policy embedded = 6; + 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; } From 19434ea050f8fec586393a5501e2bd992a58658d Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 16:38:38 +0200 Subject: [PATCH 59/73] fix tests Signed-off-by: Jose I. Paris --- .../api/workflowcontract/v1/crafting_schema_test.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go b/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go index 2879d3a34..20ad1770d 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema_test.go @@ -112,15 +112,10 @@ func TestPolicyAttachment(t *testing.T) { policy: &v1.PolicyAttachment{Policy: &v1.PolicyAttachment_Ref{Ref: "reference"}}, wantErr: false, }, - { - desc: "policy name", - policy: &v1.PolicyAttachment{Policy: &v1.PolicyAttachment_Name{Name: "name"}}, - wantErr: false, - }, { desc: "incomplete arguments", policy: &v1.PolicyAttachment{ - Policy: &v1.PolicyAttachment_Name{Name: "name"}, + Policy: &v1.PolicyAttachment_Ref{Ref: "reference"}, With: []*v1.PolicyAttachment_PolicyArgument{ { Name: "name", @@ -133,7 +128,7 @@ func TestPolicyAttachment(t *testing.T) { { desc: "complete arguments", policy: &v1.PolicyAttachment{ - Policy: &v1.PolicyAttachment_Name{Name: "name"}, + Policy: &v1.PolicyAttachment_Ref{Ref: "reference"}, With: []*v1.PolicyAttachment_PolicyArgument{ { Name: "name", From fc79a4da9dd85385668ed6ee6470b2ca8ceba87d Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 16:57:43 +0200 Subject: [PATCH 60/73] improve tests Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter_test.go | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 7268361d5..4fdd12503 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -223,6 +223,18 @@ func (s *crafterSuite) TestLoadSchema() { { name: "policies", contractPath: "testdata/contracts/with_policy_embedded.yaml", + want: &schemaapi.CraftingSchema{ + SchemaVersion: "v1", + Policies: &schemaapi.Policies{ + Attestation: []*schemaapi.PolicyAttachment{ + { + Policy: &schemaapi.PolicyAttachment_Ref{ + Ref: "testdata/contracts/policy_embedded.yaml", + }, + }, + }, + }, + }, }, { name: "missing policy", @@ -237,6 +249,18 @@ func (s *crafterSuite) TestLoadSchema() { { name: "rego policy", contractPath: "testdata/contracts/with_rego.yaml", + want: &schemaapi.CraftingSchema{ + SchemaVersion: "v1", + Policies: &schemaapi.Policies{ + Attestation: []*schemaapi.PolicyAttachment{ + { + Policy: &schemaapi.PolicyAttachment_Ref{ + Ref: "testdata/contracts/policy_rego.yaml", + }, + }, + }, + }, + }, }, } @@ -250,7 +274,7 @@ func (s *crafterSuite) TestLoadSchema() { if tc.want != nil { // Check state - if ok := proto.Equal(want, got); !ok { + if ok := proto.Equal(tc.want, got); !ok { s.Fail(fmt.Sprintf("These two protobuf messages are not equal:\nexpected: %v\nactual: %v", want, got)) } } From c1a7ecab8dc4af344381f892e4ad462640ee43b3 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 17:48:55 +0200 Subject: [PATCH 61/73] change method name Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index a5b536e7a..93612266f 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -185,17 +185,17 @@ func LoadSchema(pathOrURI string) (*schemaapi.CraftingSchema, error) { } // Load, validate policies, and embed them in the schema - if err := validateAndPreloadPolicies(schema.GetPolicies().GetMaterials()); err != nil { + if err := validatePolicyAttachments(schema.GetPolicies().GetMaterials()); err != nil { return nil, fmt.Errorf("validating policies: %w", err) } - if err := validateAndPreloadPolicies(schema.GetPolicies().GetAttestation()); err != nil { + if err := validatePolicyAttachments(schema.GetPolicies().GetAttestation()); err != nil { return nil, fmt.Errorf("validating policies: %w", err) } return schema, nil } -func validateAndPreloadPolicies(pols []*schemaapi.PolicyAttachment) error { +func validatePolicyAttachments(pols []*schemaapi.PolicyAttachment) error { for _, p := range pols { spec, err := policies.LoadPolicySpec(p) if err != nil { From 8e36caf5171843dc42f68be69ddb1c4a918230be Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 17:57:23 +0200 Subject: [PATCH 62/73] apply suggestions Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index 93612266f..8c866cc0f 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -201,8 +201,7 @@ func validatePolicyAttachments(pols []*schemaapi.PolicyAttachment) error { if err != nil { return fmt.Errorf("validating policy: %w", err) } - _, err = policies.LoadPolicyScriptFromSpec(spec) - if err != nil { + if _, err := policies.LoadPolicyScriptFromSpec(spec); err != nil { return fmt.Errorf("loading policy script: %w", err) } } From 2c239e43cdcf0228d65cd5f2006e0b0cce577037 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 18:06:19 +0200 Subject: [PATCH 63/73] change naming for policy evaluations Signed-off-by: Jose I. Paris --- .../frontend/attestation/v1/crafting_state.ts | 82 ++-- app/controlplane/pkg/data/ent/runtime.go | 1 + .../api/attestation/v1/crafting_state.pb.go | 385 +++++++++--------- .../api/attestation/v1/crafting_state.proto | 4 +- internal/attestation/crafter/crafter.go | 2 +- .../attestation/renderer/chainloop/v02.go | 14 +- internal/attestation/renderer/renderer.go | 8 +- pkg/policies/policies.go | 23 +- 8 files changed, 262 insertions(+), 257 deletions(-) diff --git a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts index 32afc5d31..3856bab71 100644 --- a/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts +++ b/app/controlplane/api/gen/frontend/attestation/v1/crafting_state.ts @@ -27,7 +27,7 @@ export interface Attestation { /** Head Commit of the environment where the attestation was executed (optional) */ head?: Commit; /** Policies that materials in this attestation were validated against */ - policies: Policy[]; + policyEvaluations: PolicyEvaluation[]; } export interface Attestation_MaterialsEntry { @@ -100,17 +100,17 @@ export interface Attestation_EnvVarsEntry { } /** A policy executed against an attestation or material */ -export interface Policy { +export interface PolicyEvaluation { /** The policy name from the policy spec */ name: string; materialName: string; /** The body script of the policy */ body: string; /** The policy violations, if any */ - violations: Policy_Violation[]; + violations: PolicyEvaluation_Violation[]; } -export interface Policy_Violation { +export interface PolicyEvaluation_Violation { subject: string; message: string; } @@ -159,7 +159,7 @@ function createBaseAttestation(): Attestation { runnerUrl: "", runnerType: 0, head: undefined, - policies: [], + policyEvaluations: [], }; } @@ -192,8 +192,8 @@ export const Attestation = { if (message.head !== undefined) { Commit.encode(message.head, writer.uint32(74).fork()).ldelim(); } - for (const v of message.policies) { - Policy.encode(v!, writer.uint32(82).fork()).ldelim(); + for (const v of message.policyEvaluations) { + PolicyEvaluation.encode(v!, writer.uint32(82).fork()).ldelim(); } return writer; }, @@ -282,7 +282,7 @@ export const Attestation = { break; } - message.policies.push(Policy.decode(reader, reader.uint32())); + message.policyEvaluations.push(PolicyEvaluation.decode(reader, reader.uint32())); continue; } if ((tag & 7) === 4 || tag === 0) { @@ -319,7 +319,9 @@ export const Attestation = { runnerUrl: isSet(object.runnerUrl) ? String(object.runnerUrl) : "", runnerType: isSet(object.runnerType) ? craftingSchema_Runner_RunnerTypeFromJSON(object.runnerType) : 0, head: isSet(object.head) ? Commit.fromJSON(object.head) : undefined, - policies: Array.isArray(object?.policies) ? object.policies.map((e: any) => Policy.fromJSON(e)) : [], + policyEvaluations: Array.isArray(object?.policyEvaluations) + ? object.policyEvaluations.map((e: any) => PolicyEvaluation.fromJSON(e)) + : [], }; }, @@ -350,10 +352,10 @@ export const Attestation = { message.runnerUrl !== undefined && (obj.runnerUrl = message.runnerUrl); message.runnerType !== undefined && (obj.runnerType = craftingSchema_Runner_RunnerTypeToJSON(message.runnerType)); message.head !== undefined && (obj.head = message.head ? Commit.toJSON(message.head) : undefined); - if (message.policies) { - obj.policies = message.policies.map((e) => e ? Policy.toJSON(e) : undefined); + if (message.policyEvaluations) { + obj.policyEvaluations = message.policyEvaluations.map((e) => e ? PolicyEvaluation.toJSON(e) : undefined); } else { - obj.policies = []; + obj.policyEvaluations = []; } return obj; }, @@ -396,7 +398,7 @@ export const Attestation = { message.runnerUrl = object.runnerUrl ?? ""; message.runnerType = object.runnerType ?? 0; message.head = (object.head !== undefined && object.head !== null) ? Commit.fromPartial(object.head) : undefined; - message.policies = object.policies?.map((e) => Policy.fromPartial(e)) || []; + message.policyEvaluations = object.policyEvaluations?.map((e) => PolicyEvaluation.fromPartial(e)) || []; return message; }, }; @@ -1169,12 +1171,12 @@ export const Attestation_EnvVarsEntry = { }, }; -function createBasePolicy(): Policy { +function createBasePolicyEvaluation(): PolicyEvaluation { return { name: "", materialName: "", body: "", violations: [] }; } -export const Policy = { - encode(message: Policy, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { +export const PolicyEvaluation = { + encode(message: PolicyEvaluation, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { if (message.name !== "") { writer.uint32(10).string(message.name); } @@ -1185,15 +1187,15 @@ export const Policy = { writer.uint32(26).string(message.body); } for (const v of message.violations) { - Policy_Violation.encode(v!, writer.uint32(34).fork()).ldelim(); + PolicyEvaluation_Violation.encode(v!, writer.uint32(34).fork()).ldelim(); } return writer; }, - decode(input: _m0.Reader | Uint8Array, length?: number): Policy { + decode(input: _m0.Reader | Uint8Array, length?: number): PolicyEvaluation { const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); let end = length === undefined ? reader.len : reader.pos + length; - const message = createBasePolicy(); + const message = createBasePolicyEvaluation(); while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { @@ -1223,7 +1225,7 @@ export const Policy = { break; } - message.violations.push(Policy_Violation.decode(reader, reader.uint32())); + message.violations.push(PolicyEvaluation_Violation.decode(reader, reader.uint32())); continue; } if ((tag & 7) === 4 || tag === 0) { @@ -1234,50 +1236,50 @@ export const Policy = { return message; }, - fromJSON(object: any): Policy { + fromJSON(object: any): PolicyEvaluation { return { name: isSet(object.name) ? String(object.name) : "", materialName: isSet(object.materialName) ? String(object.materialName) : "", body: isSet(object.body) ? String(object.body) : "", violations: Array.isArray(object?.violations) - ? object.violations.map((e: any) => Policy_Violation.fromJSON(e)) + ? object.violations.map((e: any) => PolicyEvaluation_Violation.fromJSON(e)) : [], }; }, - toJSON(message: Policy): unknown { + toJSON(message: PolicyEvaluation): unknown { const obj: any = {}; message.name !== undefined && (obj.name = message.name); message.materialName !== undefined && (obj.materialName = message.materialName); message.body !== undefined && (obj.body = message.body); if (message.violations) { - obj.violations = message.violations.map((e) => e ? Policy_Violation.toJSON(e) : undefined); + obj.violations = message.violations.map((e) => e ? PolicyEvaluation_Violation.toJSON(e) : undefined); } else { obj.violations = []; } return obj; }, - create, I>>(base?: I): Policy { - return Policy.fromPartial(base ?? {}); + create, I>>(base?: I): PolicyEvaluation { + return PolicyEvaluation.fromPartial(base ?? {}); }, - fromPartial, I>>(object: I): Policy { - const message = createBasePolicy(); + fromPartial, I>>(object: I): PolicyEvaluation { + const message = createBasePolicyEvaluation(); message.name = object.name ?? ""; message.materialName = object.materialName ?? ""; message.body = object.body ?? ""; - message.violations = object.violations?.map((e) => Policy_Violation.fromPartial(e)) || []; + message.violations = object.violations?.map((e) => PolicyEvaluation_Violation.fromPartial(e)) || []; return message; }, }; -function createBasePolicy_Violation(): Policy_Violation { +function createBasePolicyEvaluation_Violation(): PolicyEvaluation_Violation { return { subject: "", message: "" }; } -export const Policy_Violation = { - encode(message: Policy_Violation, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { +export const PolicyEvaluation_Violation = { + encode(message: PolicyEvaluation_Violation, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { if (message.subject !== "") { writer.uint32(10).string(message.subject); } @@ -1287,10 +1289,10 @@ export const Policy_Violation = { return writer; }, - decode(input: _m0.Reader | Uint8Array, length?: number): Policy_Violation { + decode(input: _m0.Reader | Uint8Array, length?: number): PolicyEvaluation_Violation { const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input); let end = length === undefined ? reader.len : reader.pos + length; - const message = createBasePolicy_Violation(); + const message = createBasePolicyEvaluation_Violation(); while (reader.pos < end) { const tag = reader.uint32(); switch (tag >>> 3) { @@ -1317,26 +1319,26 @@ export const Policy_Violation = { return message; }, - fromJSON(object: any): Policy_Violation { + fromJSON(object: any): PolicyEvaluation_Violation { return { subject: isSet(object.subject) ? String(object.subject) : "", message: isSet(object.message) ? String(object.message) : "", }; }, - toJSON(message: Policy_Violation): unknown { + toJSON(message: PolicyEvaluation_Violation): unknown { const obj: any = {}; message.subject !== undefined && (obj.subject = message.subject); message.message !== undefined && (obj.message = message.message); return obj; }, - create, I>>(base?: I): Policy_Violation { - return Policy_Violation.fromPartial(base ?? {}); + create, I>>(base?: I): PolicyEvaluation_Violation { + return PolicyEvaluation_Violation.fromPartial(base ?? {}); }, - fromPartial, I>>(object: I): Policy_Violation { - const message = createBasePolicy_Violation(); + fromPartial, I>>(object: I): PolicyEvaluation_Violation { + const message = createBasePolicyEvaluation_Violation(); message.subject = object.subject ?? ""; message.message = object.message ?? ""; return message; diff --git a/app/controlplane/pkg/data/ent/runtime.go b/app/controlplane/pkg/data/ent/runtime.go index c3267eb96..cb579976d 100644 --- a/app/controlplane/pkg/data/ent/runtime.go +++ b/app/controlplane/pkg/data/ent/runtime.go @@ -1,3 +1,4 @@ +// +build tools // Code generated by ent, DO NOT EDIT. package ent diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go index 8809f1586..e9f6473d8 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.pb.go @@ -56,7 +56,7 @@ type Attestation struct { // Head Commit of the environment where the attestation was executed (optional) Head *Commit `protobuf:"bytes,9,opt,name=head,proto3" json:"head,omitempty"` // Policies that materials in this attestation were validated against - Policies []*Policy `protobuf:"bytes,10,rep,name=policies,proto3" json:"policies,omitempty"` + PolicyEvaluations []*PolicyEvaluation `protobuf:"bytes,10,rep,name=policy_evaluations,json=policyEvaluations,proto3" json:"policy_evaluations,omitempty"` } func (x *Attestation) Reset() { @@ -154,15 +154,15 @@ func (x *Attestation) GetHead() *Commit { return nil } -func (x *Attestation) GetPolicies() []*Policy { +func (x *Attestation) GetPolicyEvaluations() []*PolicyEvaluation { if x != nil { - return x.Policies + return x.PolicyEvaluations } return nil } // A policy executed against an attestation or material -type Policy struct { +type PolicyEvaluation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -173,11 +173,11 @@ type Policy struct { // The body script of the policy Body string `protobuf:"bytes,3,opt,name=body,proto3" json:"body,omitempty"` // The policy violations, if any - Violations []*Policy_Violation `protobuf:"bytes,4,rep,name=violations,proto3" json:"violations,omitempty"` + Violations []*PolicyEvaluation_Violation `protobuf:"bytes,4,rep,name=violations,proto3" json:"violations,omitempty"` } -func (x *Policy) Reset() { - *x = Policy{} +func (x *PolicyEvaluation) Reset() { + *x = PolicyEvaluation{} if protoimpl.UnsafeEnabled { mi := &file_attestation_v1_crafting_state_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -185,13 +185,13 @@ func (x *Policy) Reset() { } } -func (x *Policy) String() string { +func (x *PolicyEvaluation) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Policy) ProtoMessage() {} +func (*PolicyEvaluation) ProtoMessage() {} -func (x *Policy) ProtoReflect() protoreflect.Message { +func (x *PolicyEvaluation) ProtoReflect() protoreflect.Message { mi := &file_attestation_v1_crafting_state_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -203,33 +203,33 @@ func (x *Policy) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Policy.ProtoReflect.Descriptor instead. -func (*Policy) Descriptor() ([]byte, []int) { +// Deprecated: Use PolicyEvaluation.ProtoReflect.Descriptor instead. +func (*PolicyEvaluation) Descriptor() ([]byte, []int) { return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{1} } -func (x *Policy) GetName() string { +func (x *PolicyEvaluation) GetName() string { if x != nil { return x.Name } return "" } -func (x *Policy) GetMaterialName() string { +func (x *PolicyEvaluation) GetMaterialName() string { if x != nil { return x.MaterialName } return "" } -func (x *Policy) GetBody() string { +func (x *PolicyEvaluation) GetBody() string { if x != nil { return x.Body } return "" } -func (x *Policy) GetViolations() []*Policy_Violation { +func (x *PolicyEvaluation) GetViolations() []*PolicyEvaluation_Violation { if x != nil { return x.Violations } @@ -842,7 +842,7 @@ func (x *Attestation_Material_Artifact) GetContent() []byte { return nil } -type Policy_Violation struct { +type PolicyEvaluation_Violation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields @@ -851,8 +851,8 @@ type Policy_Violation struct { Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` } -func (x *Policy_Violation) Reset() { - *x = Policy_Violation{} +func (x *PolicyEvaluation_Violation) Reset() { + *x = PolicyEvaluation_Violation{} if protoimpl.UnsafeEnabled { mi := &file_attestation_v1_crafting_state_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -860,13 +860,13 @@ func (x *Policy_Violation) Reset() { } } -func (x *Policy_Violation) String() string { +func (x *PolicyEvaluation_Violation) String() string { return protoimpl.X.MessageStringOf(x) } -func (*Policy_Violation) ProtoMessage() {} +func (*PolicyEvaluation_Violation) ProtoMessage() {} -func (x *Policy_Violation) ProtoReflect() protoreflect.Message { +func (x *PolicyEvaluation_Violation) ProtoReflect() protoreflect.Message { mi := &file_attestation_v1_crafting_state_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) @@ -878,19 +878,19 @@ func (x *Policy_Violation) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use Policy_Violation.ProtoReflect.Descriptor instead. -func (*Policy_Violation) Descriptor() ([]byte, []int) { +// Deprecated: Use PolicyEvaluation_Violation.ProtoReflect.Descriptor instead. +func (*PolicyEvaluation_Violation) Descriptor() ([]byte, []int) { return file_attestation_v1_crafting_state_proto_rawDescGZIP(), []int{1, 0} } -func (x *Policy_Violation) GetSubject() string { +func (x *PolicyEvaluation_Violation) GetSubject() string { if x != nil { return x.Subject } return "" } -func (x *Policy_Violation) GetMessage() string { +func (x *PolicyEvaluation_Violation) GetMessage() string { if x != nil { return x.Message } @@ -964,7 +964,7 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x29, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, - 0x67, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x84, + 0x67, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa1, 0x0f, 0x0a, 0x0b, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x49, 0x0a, 0x0e, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, @@ -1003,167 +1003,170 @@ var file_attestation_v1_crafting_state_proto_rawDesc = []byte{ 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x72, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x04, 0x68, 0x65, 0x61, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x12, 0x32, 0x0a, 0x08, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x04, 0x68, 0x65, 0x61, 0x64, 0x12, 0x4f, 0x0a, 0x12, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x11, 0x70, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x45, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x62, 0x0a, + 0x0e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 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, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, + 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 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, 0x1a, 0x82, 0x08, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12, 0x45, + 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x1a, 0x62, 0x0a, 0x0e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 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, 0x3a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 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, 0x1a, 0x82, 0x08, 0x0a, 0x08, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, - 0x6c, 0x12, 0x45, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2b, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x48, 0x00, - 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x5e, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x33, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, - 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, - 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x61, 0x72, 0x74, - 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x61, - 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x07, 0x61, 0x64, 0x64, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5e, 0x0a, 0x0d, - 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0e, 0x32, 0x39, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x63, 0x6f, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x4b, 0x65, 0x79, 0x56, 0x61, 0x6c, 0x48, 0x00, 0x52, 0x06, 0x73, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x5e, 0x0a, 0x0f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, + 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, + 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x0e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x4b, 0x0a, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x48, 0x00, 0x52, 0x08, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x12, 0x35, 0x0a, 0x08, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x65, 0x64, 0x41, 0x74, 0x12, 0x5e, 0x0a, 0x0d, 0x6d, 0x61, 0x74, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 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, 0x52, 0x0c, 0x6d, 0x61, 0x74, + 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x70, 0x6c, + 0x6f, 0x61, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x61, 0x73, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x54, 0x6f, 0x43, 0x61, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x61, 0x73, + 0x12, 0x65, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x0c, 0xba, 0x48, + 0x09, 0x9a, 0x01, 0x06, 0x2a, 0x04, 0x72, 0x02, 0x10, 0x01, 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, 0x1a, 0x40, 0x0a, 0x06, 0x4b, 0x65, 0x79, 0x56, 0x61, + 0x6c, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, + 0x10, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x98, 0x01, 0x0a, 0x0e, 0x43, 0x6f, + 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x17, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, + 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, 0x6a, 0x65, + 0x63, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x74, 0x61, 0x67, 0x1a, 0x9a, 0x01, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, + 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x42, 0x03, 0x0a, 0x01, 0x6d, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, 0x56, 0x61, 0x72, + 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, 0x8a, 0x03, 0x0a, 0x10, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x61, + 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x01, 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, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x62, 0x6f, + 0x64, 0x79, 0x12, 0x4a, 0x0a, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, + 0x61, 0x6c, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x4f, + 0x0a, 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x07, 0x73, + 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, + 0x03, 0xc8, 0x01, 0x01, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, + 0xba, 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, + 0xc9, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, + 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, + 0x61, 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, + 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, + 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, + 0x12, 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, + 0x52, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, + 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, + 0x43, 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, + 0x0c, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0c, - 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x26, 0x0a, 0x0f, - 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x61, 0x73, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x54, - 0x6f, 0x43, 0x61, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x63, - 0x61, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x6e, 0x6c, 0x69, 0x6e, 0x65, - 0x43, 0x61, 0x73, 0x12, 0x65, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x41, - 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, - 0x0c, 0xba, 0x48, 0x09, 0x9a, 0x01, 0x06, 0x2a, 0x04, 0x72, 0x02, 0x10, 0x01, 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, 0x1a, 0x40, 0x0a, 0x06, 0x4b, 0x65, - 0x79, 0x56, 0x61, 0x6c, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d, 0x0a, - 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x98, 0x01, 0x0a, - 0x0e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, - 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x06, - 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x62, - 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x53, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, 0x67, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x1a, 0x9a, 0x01, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x12, 0x17, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1b, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, - 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x64, 0x69, - 0x67, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, - 0x02, 0x10, 0x01, 0x52, 0x06, 0x64, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, - 0x73, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x09, 0x69, 0x73, 0x53, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 0x6f, 0x6e, - 0x74, 0x65, 0x6e, 0x74, 0x42, 0x03, 0x0a, 0x01, 0x6d, 0x1a, 0x3a, 0x0a, 0x0c, 0x45, 0x6e, 0x76, - 0x56, 0x61, 0x72, 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, 0xf6, 0x02, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x12, 0x97, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 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, 0x23, 0x0a, 0x0d, 0x6d, 0x61, - 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0c, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x1a, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, - 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x12, 0x40, 0x0a, 0x0a, 0x76, - 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x20, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0a, 0x76, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x4f, 0x0a, - 0x09, 0x56, 0x69, 0x6f, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x07, 0x73, 0x75, - 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, 0x48, 0x03, - 0xc8, 0x01, 0x01, 0x52, 0x07, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x20, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x06, 0xba, - 0x48, 0x03, 0xc8, 0x01, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xc9, - 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x04, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x2a, 0x0a, 0x0c, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x45, 0x6d, 0x61, - 0x69, 0x6c, 0x12, 0x28, 0x0a, 0x0b, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x5f, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, - 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x2e, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x04, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x37, 0x0a, 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x52, - 0x07, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x73, 0x1a, 0x40, 0x0a, 0x06, 0x52, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x6e, 0x67, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, + 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, + 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, + 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, + 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x19, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, - 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x43, - 0x72, 0x61, 0x66, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x46, 0x0a, 0x0c, - 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x23, 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, 0x52, 0x0b, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x61, 0x12, 0x3d, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x61, 0x74, 0x74, 0x65, - 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x64, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x22, 0x8e, 0x02, 0x0a, - 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x12, 0x1b, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, - 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, 0x6d, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, 0x0b, - 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, - 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, - 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, 0x30, - 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, - 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, - 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, 0x5a, - 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, 0x74, - 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, 0x72, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x65, 0x61, + 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x65, 0x61, 0x6d, 0x12, 0x28, 0x0a, + 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, 0x52, 0x0a, 0x77, 0x6f, 0x72, + 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, 0x12, 0x26, 0x0a, 0x0f, 0x77, 0x6f, 0x72, 0x6b, 0x66, + 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x66, 0x6c, 0x6f, 0x77, 0x52, 0x75, 0x6e, 0x49, 0x64, 0x12, + 0x30, 0x0a, 0x0f, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, + 0x01, 0x52, 0x0e, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x52, 0x65, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x2b, 0x0a, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x07, 0xba, 0x48, 0x04, 0x72, 0x02, 0x10, 0x01, + 0x52, 0x0c, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x54, + 0x5a, 0x52, 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, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x74, + 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x63, 0x72, 0x61, 0x66, 0x74, 0x65, + 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1181,7 +1184,7 @@ func file_attestation_v1_crafting_state_proto_rawDescGZIP() []byte { var file_attestation_v1_crafting_state_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_attestation_v1_crafting_state_proto_goTypes = []interface{}{ (*Attestation)(nil), // 0: attestation.v1.Attestation - (*Policy)(nil), // 1: attestation.v1.Policy + (*PolicyEvaluation)(nil), // 1: attestation.v1.PolicyEvaluation (*Commit)(nil), // 2: attestation.v1.Commit (*CraftingState)(nil), // 3: attestation.v1.CraftingState (*WorkflowMetadata)(nil), // 4: attestation.v1.WorkflowMetadata @@ -1193,7 +1196,7 @@ var file_attestation_v1_crafting_state_proto_goTypes = []interface{}{ (*Attestation_Material_KeyVal)(nil), // 10: attestation.v1.Attestation.Material.KeyVal (*Attestation_Material_ContainerImage)(nil), // 11: attestation.v1.Attestation.Material.ContainerImage (*Attestation_Material_Artifact)(nil), // 12: attestation.v1.Attestation.Material.Artifact - (*Policy_Violation)(nil), // 13: attestation.v1.Policy.Violation + (*PolicyEvaluation_Violation)(nil), // 13: attestation.v1.PolicyEvaluation.Violation (*Commit_Remote)(nil), // 14: attestation.v1.Commit.Remote (*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp (v1.CraftingSchema_Runner_RunnerType)(0), // 16: workflowcontract.v1.CraftingSchema.Runner.RunnerType @@ -1209,8 +1212,8 @@ var file_attestation_v1_crafting_state_proto_depIdxs = []int32{ 8, // 5: attestation.v1.Attestation.env_vars:type_name -> attestation.v1.Attestation.EnvVarsEntry 16, // 6: attestation.v1.Attestation.runner_type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType 2, // 7: attestation.v1.Attestation.head:type_name -> attestation.v1.Commit - 1, // 8: attestation.v1.Attestation.policies:type_name -> attestation.v1.Policy - 13, // 9: attestation.v1.Policy.violations:type_name -> attestation.v1.Policy.Violation + 1, // 8: attestation.v1.Attestation.policy_evaluations:type_name -> attestation.v1.PolicyEvaluation + 13, // 9: attestation.v1.PolicyEvaluation.violations:type_name -> attestation.v1.PolicyEvaluation.Violation 15, // 10: attestation.v1.Commit.date:type_name -> google.protobuf.Timestamp 14, // 11: attestation.v1.Commit.remotes:type_name -> attestation.v1.Commit.Remote 17, // 12: attestation.v1.CraftingState.input_schema:type_name -> workflowcontract.v1.CraftingSchema @@ -1248,7 +1251,7 @@ func file_attestation_v1_crafting_state_proto_init() { } } file_attestation_v1_crafting_state_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy); i { + switch v := v.(*PolicyEvaluation); i { case 0: return &v.state case 1: @@ -1344,7 +1347,7 @@ func file_attestation_v1_crafting_state_proto_init() { } } file_attestation_v1_crafting_state_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy_Violation); i { + switch v := v.(*PolicyEvaluation_Violation); i { case 0: return &v.state case 1: diff --git a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto index 8dd7536fa..f8b02b3ce 100644 --- a/internal/attestation/crafter/api/attestation/v1/crafting_state.proto +++ b/internal/attestation/crafter/api/attestation/v1/crafting_state.proto @@ -90,11 +90,11 @@ message Attestation { Commit head = 9; // Policies that materials in this attestation were validated against - repeated Policy policies = 10; + repeated PolicyEvaluation policy_evaluations = 10; } // A policy executed against an attestation or material -message Policy { +message PolicyEvaluation { // The policy name from the policy spec string name = 1 [(buf.validate.field) = { cel: { diff --git a/internal/attestation/crafter/crafter.go b/internal/attestation/crafter/crafter.go index 8c866cc0f..be2c20b47 100644 --- a/internal/attestation/crafter/crafter.go +++ b/internal/attestation/crafter/crafter.go @@ -578,7 +578,7 @@ func (c *Crafter) addMaterial(ctx context.Context, m *schemaapi.CraftingSchema_M return fmt.Errorf("error applying policies to material: %w", err) } // store policy results - c.CraftingState.Attestation.Policies = append(c.CraftingState.Attestation.Policies, policyResults...) + c.CraftingState.Attestation.PolicyEvaluations = append(c.CraftingState.Attestation.PolicyEvaluations, policyResults...) // 5 - Attach it to state if c.CraftingState.Attestation.Materials == nil { diff --git a/internal/attestation/renderer/chainloop/v02.go b/internal/attestation/renderer/chainloop/v02.go index 1366b250d..a0a66defc 100644 --- a/internal/attestation/renderer/chainloop/v02.go +++ b/internal/attestation/renderer/chainloop/v02.go @@ -38,7 +38,7 @@ type ProvenancePredicateV02 struct { *ProvenancePredicateCommon Materials []*intoto.ResourceDescriptor `json:"materials,omitempty"` // Map materials and policies - Policies map[string][]*v1.Policy `json:"policies,omitempty"` + PolicyEvaluations map[string][]*v1.PolicyEvaluation `json:"policy_evaluations,omitempty"` } type RendererV02 struct { @@ -148,12 +148,12 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { return nil, fmt.Errorf("error normalizing materials: %w", err) } - policies := policiesFromMaterials(r.att) + policies := policyEvaluationsFromMaterials(r.att) p := ProvenancePredicateV02{ ProvenancePredicateCommon: predicateCommon(r.builder, r.att), Materials: normalizedMaterials, - Policies: policies, + PolicyEvaluations: policies, } // transform to structpb.Struct in a two steps process @@ -172,10 +172,10 @@ func (r *RendererV02) predicate() (*structpb.Struct, error) { return predicate, nil } -// collect all policies grouped by material -func policiesFromMaterials(att *v1.Attestation) map[string][]*v1.Policy { - result := map[string][]*v1.Policy{} - for _, p := range att.GetPolicies() { +// collect all policy evaluations grouped by material +func policyEvaluationsFromMaterials(att *v1.Attestation) map[string][]*v1.PolicyEvaluation { + result := map[string][]*v1.PolicyEvaluation{} + for _, p := range att.GetPolicyEvaluations() { result[p.MaterialName] = append(result[p.MaterialName], p) } diff --git a/internal/attestation/renderer/renderer.go b/internal/attestation/renderer/renderer.go index 67f46bcd8..cab515e3e 100644 --- a/internal/attestation/renderer/renderer.go +++ b/internal/attestation/renderer/renderer.go @@ -152,7 +152,7 @@ func (ab *AttestationRenderer) Render(ctx context.Context) (*dsse.Envelope, erro return &dsseEnvelope, nil } -func addPolicyResults(statement *intoto.Statement, policyResults []*v1.Policy) error { +func addPolicyResults(statement *intoto.Statement, policyResults []*v1.PolicyEvaluation) error { predicate := statement.Predicate jsonPredicate, err := protojson.Marshal(predicate) if err != nil { @@ -163,10 +163,10 @@ func addPolicyResults(statement *intoto.Statement, policyResults []*v1.Policy) e if err != nil { return fmt.Errorf("unmarshalling predicate: %w", err) } - if p.Policies == nil { - p.Policies = make(map[string][]*v1.Policy) + if p.PolicyEvaluations == nil { + p.PolicyEvaluations = make(map[string][]*v1.PolicyEvaluation) } - p.Policies["ATTESTATION"] = policyResults + p.PolicyEvaluations["ATTESTATION"] = policyResults // marshall back to structpb jsonPredicate, err = json.Marshal(p) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 01f2be99a..9d9e72cf8 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -44,13 +44,12 @@ type PolicyVerifier struct { } func NewPolicyVerifier(schema *v1.CraftingSchema, logger *zerolog.Logger) *PolicyVerifier { - // only Rego engine is currently supported return &PolicyVerifier{schema: schema, logger: logger} } // VerifyMaterial applies all required policies to a material -func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Attestation_Material, artifactPath string) ([]*v12.Policy, error) { - result := make([]*v12.Policy, 0) +func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Attestation_Material, artifactPath string) ([]*v12.PolicyEvaluation, error) { + result := make([]*v12.PolicyEvaluation, 0) policies, err := pv.requiredPoliciesForMaterial(material) if err != nil { return nil, fmt.Errorf("error getting required policies for material: %w", err) @@ -83,7 +82,7 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte return nil, fmt.Errorf("failed to verify policy: %w", err) } - result = append(result, &v12.Policy{ + result = append(result, &v12.PolicyEvaluation{ Name: spec.GetMetadata().GetName(), MaterialName: material.GetArtifact().GetId(), Body: base64.StdEncoding.EncodeToString(script.Source), @@ -95,8 +94,8 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte } // VerifyStatement verifies that the statement is compliant with the policies present in the schema -func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto.Statement) ([]*v12.Policy, error) { - result := make([]*v12.Policy, 0) +func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto.Statement) ([]*v12.PolicyEvaluation, error) { + result := make([]*v12.PolicyEvaluation, 0) policies := pv.schema.GetPolicies().GetAttestation() for _, policyAtt := range policies { // 1. load the policy spec @@ -131,7 +130,7 @@ func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto } // 5. Store result in the attestation itself (for the renderer to include them in the predicate) - result = append(result, &v12.Policy{ + result = append(result, &v12.PolicyEvaluation{ Name: spec.Metadata.Name, Body: base64.StdEncoding.EncodeToString(script.Source), Violations: policyViolationsToAttestationViolations(res), @@ -141,10 +140,10 @@ func (pv *PolicyVerifier) VerifyStatement(ctx context.Context, statement *intoto return result, nil } -func engineViolationsToAPIViolations(input []*engine.PolicyViolation) []*v12.Policy_Violation { - res := make([]*v12.Policy_Violation, 0) +func engineViolationsToAPIViolations(input []*engine.PolicyViolation) []*v12.PolicyEvaluation_Violation { + res := make([]*v12.PolicyEvaluation_Violation, 0) for _, v := range input { - res = append(res, &v12.Policy_Violation{ + res = append(res, &v12.PolicyEvaluation_Violation{ Subject: v.Subject, Message: v.Violation, }) @@ -228,9 +227,9 @@ func getPolicyEngine(_ *v1.Policy) engine.PolicyEngine { return new(rego.Rego) } -func policyViolationsToAttestationViolations(violations []*engine.PolicyViolation) (pvs []*v12.Policy_Violation) { +func policyViolationsToAttestationViolations(violations []*engine.PolicyViolation) (pvs []*v12.PolicyEvaluation_Violation) { for _, violation := range violations { - pvs = append(pvs, &v12.Policy_Violation{ + pvs = append(pvs, &v12.PolicyEvaluation_Violation{ Subject: violation.Subject, Message: violation.Violation, }) From 84f4475132b6b0f653feb8bfc30c7c82d4dad338 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 18:08:09 +0200 Subject: [PATCH 64/73] remove stage, as it's not yet implemented Signed-off-by: Jose I. Paris --- .../workflowcontract/v1/crafting_schema.ts | 22 +----- .../workflowcontract/v1/crafting_schema.pb.go | 69 ++++++++----------- .../workflowcontract/v1/crafting_schema.proto | 6 +- app/controlplane/pkg/data/ent/runtime.go | 1 - 4 files changed, 30 insertions(+), 68 deletions(-) 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 713246a1b..12418943e 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -299,11 +299,6 @@ export interface PolicySpec { embedded?: | string | undefined; - /** - * stage at which this policy will be run. - * Only "push" is supported currently and this field will be ignored - */ - stage: PolicySpec_PolicyStage; /** * if set, it will match any material supported by Chainloop * except those not having a schema @@ -1229,7 +1224,7 @@ export const Metadata = { }; function createBasePolicySpec(): PolicySpec { - return { path: undefined, embedded: undefined, stage: 0, type: 0 }; + return { path: undefined, embedded: undefined, type: 0 }; } export const PolicySpec = { @@ -1240,11 +1235,8 @@ export const PolicySpec = { if (message.embedded !== undefined) { writer.uint32(18).string(message.embedded); } - if (message.stage !== 0) { - writer.uint32(24).int32(message.stage); - } if (message.type !== 0) { - writer.uint32(32).int32(message.type); + writer.uint32(24).int32(message.type); } return writer; }, @@ -1275,13 +1267,6 @@ export const PolicySpec = { break; } - message.stage = reader.int32() as any; - continue; - case 4: - if (tag !== 32) { - break; - } - message.type = reader.int32() as any; continue; } @@ -1297,7 +1282,6 @@ export const PolicySpec = { return { path: isSet(object.path) ? String(object.path) : undefined, embedded: isSet(object.embedded) ? String(object.embedded) : undefined, - stage: isSet(object.stage) ? policySpec_PolicyStageFromJSON(object.stage) : 0, type: isSet(object.type) ? craftingSchema_Material_MaterialTypeFromJSON(object.type) : 0, }; }, @@ -1306,7 +1290,6 @@ export const PolicySpec = { const obj: any = {}; message.path !== undefined && (obj.path = message.path); message.embedded !== undefined && (obj.embedded = message.embedded); - message.stage !== undefined && (obj.stage = policySpec_PolicyStageToJSON(message.stage)); message.type !== undefined && (obj.type = craftingSchema_Material_MaterialTypeToJSON(message.type)); return obj; }, @@ -1319,7 +1302,6 @@ export const PolicySpec = { const message = createBasePolicySpec(); message.path = object.path ?? undefined; message.embedded = object.embedded ?? undefined; - message.stage = object.stage ?? 0; message.type = object.type ?? 0; return message; }, diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index e9b176c6e..f1fe72ad7 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -688,12 +688,9 @@ type PolicySpec struct { // *PolicySpec_Path // *PolicySpec_Embedded Source isPolicySpec_Source `protobuf_oneof:"source"` - // stage at which this policy will be run. - // Only "push" is supported currently and this field will be ignored - Stage PolicySpec_PolicyStage `protobuf:"varint,3,opt,name=stage,proto3,enum=workflowcontract.v1.PolicySpec_PolicyStage" json:"stage,omitempty"` // if set, it will match any material supported by Chainloop // except those not having a schema - Type CraftingSchema_Material_MaterialType `protobuf:"varint,4,opt,name=type,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"type,omitempty"` + Type CraftingSchema_Material_MaterialType `protobuf:"varint,3,opt,name=type,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"type,omitempty"` } func (x *PolicySpec) Reset() { @@ -749,13 +746,6 @@ func (x *PolicySpec) GetEmbedded() string { return "" } -func (x *PolicySpec) GetStage() PolicySpec_PolicyStage { - if x != nil { - return x.Stage - } - return PolicySpec_UNSPECIFIED -} - func (x *PolicySpec) GetType() CraftingSchema_Material_MaterialType { if x != nil { return x.Type @@ -1167,30 +1157,26 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0x22, 0x9c, 0x02, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, + 0x6d, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 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, 0x41, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 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, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, 0x67, - 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x67, 0x65, 0x12, 0x5c, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x04, 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, 0x74, 0x79, 0x70, 0x65, 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x53, 0x74, 0x61, 0x67, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, - 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, + 0x65, 0x64, 0x64, 0x65, 0x64, 0x12, 0x5c, 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, 0x0d, + 0xba, 0x48, 0x0a, 0x82, 0x01, 0x07, 0x22, 0x05, 0x01, 0x02, 0x03, 0x0a, 0x0b, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, + 0x67, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, 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, } var ( @@ -1235,16 +1221,15 @@ var file_workflowcontract_v1_crafting_schema_proto_depIdxs = []int32{ 13, // 8: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.PolicyArgument 8, // 9: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata 9, // 10: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec - 2, // 11: workflowcontract.v1.PolicySpec.stage:type_name -> workflowcontract.v1.PolicySpec.PolicyStage - 1, // 12: workflowcontract.v1.PolicySpec.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 0, // 13: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType - 1, // 14: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 4, // 15: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation - 16, // [16:16] is the sub-list for method output_type - 16, // [16:16] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 1, // 11: workflowcontract.v1.PolicySpec.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 0, // 12: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType + 1, // 13: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType + 4, // 14: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation + 15, // [15:15] is the sub-list for method output_type + 15, // [15:15] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_workflowcontract_v1_crafting_schema_proto_init() } diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 3837c4fed..2557686a1 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -187,13 +187,9 @@ message PolicySpec { option (buf.validate.oneof).required = true; }; - // stage at which this policy will be run. - // Only "push" is supported currently and this field will be ignored - PolicyStage stage = 3; - // if set, it will match any material supported by Chainloop // except those not having a schema - CraftingSchema.Material.MaterialType type = 4 [(buf.validate.field).enum = { not_in: [1, 2, 3, 10, 11]}]; + CraftingSchema.Material.MaterialType type = 3 [(buf.validate.field).enum = { not_in: [1, 2, 3, 10, 11]}]; // buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX diff --git a/app/controlplane/pkg/data/ent/runtime.go b/app/controlplane/pkg/data/ent/runtime.go index cb579976d..c3267eb96 100644 --- a/app/controlplane/pkg/data/ent/runtime.go +++ b/app/controlplane/pkg/data/ent/runtime.go @@ -1,4 +1,3 @@ -// +build tools // Code generated by ent, DO NOT EDIT. package ent From 9cba1d058bf43d684839821ceca011cf72b1669f Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 18:12:32 +0200 Subject: [PATCH 65/73] move policies Signed-off-by: Jose I. Paris --- internal/attestation/crafter/crafter_test.go | 4 ++-- .../crafter/testdata/contracts/with_policy_embedded.yaml | 2 +- .../crafter/testdata/contracts/with_policy_missing_rego.yaml | 2 +- .../attestation/crafter/testdata/contracts/with_rego.yaml | 2 +- .../crafter/testdata/{contracts => policies}/policy.rego | 0 .../testdata/{contracts => policies}/policy_embedded.yaml | 0 .../testdata/{contracts => policies}/policy_missing_rego.yaml | 0 .../crafter/testdata/{contracts => policies}/policy_rego.yaml | 2 +- 8 files changed, 6 insertions(+), 6 deletions(-) rename internal/attestation/crafter/testdata/{contracts => policies}/policy.rego (100%) rename internal/attestation/crafter/testdata/{contracts => policies}/policy_embedded.yaml (100%) rename internal/attestation/crafter/testdata/{contracts => policies}/policy_missing_rego.yaml (100%) rename internal/attestation/crafter/testdata/{contracts => policies}/policy_rego.yaml (70%) diff --git a/internal/attestation/crafter/crafter_test.go b/internal/attestation/crafter/crafter_test.go index 4fdd12503..0cd336f02 100644 --- a/internal/attestation/crafter/crafter_test.go +++ b/internal/attestation/crafter/crafter_test.go @@ -229,7 +229,7 @@ func (s *crafterSuite) TestLoadSchema() { Attestation: []*schemaapi.PolicyAttachment{ { Policy: &schemaapi.PolicyAttachment_Ref{ - Ref: "testdata/contracts/policy_embedded.yaml", + Ref: "testdata/policies/policy_embedded.yaml", }, }, }, @@ -255,7 +255,7 @@ func (s *crafterSuite) TestLoadSchema() { Attestation: []*schemaapi.PolicyAttachment{ { Policy: &schemaapi.PolicyAttachment_Ref{ - Ref: "testdata/contracts/policy_rego.yaml", + Ref: "testdata/policies/policy_rego.yaml", }, }, }, diff --git a/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml b/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml index 74fdb60c1..39dcb1325 100644 --- a/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_policy_embedded.yaml @@ -1,4 +1,4 @@ schemaVersion: "v1" policies: attestation: - - ref: testdata/contracts/policy_embedded.yaml + - ref: testdata/policies/policy_embedded.yaml diff --git a/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml b/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml index a4a5479d9..4260c1de3 100644 --- a/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_policy_missing_rego.yaml @@ -1,4 +1,4 @@ schemaVersion: "v1" policies: attestation: - - ref: testdata/contracts/policy_missing_rego.yaml + - ref: testdata/policies/policy_missing_rego.yaml diff --git a/internal/attestation/crafter/testdata/contracts/with_rego.yaml b/internal/attestation/crafter/testdata/contracts/with_rego.yaml index edea0403d..d56ca9902 100644 --- a/internal/attestation/crafter/testdata/contracts/with_rego.yaml +++ b/internal/attestation/crafter/testdata/contracts/with_rego.yaml @@ -1,4 +1,4 @@ schemaVersion: "v1" policies: attestation: - - ref: testdata/contracts/policy_rego.yaml + - ref: testdata/policies/policy_rego.yaml diff --git a/internal/attestation/crafter/testdata/contracts/policy.rego b/internal/attestation/crafter/testdata/policies/policy.rego similarity index 100% rename from internal/attestation/crafter/testdata/contracts/policy.rego rename to internal/attestation/crafter/testdata/policies/policy.rego diff --git a/internal/attestation/crafter/testdata/contracts/policy_embedded.yaml b/internal/attestation/crafter/testdata/policies/policy_embedded.yaml similarity index 100% rename from internal/attestation/crafter/testdata/contracts/policy_embedded.yaml rename to internal/attestation/crafter/testdata/policies/policy_embedded.yaml diff --git a/internal/attestation/crafter/testdata/contracts/policy_missing_rego.yaml b/internal/attestation/crafter/testdata/policies/policy_missing_rego.yaml similarity index 100% rename from internal/attestation/crafter/testdata/contracts/policy_missing_rego.yaml rename to internal/attestation/crafter/testdata/policies/policy_missing_rego.yaml diff --git a/internal/attestation/crafter/testdata/contracts/policy_rego.yaml b/internal/attestation/crafter/testdata/policies/policy_rego.yaml similarity index 70% rename from internal/attestation/crafter/testdata/contracts/policy_rego.yaml rename to internal/attestation/crafter/testdata/policies/policy_rego.yaml index 1a64eeb9e..4c52a0c5b 100644 --- a/internal/attestation/crafter/testdata/contracts/policy_rego.yaml +++ b/internal/attestation/crafter/testdata/policies/policy_rego.yaml @@ -3,4 +3,4 @@ kind: Policy metadata: name: workflow spec: - path: testdata/contracts/policy.rego + path: testdata/policies/policy.rego From bc68c1e1a6d2fcc18cd9fc26b8da4b508365931f Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 18:15:54 +0200 Subject: [PATCH 66/73] add empty line Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 9d9e72cf8..3920b2eff 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -50,10 +50,12 @@ func NewPolicyVerifier(schema *v1.CraftingSchema, logger *zerolog.Logger) *Polic // VerifyMaterial applies all required policies to a material func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Attestation_Material, artifactPath string) ([]*v12.PolicyEvaluation, error) { result := make([]*v12.PolicyEvaluation, 0) + policies, err := pv.requiredPoliciesForMaterial(material) if err != nil { return nil, fmt.Errorf("error getting required policies for material: %w", err) } + for _, policy := range policies { // 1. load the policy spec spec, err := LoadPolicySpec(policy) From b1b15c12f6da542aee0e572362c40ea29cdec4c4 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 18:24:10 +0200 Subject: [PATCH 67/73] more suggestions Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 3920b2eff..3f866ec55 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -79,7 +79,7 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte // verify the policy ng := getPolicyEngine(spec) - res, err := ng.Verify(ctx, script, subject) + violations, err := ng.Verify(ctx, script, subject) if err != nil { return nil, fmt.Errorf("failed to verify policy: %w", err) } @@ -88,7 +88,7 @@ func (pv *PolicyVerifier) VerifyMaterial(ctx context.Context, material *v12.Atte Name: spec.GetMetadata().GetName(), MaterialName: material.GetArtifact().GetId(), Body: base64.StdEncoding.EncodeToString(script.Source), - Violations: engineViolationsToAPIViolations(res), + Violations: engineViolationsToAPIViolations(violations), }) } @@ -186,6 +186,10 @@ func getMaterialContent(material *v12.Attestation_Material, artifactPath string) return rawMaterial, nil } +// returns the list of polices to be applied to a material, following these rules: +// 1. if policy spec has a type, return it only if material has the same type +// 2. if attachment has a name filter, return the policy only if the material has the same name +// 3. if policy spec doesn't have a type, a name filter is mandatory (otherwise there is no way to know if material has to be applied) func (pv *PolicyVerifier) requiredPoliciesForMaterial(material *v12.Attestation_Material) ([]*v1.PolicyAttachment, error) { result := make([]*v1.PolicyAttachment, 0) policies := pv.schema.GetPolicies().GetMaterials() From e2f09e2a3ffa845fc35c0aa348dc8319d9053657 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 18:29:29 +0200 Subject: [PATCH 68/73] document addPolicyResults Signed-off-by: Jose I. Paris --- internal/attestation/renderer/renderer.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/internal/attestation/renderer/renderer.go b/internal/attestation/renderer/renderer.go index cab515e3e..dafb0d8a1 100644 --- a/internal/attestation/renderer/renderer.go +++ b/internal/attestation/renderer/renderer.go @@ -152,27 +152,37 @@ func (ab *AttestationRenderer) Render(ctx context.Context) (*dsse.Envelope, erro return &dsseEnvelope, nil } +// addPolicyResults adds policy evaluation results to the statement. It does it by deserializing the predicate from a structpb.Struct, +// filling PolicyEvaluations, and serializing it again to a structpb.Struct object, using JSON as an intermediate representation. +// Note that this is needed because intoto predicates are generic structpb.Struct func addPolicyResults(statement *intoto.Statement, policyResults []*v1.PolicyEvaluation) error { predicate := statement.Predicate + // marshall to json jsonPredicate, err := protojson.Marshal(predicate) if err != nil { return fmt.Errorf("marshalling predicate: %w", err) } + + // unmarshall to our typed predicate object var p chainloop.ProvenancePredicateV02 err = json.Unmarshal(jsonPredicate, &p) if err != nil { return fmt.Errorf("unmarshalling predicate: %w", err) } + + // insert policy evaluations if p.PolicyEvaluations == nil { p.PolicyEvaluations = make(map[string][]*v1.PolicyEvaluation) } p.PolicyEvaluations["ATTESTATION"] = policyResults - // marshall back to structpb + // marshall back to JSON jsonPredicate, err = json.Marshal(p) if err != nil { return fmt.Errorf("marshalling predicate: %w", err) } + + // finally unmarshal from JSON to structpb.Struct. var finalPredicate structpb.Struct err = protojson.Unmarshal(jsonPredicate, &finalPredicate) if err != nil { From 1f083fc17f7fc2b739843aba93f21c9732bedfb6 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Tue, 16 Jul 2024 18:35:31 +0200 Subject: [PATCH 69/73] add comment Signed-off-by: Jose I. Paris --- .../api/gen/frontend/workflowcontract/v1/crafting_schema.ts | 3 ++- app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go | 3 ++- app/controlplane/api/workflowcontract/v1/crafting_schema.proto | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) 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 12418943e..deb49a77a 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -301,7 +301,8 @@ export interface PolicySpec { | undefined; /** * if set, it will match any material supported by Chainloop - * except those not having a schema + * except those not having a direct schema (STRING, ARTIFACT, EVIDENCE), since their format cannot be guessed by the crafter. + * CONTAINER, HELM_CHART are also excluded, but we might implement custom policies for them in the future. */ type: CraftingSchema_Material_MaterialType; } diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index f1fe72ad7..bab510dc6 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -689,7 +689,8 @@ type PolicySpec struct { // *PolicySpec_Embedded Source isPolicySpec_Source `protobuf_oneof:"source"` // if set, it will match any material supported by Chainloop - // except those not having a schema + // except those not having a direct schema (STRING, ARTIFACT, EVIDENCE), since their format cannot be guessed by the crafter. + // CONTAINER, HELM_CHART are also excluded, but we might implement custom policies for them in the future. Type CraftingSchema_Material_MaterialType `protobuf:"varint,3,opt,name=type,proto3,enum=workflowcontract.v1.CraftingSchema_Material_MaterialType" json:"type,omitempty"` } diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 2557686a1..44ae15a74 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -188,7 +188,8 @@ message PolicySpec { }; // if set, it will match any material supported by Chainloop - // except those not having a schema + // except those not having a direct schema (STRING, ARTIFACT, EVIDENCE), since their format cannot be guessed by the crafter. + // CONTAINER, HELM_CHART are also excluded, but we might implement custom policies for them in the future. CraftingSchema.Material.MaterialType type = 3 [(buf.validate.field).enum = { not_in: [1, 2, 3, 10, 11]}]; // buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX From 0eafd1856e5f28efac6c363bce5bdb14edc7d0f5 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 17 Jul 2024 00:13:35 +0200 Subject: [PATCH 70/73] use envelope method to decode payload Signed-off-by: Jose I. Paris --- pkg/policies/policies.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 3f866ec55..26ee3a7e2 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -177,7 +177,7 @@ func getMaterialContent(material *v12.Attestation_Material, artifactPath string) return nil, fmt.Errorf("failed to unmarshal attestation material: %w", err) } - _, err = base64.StdEncoding.Decode(rawMaterial, []byte(envelope.Payload)) + rawMaterial, err = envelope.DecodeB64Payload() if err != nil { return nil, fmt.Errorf("failed to decode attestation material: %w", err) } From c640d3d0fec5792cb2712f2339956c9a8bcb09d1 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 17 Jul 2024 00:47:15 +0200 Subject: [PATCH 71/73] add tests and validate always Signed-off-by: Jose I. Paris --- .../workflowcontract/v1/crafting_schema.proto | 7 -- pkg/policies/policies.go | 57 ++++++++++------ pkg/policies/policies_test.go | 67 +++++++++++++++++++ 3 files changed, 103 insertions(+), 28 deletions(-) diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto index 44ae15a74..8f08c11d4 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.proto +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.proto @@ -191,11 +191,4 @@ message PolicySpec { // except those not having a direct schema (STRING, ARTIFACT, EVIDENCE), since their format cannot be guessed by the crafter. // CONTAINER, HELM_CHART are also excluded, but we might implement custom policies for them in the future. CraftingSchema.Material.MaterialType type = 3 [(buf.validate.field).enum = { not_in: [1, 2, 3, 10, 11]}]; - - // buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX - // buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - enum PolicyStage { - UNSPECIFIED = 0; - PUSH = 1; - } } diff --git a/pkg/policies/policies.go b/pkg/policies/policies.go index 26ee3a7e2..acea8ba2c 100644 --- a/pkg/policies/policies.go +++ b/pkg/policies/policies.go @@ -245,38 +245,53 @@ func policyViolationsToAttestationViolations(violations []*engine.PolicyViolatio // LoadPolicySpec loads and validates a policy spec from a contract func LoadPolicySpec(attachment *v1.PolicyAttachment) (*v1.Policy, error) { - if attachment.GetEmbedded() != nil { - return attachment.GetEmbedded(), nil + reference := attachment.GetRef() + embedded := attachment.GetEmbedded() + + if embedded == nil && reference == "" { + return nil, errors.New("policy must be referenced or embedded in the attachment") } - // if policy is not embedded in the contract, we'll look for it + var spec v1.Policy + if embedded != nil { + spec = *attachment.GetEmbedded() + } else { + // look for the referenced policy spec (note: loading by `name` is not supported yet) + // this method understands env, http and https schemes, and defaults to file system. + rawData, err := blob.LoadFileOrURL(reference) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) + } - // look for the referenced policy spec (note: loading by `name` is not supported yet) - reference := attachment.GetRef() - // this method understands env, http and https schemes, and defaults to file system. - rawData, err := blob.LoadFileOrURL(reference) - if err != nil { - return nil, fmt.Errorf("loading policy spec: %w", err) - } - jsonContent, err := materials.LoadJSONBytes(rawData, filepath.Ext(reference)) - if err != nil { - return nil, fmt.Errorf("loading policy spec: %w", err) - } - var policy v1.Policy - if err := protojson.Unmarshal(jsonContent, &policy); err != nil { - return nil, fmt.Errorf("unmarshalling policy spec: %w", err) + jsonContent, err := materials.LoadJSONBytes(rawData, filepath.Ext(reference)) + if err != nil { + return nil, fmt.Errorf("loading policy spec: %w", err) + } + + if err := protojson.Unmarshal(jsonContent, &spec); err != nil { + return nil, fmt.Errorf("unmarshalling policy spec: %w", err) + } } + // Validate just in case + if err := validatePolicy(&spec); err != nil { + return nil, fmt.Errorf("invalid policy: %w", err) + } + + return &spec, nil +} + +func validatePolicy(policy *v1.Policy) error { validator, err := protovalidate.New() if err != nil { - return nil, fmt.Errorf("validating policy spec: %w", err) + return fmt.Errorf("validating policy spec: %w", err) } - err = validator.Validate(&policy) + err = validator.Validate(policy) if err != nil { - return nil, fmt.Errorf("validating policy spec: %w", err) + return fmt.Errorf("validating policy spec: %w", err) } - return &policy, nil + return nil } // LoadPolicyScriptFromSpec loads a policy referenced from the spec diff --git a/pkg/policies/policies_test.go b/pkg/policies/policies_test.go index 419e4b3fd..dc75d4464 100644 --- a/pkg/policies/policies_test.go +++ b/pkg/policies/policies_test.go @@ -339,6 +339,73 @@ func (s *testSuite) TestInvalidInlineMaterial() { s.Equal("Not made with syft", res[0].Violations[0].Message) } +func (s *testSuite) TestLoadPolicySpec() { + var cases = []struct { + name string + attachment *v12.PolicyAttachment + wantErr bool + expectedName string + }{ + { + name: "missing policy", + attachment: &v12.PolicyAttachment{}, + wantErr: true, + }, + { + name: "by ref", + attachment: &v12.PolicyAttachment{ + Policy: &v12.PolicyAttachment_Ref{ + Ref: "testdata/sbom_syft.yaml", + }, + }, + expectedName: "made-with-syft", + }, + { + name: "embedded invalid", + attachment: &v12.PolicyAttachment{ + Policy: &v12.PolicyAttachment_Embedded{ + Embedded: &v12.Policy{ + ApiVersion: "", + Kind: "", + Metadata: &v12.Metadata{Name: "my-policy"}, + Spec: nil, + }, + }, + }, + wantErr: true, + }, + { + name: "embedded valid", + attachment: &v12.PolicyAttachment{ + Policy: &v12.PolicyAttachment_Embedded{ + Embedded: &v12.Policy{ + ApiVersion: "workflowcontract.chainloop.dev/v1", + Kind: "Policy", + Metadata: &v12.Metadata{Name: "my-policy"}, + Spec: &v12.PolicySpec{ + Source: &v12.PolicySpec_Path{Path: "file.rego"}, + Type: v12.CraftingSchema_Material_OPENVEX, + }, + }, + }, + }, + expectedName: "my-policy", + }, + } + + for _, tc := range cases { + s.Run(tc.name, func() { + p, err := LoadPolicySpec(tc.attachment) + if tc.wantErr { + s.Error(err) + return + } + s.Require().NoError(err) + s.Equal(tc.expectedName, p.Metadata.Name) + }) + } +} + type testSuite struct { suite.Suite From c36d9158820f3bf7ab824d7dd4b8a9b8024ff01a Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 17 Jul 2024 00:51:11 +0200 Subject: [PATCH 72/73] make generate Signed-off-by: Jose I. Paris --- .../workflowcontract/v1/crafting_schema.ts | 37 ------ .../workflowcontract/v1/crafting_schema.pb.go | 118 +++++------------- 2 files changed, 33 insertions(+), 122 deletions(-) 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 deb49a77a..68722776c 100644 --- a/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts +++ b/app/controlplane/api/gen/frontend/workflowcontract/v1/crafting_schema.ts @@ -307,43 +307,6 @@ export interface PolicySpec { type: CraftingSchema_Material_MaterialType; } -/** - * buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX - * buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX - */ -export enum PolicySpec_PolicyStage { - UNSPECIFIED = 0, - PUSH = 1, - UNRECOGNIZED = -1, -} - -export function policySpec_PolicyStageFromJSON(object: any): PolicySpec_PolicyStage { - switch (object) { - case 0: - case "UNSPECIFIED": - return PolicySpec_PolicyStage.UNSPECIFIED; - case 1: - case "PUSH": - return PolicySpec_PolicyStage.PUSH; - case -1: - case "UNRECOGNIZED": - default: - return PolicySpec_PolicyStage.UNRECOGNIZED; - } -} - -export function policySpec_PolicyStageToJSON(object: PolicySpec_PolicyStage): string { - switch (object) { - case PolicySpec_PolicyStage.UNSPECIFIED: - return "UNSPECIFIED"; - case PolicySpec_PolicyStage.PUSH: - return "PUSH"; - case PolicySpec_PolicyStage.UNRECOGNIZED: - default: - return "UNRECOGNIZED"; - } -} - function createBaseCraftingSchema(): CraftingSchema { return { schemaVersion: "", diff --git a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go index bab510dc6..13d4110dc 100644 --- a/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go +++ b/app/controlplane/api/workflowcontract/v1/crafting_schema.pb.go @@ -192,54 +192,6 @@ func (CraftingSchema_Material_MaterialType) EnumDescriptor() ([]byte, []int) { return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{0, 1, 0} } -// buf:lint:ignore ENUM_VALUE_PREFIX ENUM_ZERO_VALUE_SUFFIX -// buf:lint:ignore ENUM_ZERO_VALUE_SUFFIX -type PolicySpec_PolicyStage int32 - -const ( - PolicySpec_UNSPECIFIED PolicySpec_PolicyStage = 0 - PolicySpec_PUSH PolicySpec_PolicyStage = 1 -) - -// Enum value maps for PolicySpec_PolicyStage. -var ( - PolicySpec_PolicyStage_name = map[int32]string{ - 0: "UNSPECIFIED", - 1: "PUSH", - } - PolicySpec_PolicyStage_value = map[string]int32{ - "UNSPECIFIED": 0, - "PUSH": 1, - } -) - -func (x PolicySpec_PolicyStage) Enum() *PolicySpec_PolicyStage { - p := new(PolicySpec_PolicyStage) - *p = x - return p -} - -func (x PolicySpec_PolicyStage) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (PolicySpec_PolicyStage) Descriptor() protoreflect.EnumDescriptor { - return file_workflowcontract_v1_crafting_schema_proto_enumTypes[2].Descriptor() -} - -func (PolicySpec_PolicyStage) Type() protoreflect.EnumType { - return &file_workflowcontract_v1_crafting_schema_proto_enumTypes[2] -} - -func (x PolicySpec_PolicyStage) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use PolicySpec_PolicyStage.Descriptor instead. -func (PolicySpec_PolicyStage) EnumDescriptor() ([]byte, []int) { - return file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP(), []int{6, 0} -} - // Schema definition provided by the user to the tool // that defines the schema of the workflowRun type CraftingSchema struct { @@ -1158,7 +1110,7 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0x22, 0xd9, 0x01, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, + 0x6d, 0x65, 0x22, 0xaf, 0x01, 0x0a, 0x0a, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x70, 0x65, 0x63, 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, @@ -1168,16 +1120,13 @@ var file_workflowcontract_v1_crafting_schema_proto_rawDesc = []byte{ 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, 0x74, - 0x79, 0x70, 0x65, 0x22, 0x28, 0x0a, 0x0b, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x53, 0x74, 0x61, - 0x67, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x50, 0x55, 0x53, 0x48, 0x10, 0x01, 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, + 0x79, 0x70, 0x65, 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, } var ( @@ -1192,40 +1141,39 @@ func file_workflowcontract_v1_crafting_schema_proto_rawDescGZIP() []byte { return file_workflowcontract_v1_crafting_schema_proto_rawDescData } -var file_workflowcontract_v1_crafting_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_workflowcontract_v1_crafting_schema_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_workflowcontract_v1_crafting_schema_proto_msgTypes = make([]protoimpl.MessageInfo, 11) 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 - (PolicySpec_PolicyStage)(0), // 2: workflowcontract.v1.PolicySpec.PolicyStage - (*CraftingSchema)(nil), // 3: workflowcontract.v1.CraftingSchema - (*Annotation)(nil), // 4: workflowcontract.v1.Annotation - (*Policies)(nil), // 5: workflowcontract.v1.Policies - (*PolicyAttachment)(nil), // 6: workflowcontract.v1.PolicyAttachment - (*Policy)(nil), // 7: workflowcontract.v1.Policy - (*Metadata)(nil), // 8: workflowcontract.v1.Metadata - (*PolicySpec)(nil), // 9: workflowcontract.v1.PolicySpec - (*CraftingSchema_Runner)(nil), // 10: workflowcontract.v1.CraftingSchema.Runner - (*CraftingSchema_Material)(nil), // 11: workflowcontract.v1.CraftingSchema.Material - (*PolicyAttachment_MaterialSelector)(nil), // 12: workflowcontract.v1.PolicyAttachment.MaterialSelector - (*PolicyAttachment_PolicyArgument)(nil), // 13: workflowcontract.v1.PolicyAttachment.PolicyArgument + (*CraftingSchema)(nil), // 2: workflowcontract.v1.CraftingSchema + (*Annotation)(nil), // 3: workflowcontract.v1.Annotation + (*Policies)(nil), // 4: workflowcontract.v1.Policies + (*PolicyAttachment)(nil), // 5: workflowcontract.v1.PolicyAttachment + (*Policy)(nil), // 6: workflowcontract.v1.Policy + (*Metadata)(nil), // 7: workflowcontract.v1.Metadata + (*PolicySpec)(nil), // 8: workflowcontract.v1.PolicySpec + (*CraftingSchema_Runner)(nil), // 9: workflowcontract.v1.CraftingSchema.Runner + (*CraftingSchema_Material)(nil), // 10: workflowcontract.v1.CraftingSchema.Material + (*PolicyAttachment_MaterialSelector)(nil), // 11: workflowcontract.v1.PolicyAttachment.MaterialSelector + (*PolicyAttachment_PolicyArgument)(nil), // 12: workflowcontract.v1.PolicyAttachment.PolicyArgument } 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 - 4, // 2: workflowcontract.v1.CraftingSchema.annotations:type_name -> workflowcontract.v1.Annotation - 5, // 3: workflowcontract.v1.CraftingSchema.policies:type_name -> workflowcontract.v1.Policies - 6, // 4: workflowcontract.v1.Policies.materials:type_name -> workflowcontract.v1.PolicyAttachment - 6, // 5: workflowcontract.v1.Policies.attestation:type_name -> workflowcontract.v1.PolicyAttachment - 7, // 6: workflowcontract.v1.PolicyAttachment.embedded:type_name -> workflowcontract.v1.Policy - 12, // 7: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector - 13, // 8: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.PolicyArgument - 8, // 9: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata - 9, // 10: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec + 10, // 0: workflowcontract.v1.CraftingSchema.materials:type_name -> workflowcontract.v1.CraftingSchema.Material + 9, // 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 + 11, // 7: workflowcontract.v1.PolicyAttachment.selector:type_name -> workflowcontract.v1.PolicyAttachment.MaterialSelector + 12, // 8: workflowcontract.v1.PolicyAttachment.with:type_name -> workflowcontract.v1.PolicyAttachment.PolicyArgument + 7, // 9: workflowcontract.v1.Policy.metadata:type_name -> workflowcontract.v1.Metadata + 8, // 10: workflowcontract.v1.Policy.spec:type_name -> workflowcontract.v1.PolicySpec 1, // 11: workflowcontract.v1.PolicySpec.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType 0, // 12: workflowcontract.v1.CraftingSchema.Runner.type:type_name -> workflowcontract.v1.CraftingSchema.Runner.RunnerType 1, // 13: workflowcontract.v1.CraftingSchema.Material.type:type_name -> workflowcontract.v1.CraftingSchema.Material.MaterialType - 4, // 14: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation + 3, // 14: workflowcontract.v1.CraftingSchema.Material.annotations:type_name -> workflowcontract.v1.Annotation 15, // [15:15] is the sub-list for method output_type 15, // [15:15] is the sub-list for method input_type 15, // [15:15] is the sub-list for extension type_name @@ -1385,7 +1333,7 @@ func file_workflowcontract_v1_crafting_schema_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_workflowcontract_v1_crafting_schema_proto_rawDesc, - NumEnums: 3, + NumEnums: 2, NumMessages: 11, NumExtensions: 0, NumServices: 0, From 1401921854e825e85cab1f8eb35638da9c7305b7 Mon Sep 17 00:00:00 2001 From: "Jose I. Paris" Date: Wed, 17 Jul 2024 11:52:38 +0200 Subject: [PATCH 73/73] move literal to constant Signed-off-by: Jose I. Paris --- internal/attestation/renderer/renderer.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/attestation/renderer/renderer.go b/internal/attestation/renderer/renderer.go index dafb0d8a1..1a5413f36 100644 --- a/internal/attestation/renderer/renderer.go +++ b/internal/attestation/renderer/renderer.go @@ -58,6 +58,8 @@ type r interface { type Opt func(*AttestationRenderer) +const AttPolicyEvaluation = "CHAINLOOP.ATTESTATION" + func WithLogger(logger zerolog.Logger) Opt { return func(ar *AttestationRenderer) { ar.logger = logger @@ -174,7 +176,7 @@ func addPolicyResults(statement *intoto.Statement, policyResults []*v1.PolicyEva if p.PolicyEvaluations == nil { p.PolicyEvaluations = make(map[string][]*v1.PolicyEvaluation) } - p.PolicyEvaluations["ATTESTATION"] = policyResults + p.PolicyEvaluations[AttPolicyEvaluation] = policyResults // marshall back to JSON jsonPredicate, err = json.Marshal(p)