Skip to content

Commit

Permalink
[RuleSet] add support for annotations and labels (#271)
Browse files Browse the repository at this point in the history
fix: add support to process annotations for the ruleset
fix: add support to process labels
test: add test for ruleset generation from bundle
test: add bundle with labels and annotations
test: update test to match expected values
fix: update ruleset FromBundle to use Labels and Annotations
test: update use to proto.Equal versus reflect.DeepEqual

Signed-off-by: Ben Stickel <[email protected]>
  • Loading branch information
fin09pcap authored Jun 27, 2023
1 parent 9c6967f commit 186f399
Show file tree
Hide file tree
Showing 6 changed files with 240 additions and 1 deletion.
10 changes: 10 additions & 0 deletions pkg/bundle/ruleset/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ func FromBundle(b *bundlev1.Bundle) (*bundlev1.RuleSet, error) {
Constraints: []string{},
}

// Process the labels for each secret
for label := range p.Labels {
r.Constraints = append(r.Constraints, fmt.Sprintf(`p.match_label(%q)`, label))
}

// Process the annotations for each secret
for annotation := range p.Annotations {
r.Constraints = append(r.Constraints, fmt.Sprintf(`p.match_annotation(%q)`, annotation))
}

// Process each secret
for _, s := range p.Secrets.Data {
r.Constraints = append(r.Constraints, fmt.Sprintf(`p.has_secret(%q)`, s.Key))
Expand Down
226 changes: 226 additions & 0 deletions pkg/bundle/ruleset/bundle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you 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 ruleset

import (
"testing"

bundlev1 "github.com/elastic/harp/api/gen/go/harp/bundle/v1"
"github.com/golang/protobuf/proto"
)

func TestFromBundle(t *testing.T) {
type args struct {
b *bundlev1.Bundle
}
tests := []struct {
name string
args args
want *bundlev1.RuleSet
wantErr bool
}{
{
name: "nil",
args: args{
b: nil,
},
want: nil,
wantErr: true,
},
{
name: "packages are nil",
args: args{
b: &bundlev1.Bundle{
Labels: map[string]string{
"test": "true",
},
Annotations: map[string]string{
"harp.elastic.co/v1/testing#bundlePurpose": "test",
},
Packages: nil,
},
},
want: nil,
wantErr: true,
},
{
name: "secrets are nil",
args: args{
b: &bundlev1.Bundle{
Labels: map[string]string{
"test": "true",
},
Annotations: map[string]string{
"harp.elastic.co/v1/testing#bundlePurpose": "test",
},
Packages: []*bundlev1.Package{
{
Labels: map[string]string{
"external": "true",
},
Annotations: map[string]string{
"infosec.elastic.co/v1/SecretPolicy#rotationMethod": "ci",
"infosec.elastic.co/v1/SecretPolicy#rotationPeriod": "90d",
"infosec.elastic.co/v1/SecretPolicy#serviceType": "authentication",
"infosec.elastic.co/v1/SecretPolicy#severity": "high",
"infra.elastic.co/v1/CI#jobName": "rotate-external-api-key",
"harp.elastic.co/v1/package#encryptionKeyAlias": "test",
},
Name: "app/production/testAccount/testService/v1.0.0/internalTestComponent/authentication/api_key",
Secrets: nil,
},
},
},
},
want: &bundlev1.RuleSet{
ApiVersion: "harp.elastic.co/v1",
Kind: "RuleSet",
Meta: &bundlev1.RuleSetMeta{
Description: "Generated from bundle content",
},
Spec: &bundlev1.RuleSetSpec{
Rules: []*bundlev1.Rule{},
},
},
wantErr: false,
},
{
name: "secret data is nil",
args: args{
b: &bundlev1.Bundle{
Labels: map[string]string{
"test": "true",
},
Annotations: map[string]string{
"harp.elastic.co/v1/testing#bundlePurpose": "test",
},
Packages: []*bundlev1.Package{
{
Labels: map[string]string{
"external": "true",
},
Annotations: map[string]string{
"infosec.elastic.co/v1/SecretPolicy#rotationMethod": "ci",
"infosec.elastic.co/v1/SecretPolicy#rotationPeriod": "90d",
"infosec.elastic.co/v1/SecretPolicy#serviceType": "authentication",
"infosec.elastic.co/v1/SecretPolicy#severity": "high",
"infra.elastic.co/v1/CI#jobName": "rotate-external-api-key",
"harp.elastic.co/v1/package#encryptionKeyAlias": "test",
},
Name: "app/production/testAccount/testService/v1.0.0/internalTestComponent/authentication/api_key",
Secrets: &bundlev1.SecretChain{
Data: nil,
},
},
},
},
},
want: &bundlev1.RuleSet{
ApiVersion: "harp.elastic.co/v1",
Kind: "RuleSet",
Meta: &bundlev1.RuleSetMeta{
Description: "Generated from bundle content",
},
Spec: &bundlev1.RuleSetSpec{
Rules: []*bundlev1.Rule{},
},
},
wantErr: false,
},
{
name: "package and secrets define with annotations and labels",
args: args{
b: &bundlev1.Bundle{
Labels: map[string]string{
"test": "true",
},
Annotations: map[string]string{
"harp.elastic.co/v1/testing#bundlePurpose": "test",
},
Packages: []*bundlev1.Package{
{
Labels: map[string]string{
"external": "true",
},
Annotations: map[string]string{
"harp.elastic.co/v1/package#encryptionKeyAlias": "test",
"infra.elastic.co/v1/CI#jobName": "rotate-external-api-key",
"infosec.elastic.co/v1/SecretPolicy#rotationMethod": "ci",
"infosec.elastic.co/v1/SecretPolicy#rotationPeriod": "90d",
"infosec.elastic.co/v1/SecretPolicy#serviceType": "authentication",
"infosec.elastic.co/v1/SecretPolicy#severity": "high",
},
Name: "app/production/testAccount/testService/v1.0.0/internalTestComponent/authentication/api_key",
Secrets: &bundlev1.SecretChain{
Labels: map[string]string{
"vendor": "true",
},
Data: []*bundlev1.KV{
{
Key: "API_KEY",
Type: "string",
Value: []byte("3YGVuHwUqYVkjk-c6lQgfVQwFHawPG36TgAm72sPZGE="),
},
},
},
},
},
},
},
want: &bundlev1.RuleSet{
ApiVersion: "harp.elastic.co/v1",
Kind: "RuleSet",
Meta: &bundlev1.RuleSetMeta{
Description: "Generated from bundle content",
Name: "D0QMaOw378tey2m_TvEuhBPkHOZQAgG88MUV4g6XiLk616urhu5an_hUf_N-k_-PF0TqslvGPFSpUUgZcxRhpg",
},
Spec: &bundlev1.RuleSetSpec{
Rules: []*bundlev1.Rule{
&bundlev1.Rule{
Name: "LINT-D0QMaO-1",
Path: "app/production/testAccount/testService/v1.0.0/internalTestComponent/authentication/api_key",
Constraints: []string{
"p.match_label(\"external\")",
"p.match_annotation(\"harp.elastic.co/v1/package#encryptionKeyAlias\")",
"p.match_annotation(\"infra.elastic.co/v1/CI#jobName\")",
"p.match_annotation(\"infosec.elastic.co/v1/SecretPolicy#rotationMethod\")",
"p.match_annotation(\"infosec.elastic.co/v1/SecretPolicy#rotationPeriod\")",
"p.match_annotation(\"infosec.elastic.co/v1/SecretPolicy#serviceType\")",
"p.match_annotation(\"infosec.elastic.co/v1/SecretPolicy#severity\")",
"p.has_secret(\"API_KEY\")",
},
},
},
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := FromBundle(tt.args.b)
if (err != nil) != tt.wantErr {
t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
}

if !proto.Equal(got, tt.want) {
t.Errorf("Ruleset not equal = %v, want %v", got, tt.want)
}
})
}
}
2 changes: 1 addition & 1 deletion pkg/bundle/ruleset/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func Evaluate(ctx context.Context, b *bundlev1.Bundle, spec *bundlev1.RuleSet) e

// Process each rule
for _, r := range spec.Spec.Rules {
// Complie path matcher
// Compile path matcher
pathMatcher, err := glob.Compile(r.Path)
if err != nil {
return fmt.Errorf("unable to compile path matcher: %w", err)
Expand Down
1 change: 1 addition & 0 deletions pkg/sdk/value/encryption/transformer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/elastic/harp/pkg/sdk/value"
"github.com/elastic/harp/pkg/sdk/value/encryption"

// Register encryption transformers
_ "github.com/elastic/harp/pkg/sdk/value/encryption/aead"
_ "github.com/elastic/harp/pkg/sdk/value/encryption/age"
Expand Down
1 change: 1 addition & 0 deletions pkg/tasks/bundle/decrypt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/elastic/harp/pkg/sdk/cmdutil"
"github.com/elastic/harp/pkg/sdk/value"
"github.com/elastic/harp/pkg/sdk/value/encryption"

// Import for tests
_ "github.com/elastic/harp/pkg/sdk/value/encryption/aead"
"github.com/elastic/harp/pkg/sdk/value/identity"
Expand Down
1 change: 1 addition & 0 deletions pkg/tasks/container/recover_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/elastic/harp/pkg/sdk/cmdutil"
"github.com/elastic/harp/pkg/sdk/value"
"github.com/elastic/harp/pkg/sdk/value/encryption"

// Imported for tests
_ "github.com/elastic/harp/pkg/sdk/value/encryption/jwe"
"github.com/elastic/harp/pkg/sdk/value/identity"
Expand Down

0 comments on commit 186f399

Please sign in to comment.