From a93c24c3ef04f73657d9a90c49c7b6e75f593f96 Mon Sep 17 00:00:00 2001 From: Ewa Wojtach Date: Wed, 6 Apr 2022 14:37:41 +0200 Subject: [PATCH 1/5] policy check command --- internal/app/app.go | 50 +++++++++++++++++++++++++++++++++------------ internal/app/cli.go | 25 +++++++++++++++++++++++ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index a8a3634..b21a851 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -29,6 +29,7 @@ type PolicyAutomation interface { Close() error ClusterReview() error Version() error + PolicyCheck() error } type PolicyAutomationApp struct { @@ -81,16 +82,11 @@ func (p *PolicyAutomationApp) Close() error { func (p *PolicyAutomationApp) ClusterReview() error { files, err := p.loadPolicyFiles() - if err != nil { - return err - } pa := policy.NewPolicyAgent(p.ctx) - p.out.ColorPrintf("[light_gray][bold]Parsing REGO policies...\n") - log.Info("Parsing rego policies") - if err := pa.WithFiles(files); err != nil { - p.out.ErrorPrint("could not parse policy files", err) - log.Errorf("could not parse policy files: %s", err) - return err + + validationError := p.validatePolicyFiles(files, err) + if validationError != nil { + return validationError } evalResults := make([]*policy.PolicyEvaluationResult, 0) @@ -131,14 +127,27 @@ func (p *PolicyAutomationApp) Version() error { return nil } +func (p *PolicyAutomationApp) PolicyCheck() error { + files, err := p.loadPolicyFiles() + errorResult := p.validatePolicyFiles(files, err) + + if errorResult != nil { + p.out.ErrorPrint("validation failed: ", errorResult) + log.Errorf("validation failed: %s", errorResult) + return err + } else { + p.out.ColorPrintf("[bold][green] All policies validated correctly \n") + } + return nil +} + func (p *PolicyAutomationApp) loadPolicyFiles() ([]*policy.PolicyFile, error) { policyFiles := make([]*policy.PolicyFile, 0) for _, policyConfig := range p.config.Policies { var policySrc policy.PolicySource if policyConfig.LocalDirectory != "" { policySrc = policy.NewLocalPolicySource(policyConfig.LocalDirectory) - } - if policyConfig.GitRepository != "" { + } else if policyConfig.GitRepository != "" { policySrc = policy.NewGitPolicySource(policyConfig.GitRepository, policyConfig.GitBranch, policyConfig.GitDirectory) @@ -156,6 +165,22 @@ func (p *PolicyAutomationApp) loadPolicyFiles() ([]*policy.PolicyFile, error) { return policyFiles, nil } +func (p *PolicyAutomationApp) validatePolicyFiles(files []*policy.PolicyFile, err error) error { + if err != nil { + return err + } + pa := policy.NewPolicyAgent(p.ctx) + + p.out.ColorPrintf("[light_gray][bold]Parsing REGO policies...\n") + log.Info("Parsing rego policies") + if err := pa.WithFiles(files); err != nil { + p.out.ErrorPrint("could not parse policy files", err) + log.Errorf("could not parse policy files: %s", err) + return err + } + return nil +} + func newConfigFromFile(path string) (*ConfigNg, error) { return ReadConfig(path, os.ReadFile) } @@ -173,8 +198,7 @@ func newConfigFromCli(cliConfig *CliConfig) *ConfigNg { } if cliConfig.LocalDirectory != "" { config.Policies = append(config.Policies, ConfigPolicy{LocalDirectory: cliConfig.LocalDirectory}) - } - if cliConfig.GitRepository != "" { + } else if cliConfig.GitRepository != "" { config.Policies = append(config.Policies, ConfigPolicy{ GitRepository: cliConfig.GitRepository, GitBranch: cliConfig.GitBranch, diff --git a/internal/app/cli.go b/internal/app/cli.go index 20b7172..41fcf65 100644 --- a/internal/app/cli.go +++ b/internal/app/cli.go @@ -36,6 +36,7 @@ func NewPolicyAutomationCli(p PolicyAutomation) *cli.App { Commands: []*cli.Command{ CreateClusterCommand(p), CreateVersionCommand(p), + CreatePolicyCheckCommand(p), }, } return app @@ -111,6 +112,30 @@ func CreateVersionCommand(p PolicyAutomation) *cli.Command { } } +func CreatePolicyCheckCommand(p PolicyAutomation) *cli.Command { + config := &CliConfig{} + return &cli.Command{ + Name: "policy", + Usage: "Manages policy files", + Subcommands: []*cli.Command{ + { + Name: "check", + Usage: "Validates policy files from defined source", + Flags: (getPolicySourceFlags(config)), + Action: func(c *cli.Context) error { + defer p.Close() + if err := p.LoadCliConfig(config); err != nil { + cli.ShowSubcommandHelp(c) + return err + } + p.PolicyCheck() + return nil + }, + }, + }, + } +} + func getPolicySourceFlags(config *CliConfig) []cli.Flag { return []cli.Flag{ &cli.StringFlag{ From 37682e5d23dc8bb26687a7ec469d953d951d9a28 Mon Sep 17 00:00:00 2001 From: Ewa Wojtach Date: Wed, 6 Apr 2022 15:14:25 +0200 Subject: [PATCH 2/5] load and validate --- internal/app/app.go | 36 ++++++++++++------------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index b21a851..de264ea 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -81,14 +81,11 @@ func (p *PolicyAutomationApp) Close() error { } func (p *PolicyAutomationApp) ClusterReview() error { - files, err := p.loadPolicyFiles() - pa := policy.NewPolicyAgent(p.ctx) - - validationError := p.validatePolicyFiles(files, err) - if validationError != nil { - return validationError + _, err := p.loadAndValidatePolicyFiles() + if err != nil { + return err } - + pa := policy.NewPolicyAgent(p.ctx) evalResults := make([]*policy.PolicyEvaluationResult, 0) for _, cluster := range p.config.Clusters { clusterName, err := getClusterName(cluster) @@ -128,12 +125,10 @@ func (p *PolicyAutomationApp) Version() error { } func (p *PolicyAutomationApp) PolicyCheck() error { - files, err := p.loadPolicyFiles() - errorResult := p.validatePolicyFiles(files, err) - - if errorResult != nil { - p.out.ErrorPrint("validation failed: ", errorResult) - log.Errorf("validation failed: %s", errorResult) + _, err := p.loadAndValidatePolicyFiles() + if err != nil { + p.out.ErrorPrint("validation failed: ", err) + log.Errorf("validation failed: %s", err) return err } else { p.out.ColorPrintf("[bold][green] All policies validated correctly \n") @@ -141,7 +136,7 @@ func (p *PolicyAutomationApp) PolicyCheck() error { return nil } -func (p *PolicyAutomationApp) loadPolicyFiles() ([]*policy.PolicyFile, error) { +func (p *PolicyAutomationApp) loadAndValidatePolicyFiles() ([]*policy.PolicyFile, error) { policyFiles := make([]*policy.PolicyFile, 0) for _, policyConfig := range p.config.Policies { var policySrc policy.PolicySource @@ -162,23 +157,16 @@ func (p *PolicyAutomationApp) loadPolicyFiles() ([]*policy.PolicyFile, error) { } policyFiles = append(policyFiles, files...) } - return policyFiles, nil -} - -func (p *PolicyAutomationApp) validatePolicyFiles(files []*policy.PolicyFile, err error) error { - if err != nil { - return err - } pa := policy.NewPolicyAgent(p.ctx) p.out.ColorPrintf("[light_gray][bold]Parsing REGO policies...\n") log.Info("Parsing rego policies") - if err := pa.WithFiles(files); err != nil { + if err := pa.WithFiles(policyFiles); err != nil { p.out.ErrorPrint("could not parse policy files", err) log.Errorf("could not parse policy files: %s", err) - return err + return nil, err } - return nil + return policyFiles, nil } func newConfigFromFile(path string) (*ConfigNg, error) { From 4e0058630d7318186557f7c6a28ac6ea12dc8f2f Mon Sep 17 00:00:00 2001 From: Ewa Wojtach Date: Wed, 6 Apr 2022 15:25:58 +0200 Subject: [PATCH 3/5] load and compile policy files --- internal/app/app.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index de264ea..36e4b69 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -81,11 +81,10 @@ func (p *PolicyAutomationApp) Close() error { } func (p *PolicyAutomationApp) ClusterReview() error { - _, err := p.loadAndValidatePolicyFiles() + pa, err := p.loadAndCompilePolicyFiles() if err != nil { return err } - pa := policy.NewPolicyAgent(p.ctx) evalResults := make([]*policy.PolicyEvaluationResult, 0) for _, cluster := range p.config.Clusters { clusterName, err := getClusterName(cluster) @@ -125,7 +124,7 @@ func (p *PolicyAutomationApp) Version() error { } func (p *PolicyAutomationApp) PolicyCheck() error { - _, err := p.loadAndValidatePolicyFiles() + _, err := p.loadAndCompilePolicyFiles() if err != nil { p.out.ErrorPrint("validation failed: ", err) log.Errorf("validation failed: %s", err) @@ -136,7 +135,7 @@ func (p *PolicyAutomationApp) PolicyCheck() error { return nil } -func (p *PolicyAutomationApp) loadAndValidatePolicyFiles() ([]*policy.PolicyFile, error) { +func (p *PolicyAutomationApp) loadAndCompilePolicyFiles() (*policy.PolicyAgent, error) { policyFiles := make([]*policy.PolicyFile, 0) for _, policyConfig := range p.config.Policies { var policySrc policy.PolicySource @@ -166,7 +165,7 @@ func (p *PolicyAutomationApp) loadAndValidatePolicyFiles() ([]*policy.PolicyFile log.Errorf("could not parse policy files: %s", err) return nil, err } - return policyFiles, nil + return pa, nil } func newConfigFromFile(path string) (*ConfigNg, error) { From 2f81d32b1a47c455002c0f03b1fd9d3a8b6bcc91 Mon Sep 17 00:00:00 2001 From: Ewa Wojtach Date: Wed, 6 Apr 2022 16:15:05 +0200 Subject: [PATCH 4/5] policy check in separate flow, default repo fix reverted --- internal/app/app.go | 46 ++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index 36e4b69..220e018 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -81,10 +81,19 @@ func (p *PolicyAutomationApp) Close() error { } func (p *PolicyAutomationApp) ClusterReview() error { - pa, err := p.loadAndCompilePolicyFiles() + files, err := p.loadPolicyFiles() if err != nil { return err } + pa := policy.NewPolicyAgent(p.ctx) + p.out.ColorPrintf("[light_gray][bold]Parsing REGO policies...\n") + log.Info("Parsing rego policies") + if err := pa.WithFiles(files); err != nil { + p.out.ErrorPrint("could not parse policy files", err) + log.Errorf("could not parse policy files: %s", err) + return err + } + evalResults := make([]*policy.PolicyEvaluationResult, 0) for _, cluster := range p.config.Clusters { clusterName, err := getClusterName(cluster) @@ -124,24 +133,31 @@ func (p *PolicyAutomationApp) Version() error { } func (p *PolicyAutomationApp) PolicyCheck() error { - _, err := p.loadAndCompilePolicyFiles() + files, err := p.loadPolicyFiles() if err != nil { - p.out.ErrorPrint("validation failed: ", err) - log.Errorf("validation failed: %s", err) + p.out.ErrorPrint("loading policy files failed: ", err) + log.Errorf("loading policy files failed: %s", err) return err - } else { - p.out.ColorPrintf("[bold][green] All policies validated correctly \n") } + pa := policy.NewPolicyAgent(p.ctx) + if err := pa.WithFiles(files); err != nil { + p.out.ErrorPrint("could not parse policy files", err) + log.Errorf("could not parse policy files: %s", err) + return err + } + p.out.ColorPrintf("[bold][green] All policies validated correctly \n") + log.Info("All policies validated correctly") return nil } -func (p *PolicyAutomationApp) loadAndCompilePolicyFiles() (*policy.PolicyAgent, error) { +func (p *PolicyAutomationApp) loadPolicyFiles() ([]*policy.PolicyFile, error) { policyFiles := make([]*policy.PolicyFile, 0) for _, policyConfig := range p.config.Policies { var policySrc policy.PolicySource if policyConfig.LocalDirectory != "" { policySrc = policy.NewLocalPolicySource(policyConfig.LocalDirectory) - } else if policyConfig.GitRepository != "" { + } + if policyConfig.GitRepository != "" { policySrc = policy.NewGitPolicySource(policyConfig.GitRepository, policyConfig.GitBranch, policyConfig.GitDirectory) @@ -156,16 +172,7 @@ func (p *PolicyAutomationApp) loadAndCompilePolicyFiles() (*policy.PolicyAgent, } policyFiles = append(policyFiles, files...) } - pa := policy.NewPolicyAgent(p.ctx) - - p.out.ColorPrintf("[light_gray][bold]Parsing REGO policies...\n") - log.Info("Parsing rego policies") - if err := pa.WithFiles(policyFiles); err != nil { - p.out.ErrorPrint("could not parse policy files", err) - log.Errorf("could not parse policy files: %s", err) - return nil, err - } - return pa, nil + return policyFiles, nil } func newConfigFromFile(path string) (*ConfigNg, error) { @@ -185,7 +192,8 @@ func newConfigFromCli(cliConfig *CliConfig) *ConfigNg { } if cliConfig.LocalDirectory != "" { config.Policies = append(config.Policies, ConfigPolicy{LocalDirectory: cliConfig.LocalDirectory}) - } else if cliConfig.GitRepository != "" { + } + if cliConfig.GitRepository != "" { config.Policies = append(config.Policies, ConfigPolicy{ GitRepository: cliConfig.GitRepository, GitBranch: cliConfig.GitBranch, From 460c8cb9b08461a266f3d3e3cf9548d63f7197d2 Mon Sep 17 00:00:00 2001 From: Ewa Wojtach Date: Tue, 12 Apr 2022 10:42:40 +0200 Subject: [PATCH 5/5] gke-policy command fixed, new command added --- README.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 334dd81..0de97d5 100644 --- a/README.md +++ b/README.md @@ -42,13 +42,13 @@ CLI can be previously authenticated with `gcloud auth application-default login` Parameters for GKE cluster review can be provided as command parameters or via configuration .yaml file. ```sh -gke-policy-automation [global options] command [command options] [arguments...] +gke-policy [global options] command [command options] [arguments...] ``` For cluster review with manually provided parameters: ```sh -./gke-policy-automation cluster review -p -n -l +./gke-policy cluster review -p -n -l ``` and with .yaml file with format: @@ -73,13 +73,19 @@ Custom policies can be provided via local directory or remote Github repository. Example for local directory: ```sh -./gke-policy-automation cluster review -p my_project -n my_cluster -l europe-central2-a --local-policy-dir ./gke-policies/policy +./gke-policy cluster review -p my_project -n my_cluster -l europe-central2-a --local-policy-dir ./gke-policies/policy ``` and for Github repository: ```sh -./gke-policy-automation cluster review -p my_project -n my_cluster -l europe-central2-a --git-policy-repo "https://github.com/google/gke-policy-automation" --git-policy-branch main --git-policy-dir gka-policies/policy +./gke-policy cluster review -p my_project -n my_cluster -l europe-central2-a --git-policy-repo "https://github.com/google/gke-policy-automation" --git-policy-branch main --git-policy-dir gka-policies/policy +``` + +Policy definition validation can be done with command: + +```sh +gke-policy policy check [arguments...] ``` ## Test