diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a14fb1e..de57c077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,28 @@ FEATURES: +* template/engine: + * `isodate` time formatter to RFC3389 date format. +* bundle/pipeline: + * Support custom input reader and output writer. [#105](https://github.com/elastic/harp/pull/105) +* bundle/selector: + * support `glob` for package path and secret key matcher. [#110](https://github.com/elastic/harp/pull/110) + * support `rego` policy for `bunde filter` command and `BundlePatch` selector. [#106](https://github.com/elastic/harp/pull/106) + * support `cel` expressions used in `BundleRuleSet` for package matchers in `bundle filter` command and `BundlePatch` selector. [#109](https://github.com/elastic/harp/pull/109) * sdk/value: * support `age` encryption as value transformer. [#102](https://github.com/elastic/harp/pull/102) * support deterministic authenticated encryption value transformers. [#103](https://github.com/elastic/harp/pull/103) * support additional data for AEAD/DAE transformers. [#104](https://github.com/elastic/harp/pull/104) * DAE transformers can be initialized using an optional salt to derive different keys from the transformer key. [#104](https://github.com/elastic/harp/pull/104) +DIST + +* go: Build with Golang 1.17.6. +* build/ci + * Add SLSA Level 1 - Provenance generation step for binaries. + * Add Snyk as code / dependencies scanner via SARIF. + * Add Trivy dependencies scanner via SARIF. + ## 0.2.5 ### 2022-01-28 diff --git a/api/gen/go/harp/bundle/v1/patch.pb.go b/api/gen/go/harp/bundle/v1/patch.pb.go index ccd61e7f..9f9551cc 100644 --- a/api/gen/go/harp/bundle/v1/patch.pb.go +++ b/api/gen/go/harp/bundle/v1/patch.pb.go @@ -450,6 +450,9 @@ type PatchSelectorMatchPath struct { // Regex path matching. // Value can be templatized. Regex string `protobuf:"bytes,2,opt,name=regex,proto3" json:"regex,omitempty"` + // Glob path matching. - https://github.com/gobwas/glob + // Value can be templatized. + Glob string `protobuf:"bytes,3,opt,name=glob,proto3" json:"glob,omitempty"` } func (x *PatchSelectorMatchPath) Reset() { @@ -498,6 +501,13 @@ func (x *PatchSelectorMatchPath) GetRegex() string { return "" } +func (x *PatchSelectorMatchPath) GetGlob() string { + if x != nil { + return x.Glob + } + return "" +} + // PatchSelectorMatchPath represents package path matching strategies. type PatchSelectorMatchSecret struct { state protoimpl.MessageState @@ -510,6 +520,9 @@ type PatchSelectorMatchSecret struct { // Regex secret matching. // Value can be templatized. Regex string `protobuf:"bytes,2,opt,name=regex,proto3" json:"regex,omitempty"` + // Glob path matching. - https://github.com/gobwas/glob + // Value can be templatized. + Glob string `protobuf:"bytes,3,opt,name=glob,proto3" json:"glob,omitempty"` } func (x *PatchSelectorMatchSecret) Reset() { @@ -558,6 +571,13 @@ func (x *PatchSelectorMatchSecret) GetRegex() string { return "" } +func (x *PatchSelectorMatchSecret) GetGlob() string { + if x != nil { + return x.Glob + } + return "" +} + // PatchPackagePath represents package path operations. type PatchPackagePath struct { state protoimpl.MessageState @@ -922,90 +942,92 @@ var file_harp_bundle_v1_patch_proto_rawDesc = []byte{ 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x0b, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, - 0x63, 0x65, 0x6c, 0x22, 0x46, 0x0a, 0x16, 0x50, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x6c, 0x65, + 0x63, 0x65, 0x6c, 0x22, 0x5a, 0x0a, 0x16, 0x50, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x22, 0x48, 0x0a, 0x18, 0x50, - 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x4d, 0x61, 0x74, 0x63, - 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x12, - 0x14, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x72, 0x65, 0x67, 0x65, 0x78, 0x22, 0x2e, 0x0a, 0x10, 0x50, 0x61, 0x74, 0x63, 0x68, 0x50, 0x61, - 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, - 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x9f, 0x02, 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x63, 0x68, 0x50, - 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x34, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x50, 0x61, 0x63, 0x6b, 0x61, - 0x67, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x40, 0x0a, 0x0b, - 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, - 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, - 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x2f, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, - 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, - 0x16, 0x0a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x22, 0xd3, 0x01, 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x63, - 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x40, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x67, + 0x6c, 0x6f, 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6c, 0x6f, 0x62, 0x22, + 0x5c, 0x0a, 0x18, 0x50, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x4d, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x72, 0x69, 0x63, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x72, + 0x69, 0x63, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x72, 0x65, 0x67, 0x65, 0x78, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6c, 0x6f, + 0x62, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6c, 0x6f, 0x62, 0x22, 0x2e, 0x0a, + 0x10, 0x50, 0x61, 0x74, 0x63, 0x68, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x61, 0x74, + 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x22, 0x9f, 0x02, + 0x0a, 0x0c, 0x50, 0x61, 0x74, 0x63, 0x68, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x34, + 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, - 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x0a, 0x06, 0x6c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, - 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, - 0x02, 0x6b, 0x76, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, + 0x74, 0x63, 0x68, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x61, 0x74, 0x68, 0x52, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x40, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6b, 0x76, 0x22, 0xcd, 0x03, - 0x0a, 0x0e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x39, 0x0a, 0x03, 0x61, 0x64, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, - 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, - 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, 0x61, 0x64, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d, - 0x6f, 0x76, 0x65, 0x12, 0x42, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, - 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, + 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x36, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x2f, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, - 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x70, - 0x6c, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x72, - 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, - 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, - 0x64, 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, 0x39, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 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, 0x3e, 0x0a, - 0x10, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 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, 0x42, 0x9e, 0x01, - 0x0a, 0x2a, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x65, 0x6c, 0x61, - 0x73, 0x74, 0x69, 0x63, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x73, 0x65, 0x63, 0x2e, 0x68, 0x61, - 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x50, 0x61, - 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x2f, 0x68, - 0x61, 0x72, 0x70, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x68, - 0x61, 0x72, 0x70, 0x2f, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x75, - 0x6e, 0x64, 0x6c, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x53, 0x42, 0x58, 0xaa, 0x02, 0x0e, 0x68, - 0x61, 0x72, 0x70, 0x2e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0e, - 0x68, 0x61, 0x72, 0x70, 0x5c, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x5c, 0x56, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x63, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x22, + 0xd3, 0x01, 0x0a, 0x0b, 0x50, 0x61, 0x74, 0x63, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, + 0x40, 0x0a, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x36, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x2e, 0x0a, 0x02, 0x6b, 0x76, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x02, 0x6b, 0x76, 0x22, 0xcd, 0x03, 0x0a, 0x0e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x03, 0x61, 0x64, 0x64, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x03, + 0x61, 0x64, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x12, 0x42, 0x0a, 0x06, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, + 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, + 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x51, 0x0a, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4b, 0x65, 0x79, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x4b, 0x65, + 0x79, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, 0x79, 0x73, + 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x4b, 0x65, + 0x79, 0x73, 0x1a, 0x36, 0x0a, 0x08, 0x41, 0x64, 0x64, 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, 0x39, 0x0a, 0x0b, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 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, 0x3e, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, + 0x4b, 0x65, 0x79, 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, 0x42, 0x9e, 0x01, 0x0a, 0x2a, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x65, 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x73, 0x65, 0x63, 0x2e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x62, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x2e, 0x76, 0x31, 0x42, 0x0a, 0x50, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, + 0x6c, 0x61, 0x73, 0x74, 0x69, 0x63, 0x2f, 0x68, 0x61, 0x72, 0x70, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x68, 0x61, 0x72, 0x70, 0x2f, 0x62, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x62, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x76, 0x31, 0xa2, 0x02, + 0x03, 0x53, 0x42, 0x58, 0xaa, 0x02, 0x0e, 0x68, 0x61, 0x72, 0x70, 0x2e, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0e, 0x68, 0x61, 0x72, 0x70, 0x5c, 0x42, 0x75, 0x6e, + 0x64, 0x6c, 0x65, 0x5c, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/proto/harp/bundle/v1/patch.proto b/api/proto/harp/bundle/v1/patch.proto index e7598e7b..7ff6ac17 100644 --- a/api/proto/harp/bundle/v1/patch.proto +++ b/api/proto/harp/bundle/v1/patch.proto @@ -95,6 +95,9 @@ message PatchSelectorMatchPath { // Regex path matching. // Value can be templatized. string regex = 2; + // Glob path matching. - https://github.com/gobwas/glob + // Value can be templatized. + string glob = 3; } // PatchSelectorMatchPath represents package path matching strategies. @@ -105,6 +108,9 @@ message PatchSelectorMatchSecret { // Regex secret matching. // Value can be templatized. string regex = 2; + // Glob path matching. - https://github.com/gobwas/glob + // Value can be templatized. + string glob = 3; } // PatchPackagePath represents package path operations. diff --git a/docs/onboarding/3-secret-bundle/4-patch.md b/docs/onboarding/3-secret-bundle/4-patch.md index 5369d26c..1c3de26f 100644 --- a/docs/onboarding/3-secret-bundle/4-patch.md +++ b/docs/onboarding/3-secret-bundle/4-patch.md @@ -21,6 +21,7 @@ bundle source without altering the source bundle. - [Match by regex path](#match-by-regex-path) - [Match by JMES filter](#match-by-jmes-filter) - [Match by Rego policy](#match-by-rego-policy) + - [Match by CEL expression](#match-by-cel-expression) - [Match by secret key](#match-by-secret-key) - [PatchSelectorMatchPath](#patchselectormatchpath) - [PatchPackage](#patchpackage) @@ -187,6 +188,8 @@ message PatchSelector { string rego = 3; // Match a package by secret. PatchSelectorMatchSecret matchSecret = 4; + // Match a package using CEL expressions. + repeated string cel = 5; } ``` @@ -278,6 +281,43 @@ spec: ``` +#### Match by CEL expression + +```yaml +selector: + cel: + - "p.is_cso_compliant()" +``` + +Sample use case + +```yaml +apiVersion: harp.elastic.co/v1 +kind: BundlePatch +meta: + name: "cso-compliance-flagger" + owner: security@elastic.co + description: "Flag non CSO complaint packages" +spec: + rules: + - selector: + cel: + # No CSO compliant path as package name + - "!p.is_cso_compliant()" + package: + labels: + add: + cso-compliant: false + - selector: + cel: + # CSO compliant path as package name + - "p.is_cso_compliant()" + package: + labels: + add: + cso-compliant: true +``` + #### Match by secret key Strict matcher @@ -323,6 +363,7 @@ spec: * `strict` is used to filter package path when strictly equal to the given value * `regex` is used to match the package path with the given regular expression +* `glob` is used to match the package path with the given glob expression ```cpp // PatchSelectorMatchPath represents package path matching strategies. @@ -333,6 +374,9 @@ message PatchSelectorMatchPath { // Regex path matching. // Value can be templatized. string regex = 2; + // Glob path matching. - https://github.com/gobwas/glob + // Value can be templatized. + string glob = 3; } ``` diff --git a/docs/onboarding/3-secret-bundle/5-ruleset.md b/docs/onboarding/3-secret-bundle/5-ruleset.md index 2c4cb125..41fb3774 100644 --- a/docs/onboarding/3-secret-bundle/5-ruleset.md +++ b/docs/onboarding/3-secret-bundle/5-ruleset.md @@ -1,18 +1,33 @@ - +#### Package matchers + +* `p.match_path(globstring) bool` - Returns true if the package name match the given Glob pattern. +* `p.match_label(globstring) bool` - Returns true if one of the package labels match the given Glob pattern. +* `p.match_annotation(globstring) bool` - Returns true if one of the package annotations match the given Glob pattern. +* `p.match_secret(globstring) bool` - Returns true if the package has a secret with given pattern. +* `p.has_secret(string) bool` - Returns true if the package has a secret with given key. +* `p.has_all_secrets(...string) bool` - Returns true if the package has all secrets with given keys. +* `p.is_cso_compliant() bool` - Returns true is the package name is CSO compliant. + +#### Secret context + +* `p.secret(string) Secret` - Returns the secret context matching the secret key of the package. +* `p.secret(string).is_required()` - Flag the given secret key as required. +* `p.secret(string).is_base64()` - Flag the given secret value has a valid base64 encoded string. +* `p.secret(string).is_url()` - Flag the given secret value as a valid URL. +* `p.secret(string).is_uuid()` - Flag the given secret value as a valid UUID. +* `p.secret(string).is_email()` - Flag the given secret value as a valid email. +* `p.secret(string).is_json()` - Flag the given secret value as a valid JSON. --- diff --git a/pkg/bundle/patch/executor.go b/pkg/bundle/patch/executor.go index b96c78e6..076b6969 100644 --- a/pkg/bundle/patch/executor.go +++ b/pkg/bundle/patch/executor.go @@ -20,6 +20,7 @@ package patch import ( "context" "encoding/json" + "errors" "fmt" "regexp" @@ -80,7 +81,7 @@ func executeRule(r *bundlev1.PatchRule, p *bundlev1.Package, values map[string]i return packageUnchanged, nil } -//nolint:gocyclo // to refactor +//nolint:gocyclo,funlen // to refactor func compileSelector(s *bundlev1.PatchSelector, values map[string]interface{}) (selector.Specification, error) { // Check parameters if s == nil { @@ -89,7 +90,8 @@ func compileSelector(s *bundlev1.PatchSelector, values map[string]interface{}) ( // Has matchPath selector if s.MatchPath != nil { - if s.MatchPath.Strict != "" { + switch { + case s.MatchPath.Strict != "": // Evaluation with template engine first value, err := engine.Render(s.MatchPath.Strict, map[string]interface{}{ "Values": values, @@ -100,24 +102,30 @@ func compileSelector(s *bundlev1.PatchSelector, values map[string]interface{}) ( // Return specification return selector.MatchPathStrict(value), nil - } - if s.MatchPath.Regex != "" { + case s.MatchPath.Glob != "": // Evaluation with template engine first - value, err := engine.Render(s.MatchPath.Regex, map[string]interface{}{ + value, err := engine.Render(s.MatchPath.Glob, map[string]interface{}{ "Values": values, }) if err != nil { return nil, fmt.Errorf("unable to evaluate template before matchPath build: %w", err) } - // Compile regexp - re, err := regexp.Compile(value) + // Return specification + return selector.MatchPathGlob(value) + case s.MatchPath.Regex != "": + // Evaluation with template engine first + value, err := engine.Render(s.MatchPath.Regex, map[string]interface{}{ + "Values": values, + }) if err != nil { - return nil, fmt.Errorf("unable to compile macthPath regexp `%s`: %w", s.MatchPath.Regex, err) + return nil, fmt.Errorf("unable to evaluate template before matchPath build: %w", err) } // Return specification - return selector.MatchPathRegex(re), nil + return selector.MatchPathRegex(value) + default: + return nil, errors.New("no strict, glob or regexp defined for path matcher") } } @@ -135,7 +143,8 @@ func compileSelector(s *bundlev1.PatchSelector, values map[string]interface{}) ( // Has matchSecret selector if s.MatchSecret != nil { - if s.MatchSecret.Strict != "" { + switch { + case s.MatchSecret.Strict != "": // Evaluation with template engine first value, err := engine.Render(s.MatchSecret.Strict, map[string]interface{}{ "Values": values, @@ -146,8 +155,18 @@ func compileSelector(s *bundlev1.PatchSelector, values map[string]interface{}) ( // Return specification return selector.MatchSecretStrict(value), nil - } - if s.MatchSecret.Regex != "" { + case s.MatchSecret.Glob != "": + // Evaluation with template engine first + value, err := engine.Render(s.MatchSecret.Glob, map[string]interface{}{ + "Values": values, + }) + if err != nil { + return nil, fmt.Errorf("unable to evaluate template before matchSecret build: %w", err) + } + + // Return specification + return selector.MatchSecretGlob(value), nil + case s.MatchSecret.Regex != "": // Evaluation with template engine first value, err := engine.Render(s.MatchSecret.Regex, map[string]interface{}{ "Values": values, @@ -164,6 +183,8 @@ func compileSelector(s *bundlev1.PatchSelector, values map[string]interface{}) ( // Return specification return selector.MatchSecretRegex(re), nil + default: + return nil, errors.New("no strict, glob or regexp defined for secret matcher") } } diff --git a/pkg/bundle/ruleset/linter/engine/cel/ext/package.go b/pkg/bundle/ruleset/linter/engine/cel/ext/package.go index 2025b97c..1dced47a 100644 --- a/pkg/bundle/ruleset/linter/engine/cel/ext/package.go +++ b/pkg/bundle/ruleset/linter/engine/cel/ext/package.go @@ -46,12 +46,30 @@ func (packageLib) CompileOptions() []cel.EnvOption { return []cel.EnvOption{ cel.Declarations( decls.NewVar("p", harpPackageObjectType), + decls.NewFunction("match_label", + decls.NewInstanceOverload("package_match_label_string", + []*exprpb.Type{harpPackageObjectType, decls.String}, + decls.Bool, + ), + ), + decls.NewFunction("match_annotation", + decls.NewInstanceOverload("package_match_annotation_string", + []*exprpb.Type{harpPackageObjectType, decls.String}, + decls.Bool, + ), + ), decls.NewFunction("match_path", decls.NewInstanceOverload("package_match_path_string", []*exprpb.Type{harpPackageObjectType, decls.String}, decls.Bool, ), ), + decls.NewFunction("match_secret", + decls.NewInstanceOverload("package_match_secret_string", + []*exprpb.Type{harpPackageObjectType, decls.String}, + decls.Bool, + ), + ), decls.NewFunction("has_secret", decls.NewInstanceOverload("package_has_secret_string", []*exprpb.Type{harpPackageObjectType, decls.String}, @@ -91,10 +109,22 @@ func (packageLib) ProgramOptions() []cel.ProgramOption { return []cel.ProgramOption{ cel.Functions( + &functions.Overload{ + Operator: "package_match_label_string", + Binary: celPackageMatchLabel, + }, + &functions.Overload{ + Operator: "package_match_annotation_string", + Binary: celPackageMatchAnnotation, + }, &functions.Overload{ Operator: "package_match_path_string", Binary: celPackageMatchPath, }, + &functions.Overload{ + Operator: "package_match_secret_string", + Binary: celPackageMatchSecret, + }, &functions.Overload{ Operator: "package_has_secret_string", Binary: celPackageHasSecret, @@ -117,6 +147,60 @@ func (packageLib) ProgramOptions() []cel.ProgramOption { // ----------------------------------------------------------------------------- +func celPackageMatchLabel(lhs, rhs ref.Val) ref.Val { + x, _ := lhs.ConvertToNative(reflect.TypeOf(&bundlev1.Package{})) + p, ok := x.(*bundlev1.Package) + if !ok { + return types.Bool(false) + } + + patternTyped, ok := rhs.(types.String) + if !ok { + return types.Bool(false) + } + + pattern, ok := patternTyped.Value().(string) + if !ok { + return types.Bool(false) + } + + m := glob.MustCompile(pattern) + for k := range p.Labels { + if m.Match(k) { + return types.Bool(true) + } + } + + return types.Bool(false) +} + +func celPackageMatchAnnotation(lhs, rhs ref.Val) ref.Val { + x, _ := lhs.ConvertToNative(reflect.TypeOf(&bundlev1.Package{})) + p, ok := x.(*bundlev1.Package) + if !ok { + return types.Bool(false) + } + + patternTyped, ok := rhs.(types.String) + if !ok { + return types.Bool(false) + } + + pattern, ok := patternTyped.Value().(string) + if !ok { + return types.Bool(false) + } + + m := glob.MustCompile(pattern) + for k := range p.Annotations { + if m.Match(k) { + return types.Bool(true) + } + } + + return types.Bool(false) +} + func celPackageMatchPath(lhs, rhs ref.Val) ref.Val { x, _ := lhs.ConvertToNative(reflect.TypeOf(&bundlev1.Package{})) p, ok := x.(*bundlev1.Package) @@ -137,6 +221,40 @@ func celPackageMatchPath(lhs, rhs ref.Val) ref.Val { return types.Bool(glob.MustCompile(path).Match(p.Name)) } +func celPackageMatchSecret(lhs, rhs ref.Val) ref.Val { + x, _ := lhs.ConvertToNative(reflect.TypeOf(&bundlev1.Package{})) + p, ok := x.(*bundlev1.Package) + if !ok { + return types.Bool(false) + } + + secretTyped, ok := rhs.(types.String) + if !ok { + return types.Bool(false) + } + + secretName, ok := secretTyped.Value().(string) + if !ok { + return types.Bool(false) + } + + // No secret data + if p.Secrets == nil || p.Secrets.Data == nil || len(p.Secrets.Data) == 0 { + return types.Bool(false) + } + + m := glob.MustCompile(secretName) + + // Look for secret name + for _, s := range p.Secrets.Data { + if m.Match(s.Key) { + return types.Bool(true) + } + } + + return types.Bool(false) +} + func celPackageHasSecret(lhs, rhs ref.Val) ref.Val { x, _ := lhs.ConvertToNative(reflect.TypeOf(&bundlev1.Package{})) p, ok := x.(*bundlev1.Package) diff --git a/pkg/bundle/selector/match_path.go b/pkg/bundle/selector/match_path.go index d446cace..ed3f3bd9 100644 --- a/pkg/bundle/selector/match_path.go +++ b/pkg/bundle/selector/match_path.go @@ -18,9 +18,12 @@ package selector import ( + "fmt" "regexp" "strings" + "github.com/gobwas/glob" + bundlev1 "github.com/elastic/harp/api/gen/go/harp/bundle/v1" ) @@ -32,30 +35,51 @@ func MatchPathStrict(value string) Specification { } // MatchPathRegex returns a path matcher specification with regexp. -func MatchPathRegex(regex *regexp.Regexp) Specification { +func MatchPathRegex(pattern string) (Specification, error) { + // Compile and check filter + m, err := regexp.Compile(pattern) + if err != nil { + return nil, fmt.Errorf("unable to compile regex filter: %w", err) + } + + // No error return &matchPath{ - regex: regex, + regex: m, + }, nil +} + +// MatchPathGlob returns a path matcher specification with glob query. +func MatchPathGlob(pattern string) (Specification, error) { + // Compile and check filter + m, err := glob.Compile(pattern) + if err != nil { + return nil, fmt.Errorf("unable to compile glob filter: %w", err) } + + // No error + return &matchPath{ + g: m, + }, nil } // MatchPath checks if secret path match the given string type matchPath struct { strict string regex *regexp.Regexp + g glob.Glob } // IsSatisfiedBy returns specification satisfaction status func (s *matchPath) IsSatisfiedBy(object interface{}) bool { // If object is a package if p, ok := object.(*bundlev1.Package); ok { - // Strict mode - if s.strict != "" { + switch { + case s.strict != "": return strings.Compare(p.Name, s.strict) == 0 - } - - // Regex mode - if s.regex != nil { + case s.regex != nil: return s.regex.MatchString(p.Name) + case s.g != nil: + return s.g.Match(p.Name) } } diff --git a/pkg/bundle/selector/match_path_test.go b/pkg/bundle/selector/match_path_test.go index e73c1d33..75026e36 100644 --- a/pkg/bundle/selector/match_path_test.go +++ b/pkg/bundle/selector/match_path_test.go @@ -21,6 +21,7 @@ import ( "regexp" "testing" + "github.com/gobwas/glob" fuzz "github.com/google/gofuzz" bundlev1 "github.com/elastic/harp/api/gen/go/harp/bundle/v1" @@ -30,6 +31,7 @@ func Test_matchPath_IsSatisfiedBy(t *testing.T) { type fields struct { strict string regex *regexp.Regexp + g glob.Glob } type args struct { object interface{} @@ -120,12 +122,37 @@ func Test_matchPath_IsSatisfiedBy(t *testing.T) { }, want: true, }, + { + name: "supported type: glob mode not match", + fields: fields{ + g: glob.MustCompile("test"), + }, + args: args{ + object: &bundlev1.Package{ + Name: "foo", + }, + }, + want: false, + }, + { + name: "supported type: glob mode with match", + fields: fields{ + g: glob.MustCompile("foo"), + }, + args: args{ + object: &bundlev1.Package{ + Name: "foo", + }, + }, + want: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := &matchPath{ strict: tt.fields.strict, regex: tt.fields.regex, + g: tt.fields.g, } if got := s.IsSatisfiedBy(tt.args.object); got != tt.want { t.Errorf("matchPath.IsSatisfiedBy() = %v, want %v", got, tt.want) diff --git a/pkg/bundle/selector/match_secret.go b/pkg/bundle/selector/match_secret.go index 1abcc6b7..359b6877 100644 --- a/pkg/bundle/selector/match_secret.go +++ b/pkg/bundle/selector/match_secret.go @@ -22,26 +22,35 @@ import ( "strings" bundlev1 "github.com/elastic/harp/api/gen/go/harp/bundle/v1" + "github.com/gobwas/glob" ) -// MatchSecretStrict returns a secret matcher specification with strict profile. +// MatchSecretStrict returns a secret key matcher specification with strict profile. func MatchSecretStrict(value string) Specification { return &matchSecret{ strict: value, } } -// MatchSecretRegex returns a secret matcher specification with regexp. +// MatchSecretRegex returns a secret key matcher specification with regexp. func MatchSecretRegex(regex *regexp.Regexp) Specification { return &matchSecret{ regex: regex, } } +// MatchSecretGlob returns a secret key matcher specification with glob query. +func MatchSecretGlob(pattern string) Specification { + return &matchPath{ + g: glob.MustCompile(pattern), + } +} + // matchSecret checks if secret key match the given string type matchSecret struct { strict string regex *regexp.Regexp + g glob.Glob } // IsSatisfiedBy returns specification satisfaction status @@ -56,14 +65,13 @@ func (s *matchSecret) IsSatisfiedBy(object interface{}) bool { } for _, kv := range p.Secrets.Data { - // Strict mode - if s.strict != "" { - match = strings.Compare(kv.Key, s.strict) == 0 - } - - // Regex mode - if s.regex != nil { - match = s.regex.MatchString(kv.Key) + switch { + case s.strict != "": + return strings.Compare(kv.Key, s.strict) == 0 + case s.regex != nil: + return s.regex.MatchString(kv.Key) + case s.g != nil: + return s.g.Match(kv.Key) } } } diff --git a/pkg/bundle/selector/match_secret_test.go b/pkg/bundle/selector/match_secret_test.go index 79ad07ea..de47e46c 100644 --- a/pkg/bundle/selector/match_secret_test.go +++ b/pkg/bundle/selector/match_secret_test.go @@ -21,6 +21,7 @@ import ( "regexp" "testing" + "github.com/gobwas/glob" fuzz "github.com/google/gofuzz" bundlev1 "github.com/elastic/harp/api/gen/go/harp/bundle/v1" @@ -30,6 +31,7 @@ func Test_matchSecret_IsSatisfiedBy(t *testing.T) { type fields struct { strict string regex *regexp.Regexp + g glob.Glob } type args struct { object interface{} @@ -141,12 +143,51 @@ func Test_matchSecret_IsSatisfiedBy(t *testing.T) { }, want: true, }, + { + name: "supported type: glob mode not match", + fields: fields{ + g: glob.MustCompile("bar*"), + }, + args: args{ + object: &bundlev1.Package{ + Name: "foo", + Secrets: &bundlev1.SecretChain{ + Data: []*bundlev1.KV{ + { + Key: "foo", + }, + }, + }, + }, + }, + want: false, + }, + { + name: "supported type: glob mode with match", + fields: fields{ + g: glob.MustCompile("foo*"), + }, + args: args{ + object: &bundlev1.Package{ + Name: "foo", + Secrets: &bundlev1.SecretChain{ + Data: []*bundlev1.KV{ + { + Key: "foo", + }, + }, + }, + }, + }, + want: true, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { s := &matchSecret{ strict: tt.fields.strict, regex: tt.fields.regex, + g: tt.fields.g, } if got := s.IsSatisfiedBy(tt.args.object); got != tt.want { t.Errorf("matchSecret.IsSatisfiedBy() = %v, want %v", got, tt.want)