Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] feat: add masking to list resources #125

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ const configFlag = "config"

// Config contains the application configuration.
type Config struct {
Log logger.LogConfig `mapstructure:"log"`
Syncer SyncerConf `mapstructure:"syncer"`
Service ServeConfig `mapstructure:"service"`
PGConnStr string `mapstructure:"pg_conn_str" default:"postgres://postgres@localhost:5432/entropy?sslmode=disable"`
Telemetry telemetry.Config `mapstructure:"telemetry"`
Log logger.LogConfig `mapstructure:"log"`
Syncer SyncerConf `mapstructure:"syncer"`
Service ServeConfig `mapstructure:"service"`
PGConnStr string `mapstructure:"pg_conn_str" default:"postgres://postgres@localhost:5432/entropy?sslmode=disable"`
Telemetry telemetry.Config `mapstructure:"telemetry"`
SecretMask string `mapstructure:"secret_mask"`
}

type SyncerConf struct {
Expand Down
2 changes: 1 addition & 1 deletion cli/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func StartServer(ctx context.Context, cfg Config, migrate, spawnWorker bool) err
)

store := setupStorage(cfg.PGConnStr, cfg.Syncer, cfg.Service)
moduleService := module.NewService(setupRegistry(), store)
moduleService := module.NewService(setupRegistry(), store, cfg.SecretMask)
resourceService := core.New(store, moduleService, time.Now, cfg.Syncer.SyncBackoffInterval, cfg.Syncer.MaxRetries)

if migrate {
Expand Down
2 changes: 1 addition & 1 deletion cli/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func cmdWorker() *cobra.Command {

func StartWorkers(ctx context.Context, cfg Config) error {
store := setupStorage(cfg.PGConnStr, cfg.Syncer, cfg.Service)
moduleService := module.NewService(setupRegistry(), store)
moduleService := module.NewService(setupRegistry(), store, cfg.SecretMask)
resourceService := core.New(store, moduleService, time.Now, cfg.Syncer.SyncBackoffInterval, cfg.Syncer.MaxRetries)

eg := &errgroup.Group{}
Expand Down
2 changes: 2 additions & 0 deletions core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ type Service struct {
moduleSvc ModuleService
syncBackoff time.Duration
maxSyncRetries int
secretMask string
}

type ModuleService interface {
PlanAction(ctx context.Context, res module.ExpandedResource, act module.ActionRequest) (*resource.Resource, error)
SyncState(ctx context.Context, res module.ExpandedResource) (*resource.State, error)
StreamLogs(ctx context.Context, res module.ExpandedResource, filter map[string]string) (<-chan module.LogChunk, error)
GetOutput(ctx context.Context, res module.ExpandedResource) (json.RawMessage, error)
MaskSecrets(ctx context.Context, res resource.Resource) (resource.Resource, error)
}

func New(repo resource.Store, moduleSvc ModuleService, clockFn func() time.Time, syncBackoffInterval time.Duration, maxRetries int) *Service {
Expand Down
1 change: 1 addition & 0 deletions core/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Descriptor struct {
Actions []ActionDesc `json:"actions"`
Dependencies map[string]string `json:"dependencies"`
DriverFactory func(conf json.RawMessage) (Driver, error) `json:"-"`
Secrets []string `json:"secrets"`
}

// Registry is responsible for installing and managing module-drivers as per
Expand Down
40 changes: 35 additions & 5 deletions core/module/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ import (

"github.com/goto/entropy/core/resource"
"github.com/goto/entropy/pkg/errors"
jsonpkg "github.com/goto/entropy/pkg/json"
)

type Service struct {
store Store
registry Registry
store Store
registry Registry
secretMask string
}

func NewService(registry Registry, store Store) *Service {
func NewService(registry Registry, store Store, secretMask string) *Service {
return &Service{
store: store,
registry: registry,
store: store,
registry: registry,
secretMask: secretMask,
}
}

Expand Down Expand Up @@ -177,3 +180,30 @@ func (mr *Service) initDriver(ctx context.Context, mod Module) (Driver, Descript
func generateURN(name, project string) string {
return fmt.Sprintf("orn:entropy:module:%s:%s", project, name)
}

func (mr *Service) MaskSecrets(ctx context.Context, res resource.Resource) (resource.Resource, error) {
mod, err := mr.discoverModule(ctx, res.Kind, res.Project)
if err != nil {
return resource.Resource{}, err
}

_, desc, err := mr.initDriver(ctx, *mod)
if err != nil {
return resource.Resource{}, err
}

for _, secret := range desc.Secrets {
maskedResSpecConfigs, err := jsonpkg.SetJSONField(res.Spec.Configs, secret, mr.secretMask)
if err != nil {
return resource.Resource{}, errors.ErrInternal.WithCausef(err.Error())
}
res.Spec.Configs = maskedResSpecConfigs

maskedResStateOutput, err := jsonpkg.SetJSONField(res.State.Output, secret, mr.secretMask)
if err != nil {
return resource.Resource{}, errors.ErrInternal.WithCausef(err.Error())
}
res.State.Output = maskedResStateOutput
}
return res, nil
}
5 changes: 5 additions & 0 deletions core/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ func (svc *Service) GetResource(ctx context.Context, urn string) (*resource.Reso
}
}

*res, err = svc.moduleSvc.MaskSecrets(ctx, *res)
if err != nil {
return nil, err
}

return res, nil
}

Expand Down
1 change: 1 addition & 0 deletions core/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
const (
defaultMaxRetries = 5
defaultSyncBackoff = 5 * time.Second
secretMask = "[MASKED]"
)

func TestService_GetResource(t *testing.T) {
Expand Down Expand Up @@ -58,7 +59,7 @@
Return(nil, nil).
Once()

return core.New(repo, mod, deadClock, defaultSyncBackoff, defaultMaxRetries)

Check failure on line 62 in core/read_test.go

View workflow job for this annotation

GitHub Actions / test

cannot use mod (variable of type *mocks.ModuleService) as core.ModuleService value in argument to core.New: *mocks.ModuleService does not implement core.ModuleService (missing method MaskSecrets)

Check failure on line 62 in core/read_test.go

View workflow job for this annotation

GitHub Actions / test

cannot use mod (variable of type *mocks.ModuleService) as core.ModuleService value in argument to core.New: *mocks.ModuleService does not implement core.ModuleService (missing method MaskSecrets)
},
urn: "foo:bar:baz",
want: &sampleResource,
Expand Down
7 changes: 7 additions & 0 deletions modules/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ package modules

import (
"context"
"fmt"
"os"
"reflect"
"strings"
"sync"

"github.com/goto/entropy/core/module"
Expand Down Expand Up @@ -53,6 +56,10 @@ func (mr *Registry) Register(desc module.Descriptor) error {
}
desc.Actions[i] = action
}

secretKey := fmt.Sprintf("%s_SECRET", strings.ToUpper(desc.Kind))
secrets := os.Getenv(secretKey)
desc.Secrets = strings.Split(secrets, ",")
mr.modules[desc.Kind] = desc
return nil
}
17 changes: 17 additions & 0 deletions pkg/json/json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package json

import (
"encoding/json"

"github.com/tidwall/sjson"
)

func SetJSONField(json json.RawMessage, key string, value interface{}) (json.RawMessage, error) {
sjson, err := sjson.SetBytes(json, key, value)

if err != nil {
return nil, err
}

return sjson, nil
}
Loading