Skip to content

Commit

Permalink
Allowlist for secrets (dapr#2060)
Browse files Browse the repository at this point in the history
* Allowlist for secrets

* Add testing for gRPC

* fix linter error

* Refactor code. Add more tests.

* Refactor secrets configuration logic

* Refactor code. Add more validation, tests.

* Refactor code.

* Refactor code.

Co-authored-by: Mark Chmarny <mchmarny@users.noreply.github.com>
  • Loading branch information
mukundansundar and mchmarny authored Sep 21, 2020
1 parent 856d8cd commit 0de4003
Show file tree
Hide file tree
Showing 21 changed files with 820 additions and 63 deletions.
5 changes: 3 additions & 2 deletions .codecov.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
ignore:
- "**/zz_generated*.go" # Ignore generated files.
- "**/pkg/apis/**" # CRD related files including generated ones.
- "**/pkg/proto/**" # GRPC Protobuf client for dapr
- "**/pkg/testing/**" # testing mock
- "**/pkg/proto/**" # GRPC Protobuf client for dapr.
- "**/pkg/testing/**" # testing mock.
- "**/testdata/**" # Ignore test resources folder.
6 changes: 0 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,7 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nats-io/gnatsd v1.4.1 h1:RconcfDeWpKCD6QIIwiVFcvForlXpWeJP7i5/lDLy44=
github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
github.com/nats-io/go-nats v1.7.2 h1:cJujlwCYR8iMz5ofZSD/p2WLW8FabhkQ2lIEVbSvNSA=
github.com/nats-io/go-nats v1.7.2/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0=
github.com/nats-io/jwt v0.2.14/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
Expand Down Expand Up @@ -772,7 +770,6 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021 h1:0XM1XL/OFFJjXsYXlG30spTkV/E9+gmd5GD1w2HE8xM=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 h1:J9b7z+QKAmPf4YLrFg6oQUotqHQeUNWwkvo7jZp1GLU=
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
Expand Down Expand Up @@ -1097,7 +1094,6 @@ golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 h1:OjiUf46hAmXblsZdnoSXsEUSKU8r1UEzcL5RVZ4gO9Y=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down Expand Up @@ -1229,7 +1225,6 @@ gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI=
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
gopkg.in/jcmturner/gokrb5.v7 v7.2.3 h1:hHMV/yKPwMnJhPuPx7pH2Uw/3Qyf+thJYlisUc44010=
gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
gopkg.in/jcmturner/gokrb5.v7 v7.3.0 h1:0709Jtq/6QXEuWRfAm260XqlpcwL1vxtO1tUE2qK8Z4=
gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
Expand Down Expand Up @@ -1314,7 +1309,6 @@ modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
pack.ag/amqp v0.8.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
pack.ag/amqp v0.11.0 h1:ot/IA0enDkt4/c8xfbCO7AZzjM4bHys/UffnFmnHUnU=
pack.ag/amqp v0.11.0/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
pack.ag/amqp v0.11.2 h1:cuNDWLUTbKRtEZwhB0WQBXf9pGbm87pUBXQhvcFxBWg=
pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4=
Expand Down
18 changes: 18 additions & 0 deletions pkg/apis/configuration/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ type ConfigurationSpec struct {
TracingSpec TracingSpec `json:"tracing,omitempty"`
// +optional
MTLSSpec MTLSSpec `json:"mtls,omitempty"`
// +optional
Secrets SecretsSpec `json:"secrets,omitempty"`
}

// SecretsSpec is the spec for secrets configuration
type SecretsSpec struct {
Scopes []SecretsScope `json:"scopes"`
}

// SecretsScope defines the scope for secrets
type SecretsScope struct {
// +optional
DefaultAccess string `json:"defaultAccess,omitempty"`
StoreName string `json:"storeName"`
// +optional
AllowedSecrets []string `json:"allowedSecrets,omitempty"`
// +optional
DeniedSecrets []string `json:"deniedSecrets,omitempty"`
}

// PipelineSpec defines the middleware pipeline
Expand Down
48 changes: 48 additions & 0 deletions pkg/apis/configuration/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

83 changes: 83 additions & 0 deletions pkg/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@ import (
"encoding/json"
"io/ioutil"
"os"
"sort"
"strings"
"time"

operatorv1pb "github.com/dapr/dapr/pkg/proto/operator/v1"
grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
"github.com/pkg/errors"
yaml "gopkg.in/yaml.v2"
"k8s.io/apimachinery/pkg/util/sets"
)

const (
operatorCallTimeout = time.Second * 5
operatorMaxRetries = 100
AllowAccess = "allow"
DenyAccess = "deny"
)

type Configuration struct {
Expand All @@ -32,6 +37,19 @@ type ConfigurationSpec struct {
TracingSpec TracingSpec `json:"tracing,omitempty" yaml:"tracing,omitempty"`
MTLSSpec MTLSSpec `json:"mtls,omitempty"`
MetricSpec MetricSpec `json:"metric,omitempty" yaml:"metric,omitempty"`
Secrets SecretsSpec `json:"secrets,omitempty" yaml:"secrets,omitempty"`
}

type SecretsSpec struct {
Scopes []SecretsScope `json:"scopes"`
}

// SecretsScope defines the scope for secrets
type SecretsScope struct {
DefaultAccess string `json:"defaultAccess,omitempty" yaml:"defaultAccess,omitempty"`
StoreName string `json:"storeName" yaml:"storeName"`
AllowedSecrets []string `json:"allowedSecrets,omitempty" yaml:"allowedSecrets,omitempty"`
DeniedSecrets []string `json:"deniedSecrets,omitempty" yaml:"deniedSecrets,omitempty"`
}

type PipelineSpec struct {
Expand Down Expand Up @@ -100,6 +118,10 @@ func LoadStandaloneConfiguration(config string) (*Configuration, error) {
if err != nil {
return nil, err
}
err = sortAndValidateSecretsConfiguration(&conf)
if err != nil {
return nil, err
}

return &conf, nil
}
Expand All @@ -121,5 +143,66 @@ func LoadKubernetesConfiguration(config, namespace string, operatorClient operat
if err != nil {
return nil, err
}

err = sortAndValidateSecretsConfiguration(&conf)
if err != nil {
return nil, err
}

return &conf, nil
}

// Validate the secrets configuration and sort the allow and deny lists if present.
func sortAndValidateSecretsConfiguration(conf *Configuration) error {
scopes := conf.Spec.Secrets.Scopes
set := sets.NewString()
for _, scope := range scopes {
// validate scope
if set.Has(scope.StoreName) {
return errors.Errorf("%q storeName is repeated in secrets configuration", scope.StoreName)
}
if scope.DefaultAccess != "" &&
!strings.EqualFold(scope.DefaultAccess, AllowAccess) &&
!strings.EqualFold(scope.DefaultAccess, DenyAccess) {
return errors.Errorf("defaultAccess %q can be either allow or deny", scope.DefaultAccess)
}
set.Insert(scope.StoreName)

// modify scope
sort.Strings(scope.AllowedSecrets)
sort.Strings(scope.DeniedSecrets)
}

return nil
}

// Check if the secret is allowed to be accessed.
func (c SecretsScope) IsSecretAllowed(key string) bool {
// By default set allow access for the secret store.
var access string = AllowAccess
// Check and set deny access.
if strings.EqualFold(c.DefaultAccess, DenyAccess) {
access = DenyAccess
}

// If the allowedSecrets list is not empty then check if the access is specifically allowed for this key.
if len(c.AllowedSecrets) != 0 {
return containsKey(c.AllowedSecrets, key)
}

// Check key in deny list if deny list is present for the secret store.
// If the specific key is denied, then alone deny access.
if deny := containsKey(c.DeniedSecrets, key); deny {
return !deny
}

// Check if defined default access is allow.
return access == AllowAccess
}

// Runs Binary Search on a sorted list of strings to find a key.
func containsKey(s []string, key string) bool {
index := sort.SearchStrings(s, key)

return index < len(s) && s[index] == key
}
Loading

0 comments on commit 0de4003

Please sign in to comment.