This repository has been archived by the owner on Jul 19, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add a rule to ensure secrets scanner is running in the repo
- Loading branch information
Showing
4 changed files
with
223 additions
and
2 deletions.
There are no files selected for viewing
203 changes: 203 additions & 0 deletions
203
pkg/rulesConfig/defaultRules/15-ensure-secrets-scanner.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
package defaultRules | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"strings" | ||
|
||
githubConnector "github.com/allero-io/allero/pkg/connectors/github" | ||
gitlabConnector "github.com/allero-io/allero/pkg/connectors/gitlab" | ||
) | ||
|
||
func EnsureSecretsScanner(githubData map[string]*githubConnector.GithubOwner, gitlabData map[string]*gitlabConnector.GitlabGroup) ([]*SchemaError, error) { | ||
schemaErrors := make([]*SchemaError, 0) | ||
var err error | ||
|
||
if githubData != nil { | ||
schemaErrors, err = githubErrorsRule15(githubData) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
if gitlabData != nil { | ||
schemaErrors, err = gitlabErrorsRule15(gitlabData) | ||
if err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
return schemaErrors, nil | ||
} | ||
|
||
func githubErrorsRule15(githubData map[string]*githubConnector.GithubOwner) ([]*SchemaError, error) { | ||
schemaErrors := make([]*SchemaError, 0) | ||
|
||
usesRegexExpressions := []string{ | ||
".*trufflesecurity/trufflehog@.*", | ||
".*GitGuardian/ggshield/actions/secret@.*", | ||
".*GitGuardian/ggshield-action@.*", | ||
".*gitleaks/gitleaks-action@.*", | ||
} | ||
|
||
usesAndWithRegexExpressions := []map[string]string{ | ||
{ | ||
"uses": ".*aquasecurity/trivy-action@.*", | ||
"with": "security-checks:secret", | ||
}, | ||
} | ||
|
||
runRegexExpressions := []string{ | ||
".*^[\\S]*trufflehog.*|.*docker .* run .*(trufflesecurity/)?trufflehog.*", | ||
".*ggshield secret scan.*", | ||
".*^[\\S]*gitleaks.*|.*docker .* run .*(zricethezav/)?gitleaks.*.*", | ||
".*^[\\S]*trivy fs.*|.*docker .* run .*(aquasec/)?trivy fs.*", | ||
} | ||
for _, owner := range githubData { | ||
for _, repo := range owner.Repositories { | ||
foundSecretsScanner := false | ||
|
||
for _, workflow := range repo.GithubActionsWorkflows { | ||
content := workflow.Content | ||
contentByteArr, err := json.Marshal(content) | ||
if err != nil { | ||
return nil, err | ||
} | ||
var workflowObj Workflow | ||
err = json.Unmarshal(contentByteArr, &workflowObj) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
for _, job := range workflowObj.Jobs { | ||
for _, step := range job.Steps { | ||
for _, regexExpression := range usesRegexExpressions { | ||
if matchRegex(regexExpression, step.Uses) { | ||
foundSecretsScanner = true | ||
break | ||
} | ||
} | ||
|
||
for _, regexExpression := range runRegexExpressions { | ||
if matchRegex(regexExpression, step.Run) { | ||
foundSecretsScanner = true | ||
break | ||
} | ||
} | ||
|
||
for _, regexExpression := range usesAndWithRegexExpressions { | ||
if matchRegex(regexExpression["uses"], step.Uses) { | ||
withRegex := strings.Split(regexExpression["with"], ":") | ||
withRegexKey, withRegexValue := withRegex[0], withRegex[1] | ||
for withKey, withValue := range step.With { | ||
withValueAsString := fmt.Sprintf("%v", withValue) | ||
if withKey == withRegexKey && matchRegex(withRegexValue, withValueAsString) { | ||
foundSecretsScanner = true | ||
} | ||
} | ||
} | ||
} | ||
if foundSecretsScanner { | ||
break | ||
} | ||
} | ||
|
||
if foundSecretsScanner { | ||
break | ||
} | ||
} | ||
|
||
if foundSecretsScanner { | ||
break | ||
} | ||
} | ||
|
||
if !foundSecretsScanner { | ||
schemaErrors = append(schemaErrors, &SchemaError{ | ||
ErrorLevel: 1, | ||
RepositryName: repo.Name, | ||
CiCdPlatform: "github-actions-workflows", | ||
OwnerName: owner.Name, | ||
ScmPlatform: "github", | ||
}) | ||
} | ||
} | ||
} | ||
|
||
return schemaErrors, nil | ||
} | ||
|
||
func gitlabErrorsRule15(gitlabData map[string]*gitlabConnector.GitlabGroup) ([]*SchemaError, error) { | ||
schemaErrors := make([]*SchemaError, 0) | ||
|
||
for _, group := range gitlabData { | ||
for _, project := range group.Projects { | ||
foundScaScanner, err := findSecretsScannerRule15(project) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if !foundScaScanner { | ||
schemaErrors = append(schemaErrors, &SchemaError{ | ||
ErrorLevel: 2, | ||
RepositryName: project.Name, | ||
CiCdPlatform: "gitlab-ci", | ||
OwnerName: group.Name, | ||
ScmPlatform: "gitlab", | ||
}) | ||
} | ||
} | ||
} | ||
|
||
return schemaErrors, nil | ||
} | ||
|
||
func findSecretsScannerRule15(project *gitlabConnector.GitlabProject) (bool, error) { | ||
scriptRegexExpressions := []string{ | ||
".*^[\\S]*trufflehog.*|.*docker .* run .*(trufflesecurity/)?trufflehog.*", | ||
".*ggshield secret scan.*", | ||
".*^[\\S]*gitleaks.*|.*docker .* run .*(zricethezav/)?gitleaks.*.*", | ||
".*^[\\S]*trivy fs.*|.*docker .* run .*(aquasec/)?trivy fs.*", | ||
} | ||
|
||
for _, pipeline := range project.GitlabCi { | ||
|
||
for _, stage := range pipeline.Content { | ||
stageBytes, err := json.Marshal(stage) | ||
if err != nil { | ||
return false, err | ||
} | ||
|
||
var stageWithSingleScript GitlabStageScript | ||
var stageWithScripts GitlabStageScripts | ||
|
||
err = json.Unmarshal(stageBytes, &stageWithSingleScript) | ||
if err != nil { | ||
err = json.Unmarshal(stageBytes, &stageWithScripts) | ||
if err != nil { | ||
continue | ||
} | ||
} | ||
|
||
if stageWithSingleScript.Script != "" { | ||
for _, regexExpression := range scriptRegexExpressions { | ||
if matchRegex(regexExpression, stageWithSingleScript.Script) { | ||
return true, nil | ||
} | ||
} | ||
} | ||
|
||
if stageWithScripts.Scripts != nil { | ||
for _, script := range stageWithScripts.Scripts { | ||
for _, regexExpression := range scriptRegexExpressions { | ||
if matchRegex(regexExpression, script) { | ||
return true, nil | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return false, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
pkg/rulesConfig/defaultRules/github/15-ensure-secrets-scanner.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"description": "Ensure that at least one pipeline in each repository runs Secrets scanner", | ||
"failureMessage": "Secrets scanner was not detected in the repository pipelines. It is highly recommended to add one to prevent secrets leaks.", | ||
"uniqueId": 15, | ||
"enabledByDefault": false, | ||
"inCodeImplementation": true | ||
} |
7 changes: 7 additions & 0 deletions
7
pkg/rulesConfig/defaultRules/gitlab/15-ensure-secrets-scanner.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"description": "Ensure that at least one pipeline in each repository runs Secrets scanner", | ||
"failureMessage": "Secrets scanner was not detected in the repository pipelines. It is highly recommended to add one to prevent secrets leaks.", | ||
"uniqueId": 15, | ||
"enabledByDefault": false, | ||
"inCodeImplementation": true | ||
} |