Skip to content
This repository has been archived by the owner on Jul 19, 2023. It is now read-only.

Commit

Permalink
feat: Add a rule to ensure code quality scanner in the repo
Browse files Browse the repository at this point in the history
* code quality scanners rule

* code quality scanners rule

* add if condition on rule

* increase rule unique id
  • Loading branch information
OriYosef authored Oct 6, 2022
1 parent a3c51d5 commit 1af6c3c
Show file tree
Hide file tree
Showing 4 changed files with 194 additions and 0 deletions.
177 changes: 177 additions & 0 deletions pkg/rulesConfig/defaultRules/17-ensure-code-quality.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
package defaultRules

import (
"encoding/json"

githubConnector "github.com/allero-io/allero/pkg/connectors/github"
gitlabConnector "github.com/allero-io/allero/pkg/connectors/gitlab"
)

func EnsureCodeQualityScanner(githubData map[string]*githubConnector.GithubOwner, gitlabData map[string]*gitlabConnector.GitlabGroup) ([]*SchemaError, error) {
schemaErrors := make([]*SchemaError, 0)
var err error

if githubData != nil {
schemaErrors, err = githubErrorsRule17(githubData)
if err != nil {
return nil, err
}
}

if gitlabData != nil {
schemaErrors, err = gitlabErrorsRule17(gitlabData)
if err != nil {
return nil, err
}
}

return schemaErrors, nil
}

func githubErrorsRule17(githubData map[string]*githubConnector.GithubOwner) ([]*SchemaError, error) {
schemaErrors := make([]*SchemaError, 0)

usesRegexExpressions := []string{
".*paambaati/codeclimate-action@.*",
".*kitabisa/sonarqube-action@.*",
".*sonarsource/sonarcloud-github-action@.*",
}

runRegexExpressions := []string{
".*docker .* run .*codeclimate/codeclimate analyze.*",
}

for _, owner := range githubData {
for _, repo := range owner.Repositories {
foundCodeQualityScanner := 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) {
foundCodeQualityScanner = true
break
}
}

for _, regexExpression := range runRegexExpressions {
if matchRegex(regexExpression, step.Run) {
foundCodeQualityScanner = true
break
}
}

if foundCodeQualityScanner {
break
}
}

if foundCodeQualityScanner {
break
}
}

if foundCodeQualityScanner {
break
}
}

if !foundCodeQualityScanner {
schemaErrors = append(schemaErrors, &SchemaError{
ErrorLevel: 1,
RepositryName: repo.Name,
CiCdPlatform: "github-actions-workflows",
OwnerName: owner.Name,
ScmPlatform: "github",
})
}
}
}

return schemaErrors, nil
}

func gitlabErrorsRule17(gitlabData map[string]*gitlabConnector.GitlabGroup) ([]*SchemaError, error) {
schemaErrors := make([]*SchemaError, 0)

for _, group := range gitlabData {
for _, project := range group.Projects {
foundCodeQualityScanner, err := findCodeQualityScannerRule17(project)
if err != nil {
return nil, err
}

if !foundCodeQualityScanner {
schemaErrors = append(schemaErrors, &SchemaError{
ErrorLevel: 2,
RepositryName: project.Name,
CiCdPlatform: "gitlab-ci",
OwnerName: group.Name,
ScmPlatform: "gitlab",
})
}
}
}

return schemaErrors, nil
}

func findCodeQualityScannerRule17(project *gitlabConnector.GitlabProject) (bool, error) {
scriptRegexExpressions := []string{
".*docker .* run .*codeclimate/codeclimate analyze.*",
}

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
}
3 changes: 3 additions & 0 deletions pkg/rulesConfig/defaultRules/defaultRules.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ func Validate(rule *Rule, githubData map[string]*githubConnector.GithubOwner, gi
if rule.UniqueId == 16 {
return EnsureLinter(githubData, gitlabData)
}
if rule.UniqueId == 17 {
return EnsureCodeQualityScanner(githubData, gitlabData)
}

return nil, fmt.Errorf("missing implementation for rule %d", rule.UniqueId)
}
Expand Down
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 Code Quality scanner",
"failureMessage": "Code Quality scanner was not detected in the repository pipelines. It is highly recommended to add one to keep quality code.",
"uniqueId": 17,
"enabledByDefault": false,
"inCodeImplementation": true
}
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 Code Quality scanner",
"failureMessage": "Code Quality scanner was not detected in the repository pipelines. It is highly recommended to add one to keep quality code.",
"uniqueId": 17,
"enabledByDefault": false,
"inCodeImplementation": true
}

0 comments on commit 1af6c3c

Please sign in to comment.