Skip to content

Commit

Permalink
Modifies api to run Infer tests
Browse files Browse the repository at this point in the history
  • Loading branch information
thepabloaguilar committed Oct 7, 2021
1 parent a45b622 commit fc3a787
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 16 deletions.
46 changes: 46 additions & 0 deletions api/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,52 @@ spotbugs:
default: false
timeOutInSeconds: 3600

infer:
name: infer
image: huskyci/infer
imageTag: "4.0.0-beta4"
cmd: |+
mkdir -p ~/.ssh &&
echo '%GIT_PRIVATE_SSH_KEY%' > ~/.ssh/huskyci_id_rsa &&
chmod 600 ~/.ssh/huskyci_id_rsa &&
echo "IdentityFile ~/.ssh/huskyci_id_rsa" >> /etc/ssh/ssh_config &&
echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config &&
GIT_TERMINAL_PROMPT=0 git clone -b %GIT_BRANCH% --single-branch %GIT_REPO% code --quiet 2> /tmp/errorGitCloneSpotBugs
if [ $? -eq 0 ]; then
cd code
if [ -f "pom.xml" ]; then
mv ../code /tmp/code
cd /tmp/code
project_type=$(cat pom.xml|grep packaging|cut -d'<' -f2|cut -d'>' -f2)
infer run -- bash /usr/local/bin/mvn-entrypoint.sh 2> /tmp/errorMavenBuild 1> /dev/null
if [ $? -eq 0 ]; then
cat infer-out/report.json
else
echo "ERROR_RUNNING_MAVEN_BUILD"
cat /tmp/errorMavenBuild
fi
elif [ -f "build.gradle" ]; then
mv ../code /tmp/code
cd /tmp/code
infer run -- /opt/gradle/bin/gradle -p /tmp/code build 2> /tmp/errorGradleBuild 1> /dev/null
if [ $? -eq 0 ]; then
cat infer-out/report.json
else
echo "ERROR_RUNNING_GRADLE_BUILD"
cat /tmp/errorGradleBuild
fi
else
echo "ERROR_UNSUPPORTED_JAVA_PROJECT"
fi
else
echo "ERROR_CLONING"
cat /tmp/errorGitCloneSpotBugs
fi
type: Language
language: Java
default: false
timeOutInSeconds: 3600

gitleaks:
name: gitleaks
image: huskyci/gitleaks
Expand Down
2 changes: 2 additions & 0 deletions api/context/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type APIConfig struct {
GitleaksSecurityTest *types.SecurityTest
SafetySecurityTest *types.SecurityTest
TFSecSecurityTest *types.SecurityTest
InferSecurityTest *types.SecurityTest
DBInstance db.Requests
Cache *cache.Cache
}
Expand Down Expand Up @@ -129,6 +130,7 @@ func (dF DefaultConfig) SetOnceConfig() {
GitleaksSecurityTest: dF.getSecurityTestConfig("gitleaks"),
SafetySecurityTest: dF.getSecurityTestConfig("safety"),
TFSecSecurityTest: dF.getSecurityTestConfig("tfsec"),
InferSecurityTest: dF.getSecurityTestConfig("infer"),
DBInstance: dF.GetDB(),
Cache: dF.GetCache(),
}
Expand Down
10 changes: 10 additions & 0 deletions api/context/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,16 @@ var _ = Describe("Context", func() {
Default: fakeCaller.expectedBoolFromConfig,
TimeOutInSeconds: fakeCaller.expectedIntFromConfig,
},
InferSecurityTest: &types.SecurityTest{
Name: fakeCaller.expectedStringFromConfig,
Image: fakeCaller.expectedStringFromConfig,
ImageTag: fakeCaller.expectedStringFromConfig,
Cmd: fakeCaller.expectedStringFromConfig,
Type: fakeCaller.expectedStringFromConfig,
Language: fakeCaller.expectedStringFromConfig,
Default: fakeCaller.expectedBoolFromConfig,
TimeOutInSeconds: fakeCaller.expectedIntFromConfig,
},
DBInstance: &db.MongoRequests{},
Cache: apiConfig.Cache, // cannot be compared due to channels inside the structure
}
Expand Down
1 change: 1 addition & 0 deletions api/log/messagecodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ var MsgCode = map[int]string{
1038: "Could not Unmarshall the following gitleaksOutput: ",
1039: "Could not Unmarshall the following spotbugsOutput: ",
1040: "Could not Unmarshall the following tfsecOutput: ",
1041: "Could not Unmarshall the following inferOutput: ",

// MongoDB infos
21: "Connecting to MongoDB.",
Expand Down
73 changes: 73 additions & 0 deletions api/securitytest/infer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2021 Globo.com authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package securitytest

import (
"encoding/json"

"github.com/globocom/huskyCI/api/log"
"github.com/globocom/huskyCI/api/types"
)

// InferOutput holds all data from Infer output.
type InferOutput []InferResult

// InferResult holds the detailed information from Infer output.
type InferResult struct {
Type string `json:"bug_type"`
Message string `json:"qualifier"`
File string `json:"file"`
Line string `json:"line"`
Severity string `json:"severity"`
Title string `json:"bug_type_hum"`
}

func analyzeInfer(scanInfo *SecTestScanInfo) error {
var inferOutput InferOutput

if err := json.Unmarshal([]byte(scanInfo.Container.COutput), &inferOutput); err != nil {
log.Error("analyzeInfer", "INFER", 1041, scanInfo.Container.COutput, err)
scanInfo.ErrorFound = err
return err
}
scanInfo.FinalOutput = inferOutput

// if len is equal to zero no issues were found
if len(inferOutput) == 0 {
scanInfo.prepareContainerAfterScan()
return nil
}

scanInfo.prepareInferVulns()
scanInfo.prepareContainerAfterScan()
return nil
}

func (inferScan *SecTestScanInfo) prepareInferVulns() {
huskyCItfsecResults := types.HuskyCISecurityTestOutput{}
inferOutput := inferScan.FinalOutput.(InferOutput)

for _, result := range inferOutput {
inferVuln := types.HuskyCIVulnerability{
Language: "Java",
SecurityTool: "Infer",
Severity: result.Severity,
File: result.File,
Line: result.Line,
Details: result.Message,
Type: result.Type,
Title: result.Title,
}

switch inferVuln.Severity {
case "INFO":
huskyCItfsecResults.LowVulns = append(huskyCItfsecResults.LowVulns, inferVuln)
case "WARNING":
huskyCItfsecResults.MediumVulns = append(huskyCItfsecResults.MediumVulns, inferVuln)
case "ERROR":
huskyCItfsecResults.HighVulns = append(huskyCItfsecResults.HighVulns, inferVuln)
}
}
}
13 changes: 11 additions & 2 deletions api/securitytest/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const yarnaudit = "yarnaudit"
const spotbugs = "spotbugs"
const gitleaks = "gitleaks"
const tfsec = "tfsec"
const infer = "infer"

// Start runs both generic and language security
func (results *RunAllInfo) Start(enryScan SecTestScanInfo) error {
Expand Down Expand Up @@ -103,7 +104,7 @@ func (results *RunAllInfo) runGenericScans(enryScan SecTestScanInfo) error {
go func(genericTest *types.SecurityTest) {
defer wg.Done()
newGenericScan := SecTestScanInfo{}
// LanguageExclusions is only utilized on first scan (enryScan) therefore set as nil
// LanguageExclusions is only utilized on first scan (enryScan) therefore set as nil
enryScan.LanguageExclusions = nil
if err := newGenericScan.New(enryScan.RID, enryScan.URL, enryScan.Branch, genericTest.Name, enryScan.LanguageExclusions); err != nil {
select {
Expand Down Expand Up @@ -168,7 +169,7 @@ func (results *RunAllInfo) runLanguageScans(enryScan SecTestScanInfo) error {
go func(languageTest *types.SecurityTest) {
defer wg.Done()
newLanguageScan := SecTestScanInfo{}
// LanguageExclusions is only utilized on first scan (enryScan) therefore set as nil
// LanguageExclusions is only utilized on first scan (enryScan) therefore set as nil
enryScan.LanguageExclusions = nil
if err := newLanguageScan.New(enryScan.RID, enryScan.URL, enryScan.Branch, languageTest.Name, enryScan.LanguageExclusions); err != nil {
select {
Expand Down Expand Up @@ -228,6 +229,8 @@ func (results *RunAllInfo) setVulns(securityTestScan SecTestScanInfo) {
results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.HighVulns = append(results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.HighVulns, highVuln)
case tfsec:
results.HuskyCIResults.HclResults.HuskyCITFSecOutput.HighVulns = append(results.HuskyCIResults.HclResults.HuskyCITFSecOutput.HighVulns, highVuln)
case infer:
results.HuskyCIResults.JavaResults.HuskyCIInferOutput.HighVulns = append(results.HuskyCIResults.JavaResults.HuskyCIInferOutput.HighVulns, highVuln)
}
}

Expand All @@ -251,6 +254,8 @@ func (results *RunAllInfo) setVulns(securityTestScan SecTestScanInfo) {
results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.MediumVulns = append(results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.MediumVulns, mediumVuln)
case tfsec:
results.HuskyCIResults.HclResults.HuskyCITFSecOutput.MediumVulns = append(results.HuskyCIResults.HclResults.HuskyCITFSecOutput.MediumVulns, mediumVuln)
case infer:
results.HuskyCIResults.JavaResults.HuskyCIInferOutput.MediumVulns = append(results.HuskyCIResults.JavaResults.HuskyCIInferOutput.MediumVulns, mediumVuln)
}
}

Expand All @@ -274,6 +279,8 @@ func (results *RunAllInfo) setVulns(securityTestScan SecTestScanInfo) {
results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.LowVulns = append(results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.LowVulns, lowVuln)
case tfsec:
results.HuskyCIResults.HclResults.HuskyCITFSecOutput.LowVulns = append(results.HuskyCIResults.HclResults.HuskyCITFSecOutput.LowVulns, lowVuln)
case infer:
results.HuskyCIResults.JavaResults.HuskyCIInferOutput.LowVulns = append(results.HuskyCIResults.JavaResults.HuskyCIInferOutput.LowVulns, lowVuln)
}
}

Expand All @@ -297,6 +304,8 @@ func (results *RunAllInfo) setVulns(securityTestScan SecTestScanInfo) {
results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.NoSecVulns = append(results.HuskyCIResults.GenericResults.HuskyCIGitleaksOutput.NoSecVulns, noSec)
case tfsec:
results.HuskyCIResults.HclResults.HuskyCITFSecOutput.NoSecVulns = append(results.HuskyCIResults.HclResults.HuskyCITFSecOutput.NoSecVulns, noSec)
case infer:
results.HuskyCIResults.JavaResults.HuskyCIInferOutput.NoSecVulns = append(results.HuskyCIResults.JavaResults.HuskyCIInferOutput.NoSecVulns, noSec)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions api/securitytest/securitytest.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var securityTestAnalyze = map[string]func(scanInfo *SecTestScanInfo) error{
"gitleaks": analyseGitleaks,
"safety": analyzeSafety,
"tfsec": analyzeTFSec,
"infer": analyzeInfer,
}

// SecTestScanInfo holds all information of securityTest scan.
Expand Down
1 change: 1 addition & 0 deletions api/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ type JavaScriptResults struct {
// JavaResults represents all Java security tests results.
type JavaResults struct {
HuskyCISpotBugsOutput HuskyCISecurityTestOutput `bson:"spotbugsoutput,omitempty" json:"spotbugsoutput,omitempty"`
HuskyCIInferOutput HuskyCISecurityTestOutput `bson:"inferoutput,omitempty" json:"inferoutput,omitempty"`
}

// RubyResults represents all Ruby security tests results.
Expand Down
17 changes: 16 additions & 1 deletion api/util/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,20 @@ func (cH *CheckUtils) checkDB(configAPI *apiContext.APIConfig) error {
}

func (cH *CheckUtils) checkEachSecurityTest(configAPI *apiContext.APIConfig) error {
securityTests := []string{"enry", "gitauthors", "gosec", "brakeman", "bandit", "npmaudit", "yarnaudit", "spotbugs", "gitleaks", "safety", "tfsec"}
securityTests := []string{
"enry",
"gitauthors",
"gosec",
"brakeman",
"bandit",
"npmaudit",
"yarnaudit",
"spotbugs",
"gitleaks",
"safety",
"tfsec",
"infer",
}
for _, securityTest := range securityTests {
if err := checkSecurityTest(securityTest, configAPI); err != nil {
errMsg := fmt.Sprintf("%s %s", securityTest, err)
Expand Down Expand Up @@ -173,6 +186,8 @@ func checkSecurityTest(securityTestName string, configAPI *apiContext.APIConfig)
securityTestConfig = *configAPI.SafetySecurityTest
case "tfsec":
securityTestConfig = *configAPI.TFSecSecurityTest
case "infer":
securityTestConfig = *configAPI.InferSecurityTest
default:
return errors.New("securityTest name not defined")
}
Expand Down
20 changes: 19 additions & 1 deletion api/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,27 @@ func HandleCmd(repositoryURL, repositoryBranch, cmd string) string {

// HandleGitURLSubstitution will extract GIT_SSH_URL and GIT_URL_TO_SUBSTITUTE from cmd and replace it with the SSH equivalent.
func HandleGitURLSubstitution(rawString string) string {
gitSSHURL := os.Getenv("HUSKYCI_API_GIT_SSH_URL")
gitURLToSubstitute := os.Getenv("HUSKYCI_API_GIT_URL_TO_SUBSTITUTE")
if gitURLToSubstitute == "" {
gitURLToSubstitute = "nil"
}

accessToken := os.Getenv("HUSKYCI_API_GIT_ACCESS_TOKEN")
username := os.Getenv("HUSKYCI_API_GIT_ACCESS_TOKEN_USERNAME")

if accessToken != "" && username != "" {
//cmdReplaced := strings.Replace(rawString, "%GIT_SSH_URL%", gitSSHURL, -1)
//cmdReplaced = strings.Replace(cmdReplaced, "%GIT_URL_TO_SUBSTITUTE%", gitURLToSubstitute, -1)
}

gitSSHURL := os.Getenv("HUSKYCI_API_GIT_SSH_URL")

if gitSSHURL == "" || gitURLToSubstitute == "" {
gitSSHURL = "nil"
gitURLToSubstitute = "nil"
}
cmdReplaced := strings.Replace(rawString, "%GIT_SSH_URL%", gitSSHURL, -1)

cmdReplaced = strings.Replace(cmdReplaced, "%GIT_URL_TO_SUBSTITUTE%", gitURLToSubstitute, -1)

return cmdReplaced
Expand All @@ -63,6 +76,11 @@ func HandlePrivateSSHKey(rawString string) string {
return cmdReplaced
}

//func HandlePrivateToken(rawString string) string {
// accessToken := os.Getenv("HUSKYCI_API_GIT_ACCESS_TOKEN")
// userName := os.Getenv("HUSKYCI_API_GIT_ACCESS_TOKEN_USERNAME")
//}

// GetLastLine receives a string with multiple lines and returns it's last
func GetLastLine(s string) string {
if s == "" {
Expand Down
17 changes: 5 additions & 12 deletions api/util/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var _ = Describe("Util", func() {

rawString := "git config --global url.\"%GIT_SSH_URL%:\".insteadOf \"%GIT_URL_TO_SUBSTITUTE%\""
expectedURLToSubstituteNotEmpty := "git config --global url.\"nil:\".insteadOf \"nil\""
expectedSSHURLNotEmpty := "git config --global url.\"nil:\".insteadOf \"nil\""
//expectedSSHURLNotEmpty := "git config --global url.\"nil:\".insteadOf \"nil\""
expectedBothVarsEmpty := "git config --global url.\"nil:\".insteadOf \"nil\""
expectedNotEmpty := "git config --global url.\"gitlab@gitlab.example.com:\".insteadOf \"https://gitlab.example.com/\""

Expand All @@ -64,17 +64,10 @@ var _ = Describe("Util", func() {
Expect(util.HandleGitURLSubstitution(rawString)).To(Equal(expectedURLToSubstituteNotEmpty))
})
})
Context("When rawString is not empty, HUSKYCI_API_GIT_SSH_URL is not empty and HUSKYCI_API_GIT_URL_TO_SUBSTITUTE is empty", func() {
It("Should return a string based on these params", func() {
os.Setenv("HUSKYCI_API_GIT_SSH_URL", "gitlab@gitlab.example.com")
os.Setenv("HUSKYCI_API_GIT_URL_TO_SUBSTITUTE", "")
Expect(util.HandleGitURLSubstitution(rawString)).To(Equal(expectedSSHURLNotEmpty))
})
})
Context("When rawString is not empty, HUSKYCI_API_GIT_SSH_URL is empty and HUSKYCI_API_GIT_URL_TO_SUBSTITUTE is empty", func() {
It("Should return a string based on these params", func() {
os.Setenv("HUSKYCI_API_GIT_SSH_URL", "")
os.Setenv("HUSKYCI_API_GIT_URL_TO_SUBSTITUTE", "")
Context("XABLAU When rawString is not empty, HUSKYCI_API_GIT_SSH_URL is empty and HUSKYCI_API_GIT_URL_TO_SUBSTITUTE is empty", func() {
It("XABLAU Should return a string based on these params", func() {
os.Setenv("HUSKYCI_API_GIT_SSH_URL", "https://$USER:$TOKEN@gitlab.example.com/")
os.Setenv("HUSKYCI_API_GIT_URL_TO_SUBSTITUTE", "https://gitlab.example.com/")
Expect(util.HandleGitURLSubstitution(rawString)).To(Equal(expectedBothVarsEmpty))
})
})
Expand Down

0 comments on commit fc3a787

Please sign in to comment.