diff --git a/README.md b/README.md index 2123153..09970dc 100644 --- a/README.md +++ b/README.md @@ -101,12 +101,22 @@ You can specify the configuration file with the command line option `-config (-c ghalint -c foo.yaml run ``` -You can exclude the policy `job_secrets` and `action_ref_should_be_full_length_commit_sha`. +### Disable policies + +You can disable the following policies. + +- [deny_inherit_secrets](docs/policies/004.md) +- [job_secrets](docs/policies/006.md) +- [action_ref_should_be_full_length_commit_sha](docs/policies/008.md) +- [github_app_should_limit_repositories](docs/policies/009.md) e.g. ```yaml excludes: + - policy_name: deny_inherit_secrets + workflow_file_path: .github/workflows/actionlint.yaml + job_name: actionlint - policy_name: job_secrets workflow_file_path: .github/workflows/actionlint.yaml job_name: actionlint @@ -118,14 +128,6 @@ excludes: step_id: create_token ``` -### excludes[].policy_name - -Required. You can exclude only the following policies. - -- [job_secrets](docs/policies/006.md) -- [action_ref_should_be_full_length_commit_sha](docs/policies/008.md) -- [github_app_should_limit_repositories](docs/policies/009.md) - ## Environment variables - `GHALINT_CONFIG`: Configuration file path diff --git a/docs/policies/004.md b/docs/policies/004.md index c97aa0a..4f1c99f 100644 --- a/docs/policies/004.md +++ b/docs/policies/004.md @@ -27,3 +27,20 @@ jobs: ## Why? Secrets should be exposed to only required jobs. + +## How to ignore the violation + +We don't recommend, but if you want to ignore the violation of this policy, please configure it with [the configuration file](../../README.md#configuration-file). + +e.g. + +ghalint.yaml + +```yaml +excludes: + - policy_name: deny_inherit_secrets + workflow_file_path: .github/workflows/actionlint.yaml + job_name: actionlint +``` + +`policy_name`, `workflow_file_path`, and `job_name` are required. diff --git a/pkg/config/config.go b/pkg/config/config.go index c152d24..59222ef 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -76,6 +76,13 @@ func validate(exclude *Exclude) error { //nolint:cyclop if exclude.JobName == "" { return errors.New(`job_name is required to exclude job_secrets`) } + case "deny_inherit_secrets": + if exclude.WorkflowFilePath == "" { + return errors.New(`workflow_file_path is required to exclude deny_inherit_secrets`) + } + if exclude.JobName == "" { + return errors.New(`job_name is required to exclude deny_inherit_secrets`) + } case "github_app_should_limit_repositories": if exclude.WorkflowFilePath == "" && exclude.ActionFilePath == "" { return errors.New(`workflow_file_path or action_file_path is required to exclude github_app_should_limit_repositories`) diff --git a/pkg/policy/deny_inherit_secrets.go b/pkg/policy/deny_inherit_secrets.go index f74ef29..ba4e785 100644 --- a/pkg/policy/deny_inherit_secrets.go +++ b/pkg/policy/deny_inherit_secrets.go @@ -18,7 +18,10 @@ func (p *DenyInheritSecretsPolicy) ID() string { return "004" } -func (p *DenyInheritSecretsPolicy) ApplyJob(_ *logrus.Entry, _ *config.Config, _ *JobContext, job *workflow.Job) error { +func (p *DenyInheritSecretsPolicy) ApplyJob(_ *logrus.Entry, cfg *config.Config, jobCtx *JobContext, job *workflow.Job) error { + if checkExcludes(p.Name(), jobCtx, cfg) { + return nil + } if job.Secrets.Inherit() { return errors.New("`secrets: inherit` should not be used. Only required secrets should be passed explicitly") } diff --git a/pkg/policy/deny_inherit_secrets_test.go b/pkg/policy/deny_inherit_secrets_test.go index f2d135f..3257585 100644 --- a/pkg/policy/deny_inherit_secrets_test.go +++ b/pkg/policy/deny_inherit_secrets_test.go @@ -1,9 +1,11 @@ +//nolint:funlen package policy_test import ( "testing" "github.com/sirupsen/logrus" + "github.com/suzuki-shunsuke/ghalint/pkg/config" "github.com/suzuki-shunsuke/ghalint/pkg/policy" "github.com/suzuki-shunsuke/ghalint/pkg/workflow" "gopkg.in/yaml.v3" @@ -12,17 +14,72 @@ import ( func TestDenyInheritSecretsPolicy_ApplyJob(t *testing.T) { t.Parallel() data := []struct { - name string - job string - isErr bool + name string + job string + cfg *config.Config + jobCtx *policy.JobContext + isErr bool }{ { - name: "error", + name: "exclude", + cfg: &config.Config{ + Excludes: []*config.Exclude{ + { + PolicyName: "deny_inherit_secrets", + WorkflowFilePath: ".github/workflows/test.yaml", + JobName: "foo", + }, + }, + }, + jobCtx: &policy.JobContext{ + Workflow: &policy.WorkflowContext{ + FilePath: ".github/workflows/test.yaml", + }, + Name: "foo", + }, + job: `secrets: inherit`, + }, + { + name: "not exclude", + cfg: &config.Config{ + Excludes: []*config.Exclude{ + { + PolicyName: "deny_inherit_secrets", + WorkflowFilePath: ".github/workflows/test.yaml", + JobName: "bar", + }, + }, + }, + jobCtx: &policy.JobContext{ + Workflow: &policy.WorkflowContext{ + FilePath: ".github/workflows/test.yaml", + }, + Name: "foo", + }, job: `secrets: inherit`, isErr: true, }, + { + name: "error", + job: `secrets: inherit`, + cfg: &config.Config{}, + jobCtx: &policy.JobContext{ + Workflow: &policy.WorkflowContext{ + FilePath: ".github/workflows/test.yaml", + }, + Name: "foo", + }, + isErr: true, + }, { name: "pass", + cfg: &config.Config{}, + jobCtx: &policy.JobContext{ + Workflow: &policy.WorkflowContext{ + FilePath: ".github/workflows/test.yaml", + }, + Name: "foo", + }, job: `secrets: foo: ${{secrets.API_KEY}}`, }, @@ -37,7 +94,7 @@ func TestDenyInheritSecretsPolicy_ApplyJob(t *testing.T) { if err := yaml.Unmarshal([]byte(d.job), job); err != nil { t.Fatal(err) } - if err := p.ApplyJob(logE, nil, nil, job); err != nil { + if err := p.ApplyJob(logE, d.cfg, d.jobCtx, job); err != nil { if d.isErr { return }