Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Secret Token Validation #128

Closed
wants to merge 34 commits into from
Closed

Conversation

barv-jfrog
Copy link
Contributor

@barv-jfrog barv-jfrog commented Aug 4, 2024

  • The pull request is targeting the dev branch.
  • The code has been validated to compile successfully by running go vet ./....
  • The code has been formatted properly using go fmt ./....
  • All static analysis checks passed.
  • All tests have passed. If this feature is not already covered by the tests, new tests have been added.
  • All changes are detailed at the description. if not already covered at JFrog Documentation, new documentation have been added.

Depends on - jfrog/documentation#145
Depends on - jfrog/jfrog-client-go#991


Description - adding a flag --validate-secrets to jf audit and jf docker scan so secrets found will trigger token validation on XRAY. Token validation takes secrets that are api tokens for example amazon secret key and checks if this key is still valid on amazon side. The capability is identical to audit and docker scan.
What I do is I pass an env var to analyzermanager because analyzers contain an env variable which according to its value (true/false) turns on the Gadget which is responsible for token validation.
As you see, there are multiple options to pass this env var, first through flag --validate-secrets, second through env var defined in user setup, third XRAY API which exists only from 3.101.0. otherwise it returns False.

@barv-jfrog barv-jfrog changed the base branch from main to dev August 4, 2024 09:03
@barv-jfrog barv-jfrog changed the title Token validation Secret Token Validation Aug 4, 2024
@barv-jfrog barv-jfrog closed this Aug 4, 2024
@barv-jfrog barv-jfrog reopened this Aug 4, 2024
@attiasas attiasas added new feature Automatically generated release notes safe to test Approve running integration tests on a pull request labels Aug 11, 2024
@github-actions github-actions bot removed the safe to test Approve running integration tests on a pull request label Aug 11, 2024
Copy link

👍 Frogbot scanned this pull request and did not find any new security issues.


@attiasas attiasas self-requested a review August 12, 2024 08:42
Copy link
Contributor

@attiasas attiasas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, please take a look at my comments:

  1. Add example image to the PR details (run results table format)
  2. Fix tests
  3. Add integration tests for the new statuses (project with all types)

Watches: components.NewStringFlag(Watches, "A comma-separated list of Xray watches, to determine Xray's violations creation."),
RepoPath: components.NewStringFlag(RepoPath, "Target repo path, to enable Xray to determine watches accordingly."),
Licenses: components.NewBoolFlag(Licenses, "Set to true if you'd like to receive licenses from Xray scanning."),
SecretValidation: components.NewBoolFlag(SecretValidation, "Set it if you want exposures scanner to validate api tokens"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
SecretValidation: components.NewBoolFlag(SecretValidation, "Set it if you want exposures scanner to validate api tokens"),
SecretValidation: components.NewBoolFlag(SecretValidation, "Set to true if you want exposures scanner to validate api tokens"),

Comment on lines 129 to +150

func GetResultPropertyTokenValidation(result *sarif.Result) string {
if result != nil && result.Properties != nil && result.Properties["tokenValidation"] != nil {
status, ok := result.Properties["tokenValidation"].(string)
if !ok {
return ""
}
return status
}
return ""
}

func GetResultPropertyMetadata(result *sarif.Result) string {
if result != nil && result.Properties != nil && result.Properties["metadata"] != nil {
metadata, ok := result.Properties["metadata"].(string)
if !ok {
return ""
}
return metadata
}
return ""
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func GetResultPropertyTokenValidation(result *sarif.Result) string {
if result != nil && result.Properties != nil && result.Properties["tokenValidation"] != nil {
status, ok := result.Properties["tokenValidation"].(string)
if !ok {
return ""
}
return status
}
return ""
}
func GetResultPropertyMetadata(result *sarif.Result) string {
if result != nil && result.Properties != nil && result.Properties["metadata"] != nil {
metadata, ok := result.Properties["metadata"].(string)
if !ok {
return ""
}
return metadata
}
return ""
}
func GetResultProperty(key string, result *sarif.Result) string {
if result != nil && result.Properties != nil && result.Properties[key] != nil {
status, ok := result.Properties[key].(string)
if !ok {
return ""
}
return status
}
return ""
}
func GetResultPropertyTokenValidation(result *sarif.Result) string {
return GetResultProperty("tokenValidation", result)
}
func GetResultPropertyMetadata(result *sarif.Result) string {
return GetResultProperty("metadata", result)
}

reduce code duplications

Comment on lines +36 to +45
func CreateResultWithTokenValidation(msg, ruleId, level string, tokenValidation string, metadata string, locations ...*sarif.Location) *sarif.Result {
result := &sarif.Result{
Message: *sarif.NewTextMessage(msg),
Level: &level,
RuleID: &ruleId,
Locations: locations,
}
result.Properties = map[string]interface{}{"tokenValidation": tokenValidation, "metadata": metadata}
return result
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func CreateResultWithTokenValidation(msg, ruleId, level string, tokenValidation string, metadata string, locations ...*sarif.Location) *sarif.Result {
result := &sarif.Result{
Message: *sarif.NewTextMessage(msg),
Level: &level,
RuleID: &ruleId,
Locations: locations,
}
result.Properties = map[string]interface{}{"tokenValidation": tokenValidation, "metadata": metadata}
return result
}
func CreateResultWithProperties(msg, ruleId, level string, properties map[string]string, locations ...*sarif.Location) *sarif.Result {
result := &sarif.Result{
Message: *sarif.NewTextMessage(msg),
Level: &level,
RuleID: &ruleId,
Locations: locations,
Properties: make(sarif.Properties),
}
for key, val := range properties {
result.Properties[key] = value
}
return result
}

Make it general and not specific

Comment on lines +128 to +134
var tokenValidationOrder = map[string]int{
"Active": 1,
"Inactive": 2,
"Unsupported": 3,
"Unavailable": 4,
"": 5,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

type TokenStatus string
Move this to jasutils, create a new type to be used in all places (just like ApplicableStatus)

Comment on lines +136 to +151
type SourceCodeRows []SourceCodeRow

func (a SourceCodeRows) Less(i, j int) bool {
if tokenValidationOrder[a[i].TokenValidation] != tokenValidationOrder[a[j].TokenValidation] {
return tokenValidationOrder[a[i].TokenValidation] < tokenValidationOrder[a[j].TokenValidation]
}
return a[i].SeverityNumValue > a[j].SeverityNumValue
}

func (a SourceCodeRows) Len() int {
return len(a)
}

func (a SourceCodeRows) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for new type, please remove. move logic to the actual usage at resultstable.go use anonymus func

Comment on lines +443 to +445
amEnvVars := jas.GetAnalyzerManagerXscEnvVars("", techutils.Technology(graphScanResults.ScannedPackageType))
jas.AppendTokenValidationToEnvVars(amEnvVars, validateSecrets)
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, scanCmd.serverDetails, amEnvVars)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
amEnvVars := jas.GetAnalyzerManagerXscEnvVars("", techutils.Technology(graphScanResults.ScannedPackageType))
jas.AppendTokenValidationToEnvVars(amEnvVars, validateSecrets)
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, scanCmd.serverDetails, amEnvVars)
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, scanCmd.serverDetails, jas.GetAnalyzerManagerXscEnvVars("", techutils.Technology(graphScanResults.ScannedPackageType), validateSecrets))

no need for AppendTokenValidationToEnvVars this is a new var for running the AM, it should be in the right method

Comment on lines +218 to +224
dynamicTokenVersionMismatchErr := clientutils.ValidateMinimumVersion(clientutils.Xray, xrayVersion, jasutils.DynamicTokenValidationMinXrayVersion)
if dynamicTokenVersionMismatchErr != nil && (scanCmd.validateSecrets) {
log.Warn("Token validation (--validate-secrets flag) is not supported in your xray version")
scanResults.ExtendedScanResults.SecretValidation = false
} else {
scanResults.ExtendedScanResults.SecretValidation = jas.CheckForSecretValidation(xrayManager, scanCmd.validateSecrets)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to reduce code duplication and to make sure this is always running, put clientutils.ValidateMinimumVersion inside of CheckForSecretValidation right before running the API call.
(also true for the one in audit)

Comment on lines +203 to +209
dynamicTokenVersionMismatchErr := clientutils.ValidateMinimumVersion(clientutils.Xray, auditParams.xrayVersion, jasutils.DynamicTokenValidationMinXrayVersion)
if dynamicTokenVersionMismatchErr != nil && (auditParams.AuditBasicParams.ValidateSecrets) {
log.Warn("Token validation (--validate-secrets flag) is not supported in your xray version")
results.ExtendedScanResults.SecretValidation = false
} else {
results.ExtendedScanResults.SecretValidation = jas.CheckForSecretValidation(xrayManager, auditParams.AuditBasicParams.ValidateSecrets)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to reduce code duplication and to make sure this is always running, put clientutils.ValidateMinimumVersion inside of CheckForSecretValidation right before running the API call.
(also true for the one in scan)

Comment on lines +276 to +278
amEnvVars := jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, scanResults.GetScaScannedTechnologies()...)
jas.AppendTokenValidationToEnvVars(amEnvVars, scanResults.ExtendedScanResults.SecretValidation)
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, serverDetails, amEnvVars, auditParams.Exclusions()...)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
amEnvVars := jas.GetAnalyzerManagerXscEnvVars(auditParams.commonGraphScanParams.MultiScanId, scanResults.GetScaScannedTechnologies()...)
jas.AppendTokenValidationToEnvVars(amEnvVars, scanResults.ExtendedScanResults.SecretValidation)
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, serverDetails, amEnvVars, auditParams.Exclusions()...)
scanner, err = jas.CreateJasScanner(scanner, jfrogAppsConfig, scanCmd.serverDetails, jas.GetAnalyzerManagerXscEnvVars("", techutils.Technology(graphScanResults.ScannedPackageType), validateSecrets))

no need for AppendTokenValidationToEnvVars this is a new var for running the AM, it should be in the right method

@@ -212,7 +212,7 @@ type DependencyTreeResult struct {
}

func GetTechDependencyTree(params xrayutils.AuditParams, artifactoryServerDetails *config.ServerDetails, tech techutils.Technology) (depTreeResult DependencyTreeResult, err error) {
logMessage := fmt.Sprintf("Calculating %s dependencies", tech.ToFormal())
logMessage := fmt.Sprintf("Calculating %s dependencies DEBUG MODE ACTIVATED", tech.ToFormal())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logMessage := fmt.Sprintf("Calculating %s dependencies DEBUG MODE ACTIVATED", tech.ToFormal())
logMessage := fmt.Sprintf("Calculating %s dependencies", tech.ToFormal())

remove to old value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature Automatically generated release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants