2022-01-13 20:02:24 +00:00
package main
import (
2024-06-13 20:47:09 +00:00
"encoding/json"
2022-01-13 20:02:24 +00:00
"fmt"
2024-02-09 20:30:28 +00:00
"io"
2022-02-07 18:29:06 +00:00
"net/http"
_ "net/http/pprof"
2022-01-13 20:02:24 +00:00
"os"
2023-12-22 15:41:54 +00:00
"os/signal"
2022-01-13 20:02:24 +00:00
"runtime"
"strconv"
2022-03-15 00:27:14 +00:00
"strings"
2024-06-05 20:28:19 +00:00
"sync"
2022-04-03 18:51:56 +00:00
"syscall"
2023-12-22 15:41:54 +00:00
"time"
2022-02-07 18:29:06 +00:00
2023-10-30 17:58:38 +00:00
"github.com/alecthomas/kingpin/v2"
2022-04-04 04:13:39 +00:00
"github.com/felixge/fgprof"
2023-02-14 23:00:07 +00:00
"github.com/go-logr/logr"
2022-04-03 18:51:56 +00:00
"github.com/jpillora/overseer"
2023-08-09 20:13:55 +00:00
"github.com/mattn/go-isatty"
2022-08-10 17:11:13 +00:00
2023-10-26 16:28:56 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/cleantemp"
2022-02-10 18:54:33 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/common"
2022-12-20 16:14:49 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/config"
2022-08-29 18:45:37 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/context"
2022-02-10 18:54:33 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/engine"
2023-02-07 23:25:14 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/handlers"
2022-11-30 19:10:05 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/log"
2022-02-10 18:54:33 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/output"
2022-08-29 18:45:37 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/sources"
2023-08-09 20:13:55 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/tui"
2022-08-29 18:45:37 +00:00
"github.com/trufflesecurity/trufflehog/v3/pkg/updater"
"github.com/trufflesecurity/trufflehog/v3/pkg/version"
2022-01-13 20:02:24 +00:00
)
2022-04-03 18:51:56 +00:00
var (
2024-03-15 14:19:31 +00:00
cli = kingpin . New ( "TruffleHog" , "TruffleHog is a tool for finding credentials." )
cmd string
debug = cli . Flag ( "debug" , "Run in debug mode." ) . Bool ( )
trace = cli . Flag ( "trace" , "Run in trace mode." ) . Bool ( )
profile = cli . Flag ( "profile" , "Enables profiling and sets a pprof and fgprof server on :18066." ) . Bool ( )
localDev = cli . Flag ( "local-dev" , "Hidden feature to disable overseer for local dev." ) . Hidden ( ) . Bool ( )
jsonOut = cli . Flag ( "json" , "Output in JSON format." ) . Short ( 'j' ) . Bool ( )
jsonLegacy = cli . Flag ( "json-legacy" , "Use the pre-v3.0 JSON format. Only works with git, gitlab, and github sources." ) . Bool ( )
gitHubActionsFormat = cli . Flag ( "github-actions" , "Output in GitHub Actions format." ) . Bool ( )
concurrency = cli . Flag ( "concurrency" , "Number of concurrent workers." ) . Default ( strconv . Itoa ( runtime . NumCPU ( ) ) ) . Int ( )
noVerification = cli . Flag ( "no-verification" , "Don't verify the results." ) . Bool ( )
onlyVerified = cli . Flag ( "only-verified" , "Only output verified results." ) . Bool ( )
results = cli . Flag ( "results" , "Specifies which type(s) of results to output: verified, unknown, unverified. Defaults to all types." ) . Hidden ( ) . String ( )
2024-06-05 20:28:19 +00:00
allowVerificationOverlap = cli . Flag ( "allow-verification-overlap" , "Allow verification of similar credentials across detectors" ) . Bool ( )
filterUnverified = cli . Flag ( "filter-unverified" , "Only output first unverified result per chunk per detector if there are more than one results." ) . Bool ( )
filterEntropy = cli . Flag ( "filter-entropy" , "Filter unverified results with Shannon entropy. Start with 3.0." ) . Float64 ( )
scanEntireChunk = cli . Flag ( "scan-entire-chunk" , "Scan the entire chunk for secrets." ) . Hidden ( ) . Default ( "false" ) . Bool ( )
compareDetectionStrategies = cli . Flag ( "compare-detection-strategies" , "Compare different detection strategies for matching spans" ) . Hidden ( ) . Default ( "false" ) . Bool ( )
configFilename = cli . Flag ( "config" , "Path to configuration file." ) . ExistingFile ( )
2022-04-03 18:51:56 +00:00
// rules = cli.Flag("rules", "Path to file with custom rules.").String()
printAvgDetectorTime = cli . Flag ( "print-avg-detector-time" , "Print the average time spent on each detector." ) . Bool ( )
noUpdate = cli . Flag ( "no-update" , "Don't check for updates." ) . Bool ( )
2022-04-21 17:08:51 +00:00
fail = cli . Flag ( "fail" , "Exit with code 183 if results are found." ) . Bool ( )
2023-03-29 19:26:39 +00:00
verifiers = cli . Flag ( "verifier" , "Set custom verification endpoints." ) . StringMap ( )
2024-01-14 00:52:41 +00:00
customVerifiersOnly = cli . Flag ( "custom-verifiers-only" , "Only use custom verification endpoints." ) . Bool ( )
2023-02-16 21:56:55 +00:00
archiveMaxSize = cli . Flag ( "archive-max-size" , "Maximum size of archive to scan. (Byte units eg. 512B, 2KB, 4MB)" ) . Bytes ( )
2023-02-07 23:25:14 +00:00
archiveMaxDepth = cli . Flag ( "archive-max-depth" , "Maximum depth of archive to scan." ) . Int ( )
archiveTimeout = cli . Flag ( "archive-timeout" , "Maximum time to spend extracting an archive." ) . Duration ( )
2023-02-27 22:46:45 +00:00
includeDetectors = cli . Flag ( "include-detectors" , "Comma separated list of detector types to include. Protobuf name or IDs may be used, as well as ranges." ) . Default ( "all" ) . String ( )
excludeDetectors = cli . Flag ( "exclude-detectors" , "Comma separated list of detector types to exclude. Protobuf name or IDs may be used, as well as ranges. IDs defined here take precedence over the include list." ) . String ( )
2024-02-09 20:30:28 +00:00
jobReportFile = cli . Flag ( "output-report" , "Write a scan report to the provided path." ) . Hidden ( ) . OpenFile ( os . O_WRONLY | os . O_CREATE | os . O_TRUNC , 0666 )
2022-04-03 18:51:56 +00:00
gitScan = cli . Command ( "git" , "Find credentials in git repositories." )
2022-08-24 06:26:09 +00:00
gitScanURI = gitScan . Arg ( "uri" , "Git repository URL. https://, file://, or ssh:// schema expected." ) . Required ( ) . String ( )
2022-04-03 18:51:56 +00:00
gitScanIncludePaths = gitScan . Flag ( "include-paths" , "Path to file with newline separated regexes for files to include in scan." ) . Short ( 'i' ) . String ( )
gitScanExcludePaths = gitScan . Flag ( "exclude-paths" , "Path to file with newline separated regexes for files to exclude in scan." ) . Short ( 'x' ) . String ( )
2023-03-28 15:46:03 +00:00
gitScanExcludeGlobs = gitScan . Flag ( "exclude-globs" , "Comma separated list of globs to exclude in scan. This option filters at the `git log` level, resulting in faster scans." ) . String ( )
2022-04-03 18:51:56 +00:00
gitScanSinceCommit = gitScan . Flag ( "since-commit" , "Commit to start scan from." ) . String ( )
gitScanBranch = gitScan . Flag ( "branch" , "Branch to scan." ) . String ( )
gitScanMaxDepth = gitScan . Flag ( "max-depth" , "Maximum depth of commits to scan." ) . Int ( )
2023-08-03 16:23:41 +00:00
gitScanBare = gitScan . Flag ( "bare" , "Scan bare repository (e.g. useful while using in pre-receive hooks)" ) . Bool ( )
2022-04-03 18:51:56 +00:00
_ = gitScan . Flag ( "allow" , "No-op flag for backwards compat." ) . Bool ( )
_ = gitScan . Flag ( "entropy" , "No-op flag for backwards compat." ) . Bool ( )
_ = gitScan . Flag ( "regex" , "No-op flag for backwards compat." ) . Bool ( )
2024-01-31 15:52:24 +00:00
githubScan = cli . Command ( "github" , "Find credentials in GitHub repositories." )
githubScanEndpoint = githubScan . Flag ( "endpoint" , "GitHub endpoint." ) . Default ( "https://api.github.com" ) . String ( )
githubScanRepos = githubScan . Flag ( "repo" , ` GitHub repository to scan. You can repeat this flag. Example: "https://github.com/dustin-decker/secretsandstuff" ` ) . Strings ( )
githubScanOrgs = githubScan . Flag ( "org" , ` GitHub organization to scan. You can repeat this flag. Example: "trufflesecurity" ` ) . Strings ( )
githubScanToken = githubScan . Flag ( "token" , "GitHub token. Can be provided with environment variable GITHUB_TOKEN." ) . Envar ( "GITHUB_TOKEN" ) . String ( )
githubIncludeForks = githubScan . Flag ( "include-forks" , "Include forks in scan." ) . Bool ( )
githubIncludeMembers = githubScan . Flag ( "include-members" , "Include organization member repositories in scan." ) . Bool ( )
githubIncludeRepos = githubScan . Flag ( "include-repos" , ` Repositories to include in an org scan. This can also be a glob pattern. You can repeat this flag. Must use Github repo full name. Example: "trufflesecurity/trufflehog", "trufflesecurity/t*" ` ) . Strings ( )
2024-02-05 21:59:53 +00:00
githubIncludeWikis = githubScan . Flag ( "include-wikis" , "Include repository wikisin scan." ) . Bool ( )
2024-01-31 15:52:24 +00:00
2023-08-16 22:23:59 +00:00
githubExcludeRepos = githubScan . Flag ( "exclude-repos" , ` Repositories to exclude in an org scan. This can also be a glob pattern. You can repeat this flag. Must use Github repo full name. Example: "trufflesecurity/driftwood", "trufflesecurity/d*" ` ) . Strings ( )
githubScanIncludePaths = githubScan . Flag ( "include-paths" , "Path to file with newline separated regexes for files to include in scan." ) . Short ( 'i' ) . String ( )
githubScanExcludePaths = githubScan . Flag ( "exclude-paths" , "Path to file with newline separated regexes for files to exclude in scan." ) . Short ( 'x' ) . String ( )
2023-09-27 19:54:02 +00:00
githubScanIssueComments = githubScan . Flag ( "issue-comments" , "Include issue descriptions and comments in scan." ) . Bool ( )
githubScanPRComments = githubScan . Flag ( "pr-comments" , "Include pull request descriptions and comments in scan." ) . Bool ( )
2023-08-16 22:23:59 +00:00
githubScanGistComments = githubScan . Flag ( "gist-comments" , "Include gist comments in scan." ) . Bool ( )
2022-04-03 18:51:56 +00:00
gitlabScan = cli . Command ( "gitlab" , "Find credentials in GitLab repositories." )
// TODO: Add more GitLab options
2022-11-15 21:02:37 +00:00
gitlabScanEndpoint = gitlabScan . Flag ( "endpoint" , "GitLab endpoint." ) . Default ( "https://gitlab.com" ) . String ( )
gitlabScanRepos = gitlabScan . Flag ( "repo" , "GitLab repo url. You can repeat this flag. Leave empty to scan all repos accessible with provided credential. Example: https://gitlab.com/org/repo.git" ) . Strings ( )
gitlabScanToken = gitlabScan . Flag ( "token" , "GitLab token. Can be provided with environment variable GITLAB_TOKEN." ) . Envar ( "GITLAB_TOKEN" ) . Required ( ) . String ( )
gitlabScanIncludePaths = gitlabScan . Flag ( "include-paths" , "Path to file with newline separated regexes for files to include in scan." ) . Short ( 'i' ) . String ( )
gitlabScanExcludePaths = gitlabScan . Flag ( "exclude-paths" , "Path to file with newline separated regexes for files to exclude in scan." ) . Short ( 'x' ) . String ( )
2022-04-03 18:51:56 +00:00
2023-02-27 18:15:05 +00:00
filesystemScan = cli . Command ( "filesystem" , "Find credentials in a filesystem." )
filesystemPaths = filesystemScan . Arg ( "path" , "Path to file or directory to scan." ) . Strings ( )
// DEPRECATED: --directory is deprecated in favor of arguments.
filesystemDirectories = filesystemScan . Flag ( "directory" , "Path to directory to scan. You can repeat this flag." ) . Strings ( )
2022-04-03 18:51:56 +00:00
// TODO: Add more filesystem scan options. Currently only supports scanning a list of directories.
// filesystemScanRecursive = filesystemScan.Flag("recursive", "Scan recursively.").Short('r').Bool()
2023-01-26 17:33:45 +00:00
filesystemScanIncludePaths = filesystemScan . Flag ( "include-paths" , "Path to file with newline separated regexes for files to include in scan." ) . Short ( 'i' ) . String ( )
filesystemScanExcludePaths = filesystemScan . Flag ( "exclude-paths" , "Path to file with newline separated regexes for files to exclude in scan." ) . Short ( 'x' ) . String ( )
2022-04-03 18:51:56 +00:00
2023-09-11 15:18:48 +00:00
s3Scan = cli . Command ( "s3" , "Find credentials in S3 buckets." )
s3ScanKey = s3Scan . Flag ( "key" , "S3 key used to authenticate. Can be provided with environment variable AWS_ACCESS_KEY_ID." ) . Envar ( "AWS_ACCESS_KEY_ID" ) . String ( )
s3ScanRoleArns = s3Scan . Flag ( "role-arn" , "Specify the ARN of an IAM role to assume for scanning. You can repeat this flag." ) . Strings ( )
s3ScanSecret = s3Scan . Flag ( "secret" , "S3 secret used to authenticate. Can be provided with environment variable AWS_SECRET_ACCESS_KEY." ) . Envar ( "AWS_SECRET_ACCESS_KEY" ) . String ( )
s3ScanSessionToken = s3Scan . Flag ( "session-token" , "S3 session token used to authenticate temporary credentials. Can be provided with environment variable AWS_SESSION_TOKEN." ) . Envar ( "AWS_SESSION_TOKEN" ) . String ( )
2023-04-26 22:39:43 +00:00
s3ScanCloudEnv = s3Scan . Flag ( "cloud-environment" , "Use IAM credentials in cloud environment." ) . Bool ( )
2024-03-05 13:01:20 +00:00
s3ScanBuckets = s3Scan . Flag ( "bucket" , "Name of S3 bucket to scan. You can repeat this flag. Incompatible with --ignore-bucket." ) . Strings ( )
s3ScanIgnoreBuckets = s3Scan . Flag ( "ignore-bucket" , "Name of S3 bucket to ignore. You can repeat this flag. Incompatible with --bucket." ) . Strings ( )
2023-04-26 22:39:43 +00:00
s3ScanMaxObjectSize = s3Scan . Flag ( "max-object-size" , "Maximum size of objects to scan. Objects larger than this will be skipped. (Byte units eg. 512B, 2KB, 4MB)" ) . Default ( "250MB" ) . Bytes ( )
2022-05-04 22:08:11 +00:00
2023-03-08 01:32:04 +00:00
gcsScan = cli . Command ( "gcs" , "Find credentials in GCS buckets." )
2023-03-17 00:53:42 +00:00
gcsProjectID = gcsScan . Flag ( "project-id" , "GCS project ID used to authenticate. Can NOT be used with unauth scan. Can be provided with environment variable GOOGLE_CLOUD_PROJECT." ) . Envar ( "GOOGLE_CLOUD_PROJECT" ) . String ( )
2023-03-08 01:32:04 +00:00
gcsCloudEnv = gcsScan . Flag ( "cloud-environment" , "Use Application Default Credentials, IAM credentials to authenticate." ) . Bool ( )
gcsServiceAccount = gcsScan . Flag ( "service-account" , "Path to GCS service account JSON file." ) . ExistingFile ( )
gcsWithoutAuth = gcsScan . Flag ( "without-auth" , "Scan GCS buckets without authentication. This will only work for public buckets" ) . Bool ( )
gcsAPIKey = gcsScan . Flag ( "api-key" , "GCS API key used to authenticate. Can be provided with environment variable GOOGLE_API_KEY." ) . Envar ( "GOOGLE_API_KEY" ) . String ( )
2023-06-21 14:15:28 +00:00
gcsIncludeBuckets = gcsScan . Flag ( "include-buckets" , "Buckets to scan. Comma separated list of buckets. You can repeat this flag. Globs are supported" ) . Short ( 'I' ) . Strings ( )
2023-03-17 00:53:42 +00:00
gcsExcludeBuckets = gcsScan . Flag ( "exclude-buckets" , "Buckets to exclude from scan. Comma separated list of buckets. Globs are supported" ) . Short ( 'X' ) . Strings ( )
gcsIncludeObjects = gcsScan . Flag ( "include-objects" , "Objects to scan. Comma separated list of objects. you can repeat this flag. Globs are supported" ) . Short ( 'i' ) . Strings ( )
gcsExcludeObjects = gcsScan . Flag ( "exclude-objects" , "Objects to exclude from scan. Comma separated list of objects. You can repeat this flag. Globs are supported" ) . Short ( 'x' ) . Strings ( )
gcsMaxObjectSize = gcsScan . Flag ( "max-object-size" , "Maximum size of objects to scan. Objects larger than this will be skipped. (Byte units eg. 512B, 2KB, 4MB)" ) . Default ( "10MB" ) . Bytes ( )
2023-03-08 01:32:04 +00:00
2022-05-04 22:08:11 +00:00
syslogScan = cli . Command ( "syslog" , "Scan syslog" )
syslogAddress = syslogScan . Flag ( "address" , "Address and port to listen on for syslog. Example: 127.0.0.1:514" ) . String ( )
syslogProtocol = syslogScan . Flag ( "protocol" , "Protocol to listen on. udp or tcp" ) . String ( )
syslogTLSCert = syslogScan . Flag ( "cert" , "Path to TLS cert." ) . String ( )
syslogTLSKey = syslogScan . Flag ( "key" , "Path to TLS key." ) . String ( )
syslogFormat = syslogScan . Flag ( "format" , "Log format. Can be rfc3164 or rfc5424" ) . String ( )
2023-01-06 05:44:37 +00:00
circleCiScan = cli . Command ( "circleci" , "Scan CircleCI" )
circleCiScanToken = circleCiScan . Flag ( "token" , "CircleCI token. Can also be provided with environment variable" ) . Envar ( "CIRCLECI_TOKEN" ) . Required ( ) . String ( )
2023-06-22 15:02:25 +00:00
dockerScan = cli . Command ( "docker" , "Scan Docker Image" )
dockerScanImages = dockerScan . Flag ( "image" , "Docker image to scan. Use the file:// prefix to point to a local tarball, otherwise a image registry is assumed." ) . Required ( ) . Strings ( )
2024-05-14 18:30:11 +00:00
dockerScanToken = dockerScan . Flag ( "token" , "Docker bearer token. Can also be provided with environment variable" ) . Envar ( "DOCKER_TOKEN" ) . String ( )
2023-10-30 14:28:25 +00:00
travisCiScan = cli . Command ( "travisci" , "Scan TravisCI" )
travisCiScanToken = travisCiScan . Flag ( "token" , "TravisCI token. Can also be provided with environment variable" ) . Envar ( "TRAVISCI_TOKEN" ) . Required ( ) . String ( )
2024-03-20 16:36:20 +00:00
// Postman is hidden for now until we get more feedback from the community.
2024-05-10 17:30:08 +00:00
postmanScan = cli . Command ( "postman" , "Scan Postman" )
postmanToken = postmanScan . Flag ( "token" , "Postman token. Can also be provided with environment variable" ) . Envar ( "POSTMAN_TOKEN" ) . String ( )
postmanWorkspaces = postmanScan . Flag ( "workspace" , "Postman workspace to scan. You can repeat this flag. Deprecated flag." ) . Hidden ( ) . Strings ( )
postmanWorkspaceIDs = postmanScan . Flag ( "workspace-id" , "Postman workspace ID to scan. You can repeat this flag." ) . Strings ( )
postmanCollections = postmanScan . Flag ( "collection" , "Postman collection to scan. You can repeat this flag. Deprecated flag." ) . Hidden ( ) . Strings ( )
postmanCollectionIDs = postmanScan . Flag ( "collection-id" , "Postman collection ID to scan. You can repeat this flag." ) . Strings ( )
postmanEnvironments = postmanScan . Flag ( "environment" , "Postman environment to scan. You can repeat this flag." ) . Strings ( )
postmanIncludeCollections = postmanScan . Flag ( "include-collections" , "Collections to include in scan. You can repeat this flag. Deprecated flag." ) . Hidden ( ) . Strings ( )
postmanIncludeCollectionIDs = postmanScan . Flag ( "include-collection-id" , "Collection ID to include in scan. You can repeat this flag." ) . Strings ( )
2024-03-20 16:36:20 +00:00
postmanIncludeEnvironments = postmanScan . Flag ( "include-environments" , "Environments to include in scan. You can repeat this flag." ) . Strings ( )
2024-05-10 17:30:08 +00:00
postmanExcludeCollections = postmanScan . Flag ( "exclude-collections" , "Collections to exclude from scan. You can repeat this flag. Deprecated flag." ) . Hidden ( ) . Strings ( )
postmanExcludeCollectionIDs = postmanScan . Flag ( "exclude-collection-id" , "Collection ID to exclude from scan. You can repeat this flag." ) . Strings ( )
2024-03-20 16:36:20 +00:00
postmanExcludeEnvironments = postmanScan . Flag ( "exclude-environments" , "Environments to exclude from scan. You can repeat this flag." ) . Strings ( )
postmanWorkspacePaths = postmanScan . Flag ( "workspace-paths" , "Path to Postman workspaces." ) . Strings ( )
postmanCollectionPaths = postmanScan . Flag ( "collection-paths" , "Path to Postman collections." ) . Strings ( )
postmanEnvironmentPaths = postmanScan . Flag ( "environment-paths" , "Path to Postman environments." ) . Strings ( )
2024-05-24 14:38:20 +00:00
elasticsearchScan = cli . Command ( "elasticsearch" , "Scan Elasticsearch" )
elasticsearchNodes = elasticsearchScan . Flag ( "nodes" , "Elasticsearch nodes" ) . Envar ( "ELASTICSEARCH_NODES" ) . Strings ( )
elasticsearchUsername = elasticsearchScan . Flag ( "username" , "Elasticsearch username" ) . Envar ( "ELASTICSEARCH_USERNAME" ) . String ( )
elasticsearchPassword = elasticsearchScan . Flag ( "password" , "Elasticsearch password" ) . Envar ( "ELASTICSEARCH_PASSWORD" ) . String ( )
elasticsearchServiceToken = elasticsearchScan . Flag ( "service-token" , "Elasticsearch service token" ) . Envar ( "ELASTICSEARCH_SERVICE_TOKEN" ) . String ( )
elasticsearchCloudId = elasticsearchScan . Flag ( "cloud-id" , "Elasticsearch cloud ID. Can also be provided with environment variable" ) . Envar ( "ELASTICSEARCH_CLOUD_ID" ) . String ( )
elasticsearchAPIKey = elasticsearchScan . Flag ( "api-key" , "Elasticsearch API key. Can also be provided with environment variable" ) . Envar ( "ELASTICSEARCH_API_KEY" ) . String ( )
elasticsearchIndexPattern = elasticsearchScan . Flag ( "index-pattern" , "Filters the indices to search" ) . Default ( "*" ) . Envar ( "ELASTICSEARCH_INDEX_PATTERN" ) . String ( )
elasticsearchQueryJSON = elasticsearchScan . Flag ( "query-json" , "Filters the documents to search" ) . Envar ( "ELASTICSEARCH_QUERY_JSON" ) . String ( )
elasticsearchSinceTimestamp = elasticsearchScan . Flag ( "since-timestamp" , "Filters the documents to search to those created since this timestamp; overrides any timestamp from --query-json" ) . Envar ( "ELASTICSEARCH_SINCE_TIMESTAMP" ) . String ( )
elasticsearchBestEffortScan = elasticsearchScan . Flag ( "best-effort-scan" , "Attempts to continuously scan a cluster" ) . Envar ( "ELASTICSEARCH_BEST_EFFORT_SCAN" ) . Bool ( )
2024-06-04 11:13:14 +00:00
jenkinsScan = cli . Command ( "jenkins" , "Scan Jenkins" )
jenkinsURL = jenkinsScan . Flag ( "url" , "Jenkins URL" ) . Envar ( "JENKINS_URL" ) . Required ( ) . String ( )
jenkinsUsername = jenkinsScan . Flag ( "username" , "Jenkins username" ) . Envar ( "JENKINS_USERNAME" ) . String ( )
jenkinsPassword = jenkinsScan . Flag ( "password" , "Jenkins password" ) . Envar ( "JENKINS_PASSWORD" ) . String ( )
jenkinsInsecureSkipVerifyTLS = jenkinsScan . Flag ( "insecure-skip-verify-tls" , "Skip TLS verification" ) . Envar ( "JENKINS_INSECURE_SKIP_VERIFY_TLS" ) . Bool ( )
2024-06-05 17:07:50 +00:00
usingTUI = false
2022-04-03 18:51:56 +00:00
)
func init ( ) {
for i , arg := range os . Args {
if strings . HasPrefix ( arg , "--" ) {
2022-04-04 07:04:24 +00:00
split := strings . SplitN ( arg , "=" , 2 )
split [ 0 ] = strings . ReplaceAll ( split [ 0 ] , "_" , "-" )
os . Args [ i ] = strings . Join ( split , "=" )
2022-04-03 18:51:56 +00:00
}
}
2022-04-11 16:47:03 +00:00
cli . Version ( "trufflehog " + version . BuildVersion )
2023-08-09 20:13:55 +00:00
2023-11-16 21:59:53 +00:00
// Support -h for help
2023-10-18 13:57:05 +00:00
cli . HelpFlag . Short ( 'h' )
2023-08-09 20:13:55 +00:00
if len ( os . Args ) <= 1 && isatty . IsTerminal ( os . Stdout . Fd ( ) ) {
args := tui . Run ( )
if len ( args ) == 0 {
os . Exit ( 0 )
}
// Overwrite the Args slice so overseer works properly.
os . Args = os . Args [ : 1 ]
os . Args = append ( os . Args , args ... )
2024-06-05 17:07:50 +00:00
usingTUI = true
2023-08-09 20:13:55 +00:00
}
2022-04-03 18:51:56 +00:00
cmd = kingpin . MustParse ( cli . Parse ( os . Args [ 1 : ] ) )
2022-04-04 04:13:39 +00:00
2022-04-11 23:38:08 +00:00
switch {
case * trace :
2022-12-14 00:46:09 +00:00
log . SetLevel ( 5 )
2022-04-11 23:38:08 +00:00
case * debug :
2022-12-14 00:46:09 +00:00
log . SetLevel ( 2 )
2022-04-04 04:13:39 +00:00
}
2022-04-03 18:51:56 +00:00
}
2022-01-13 20:02:24 +00:00
func main ( ) {
2023-02-14 23:00:07 +00:00
// setup logger
logFormat := log . WithConsoleSink
if * jsonOut {
logFormat = log . WithJSONSink
}
logger , sync := log . New ( "trufflehog" , logFormat ( os . Stderr ) )
// make it the default logger for contexts
context . SetDefaultLogger ( logger )
2023-08-01 02:03:59 +00:00
if * localDev {
run ( overseer . State { } )
os . Exit ( 0 )
}
2023-02-14 23:00:07 +00:00
defer func ( ) { _ = sync ( ) } ( )
logFatal := logFatalFunc ( logger )
2022-04-03 18:51:56 +00:00
updateCfg := overseer . Config {
Program : run ,
Debug : * debug ,
RestartSignal : syscall . SIGTERM ,
// TODO: Eventually add a PreUpgrade func for signature check w/ x509 PKCS1v15
// PreUpgrade: checkUpdateSignature(binaryPath string),
}
if ! * noUpdate {
2024-06-05 17:07:50 +00:00
updateCfg . Fetcher = updater . Fetcher ( usingTUI )
2022-04-03 18:51:56 +00:00
}
2022-04-08 06:55:01 +00:00
if version . BuildVersion == "dev" {
updateCfg . Fetcher = nil
}
2022-04-03 18:51:56 +00:00
err := overseer . RunErr ( updateCfg )
if err != nil {
2023-06-21 14:15:28 +00:00
logFatal ( err , "error occurred with trufflehog updater 🐷" )
2022-04-03 18:51:56 +00:00
}
}
func run ( state overseer . State ) {
2023-12-22 15:41:54 +00:00
ctx , cancel := context . WithCancelCause ( context . Background ( ) )
defer cancel ( nil )
go func ( ) {
if err := cleantemp . CleanTempArtifacts ( ctx ) ; err != nil {
ctx . Logger ( ) . Error ( err , "error cleaning temporary artifacts" )
}
} ( )
2023-12-19 04:02:36 +00:00
2023-02-14 23:00:07 +00:00
logger := ctx . Logger ( )
logFatal := logFatalFunc ( logger )
2023-12-22 15:41:54 +00:00
killSignal := make ( chan os . Signal , 1 )
signal . Notify ( killSignal , syscall . SIGINT , syscall . SIGTERM , syscall . SIGQUIT )
go func ( ) {
<- killSignal
logger . Info ( "Received signal, shutting down." )
cancel ( fmt . Errorf ( "canceling context due to signal" ) )
if err := cleantemp . CleanTempArtifacts ( ctx ) ; err != nil {
logger . Error ( err , "error cleaning temporary artifacts" )
} else {
logger . Info ( "cleaned temporary artifacts" )
}
time . Sleep ( time . Second * 10 )
logger . Info ( "10 seconds elapsed. Forcing shutdown." )
os . Exit ( 0 )
} ( )
2023-02-14 23:00:07 +00:00
logger . V ( 2 ) . Info ( fmt . Sprintf ( "trufflehog %s" , version . BuildVersion ) )
2022-04-03 18:51:56 +00:00
2022-06-01 01:45:28 +00:00
if * githubScanToken != "" {
// NOTE: this kludge is here to do an authenticated shallow commit
// TODO: refactor to better pass credentials
os . Setenv ( "GITHUB_TOKEN" , * githubScanToken )
}
2022-02-23 15:40:18 +00:00
// When setting a base commit, chunks must be scanned in order.
if * gitScanSinceCommit != "" {
* concurrency = 1
}
2023-02-28 20:49:54 +00:00
if * profile {
2022-02-04 03:07:39 +00:00
go func ( ) {
2023-06-21 00:07:03 +00:00
router := http . NewServeMux ( )
2023-07-22 03:45:27 +00:00
router . Handle ( "/debug/pprof/" , http . DefaultServeMux )
2023-06-21 00:07:03 +00:00
router . Handle ( "/debug/fgprof" , fgprof . Handler ( ) )
2023-02-14 23:00:07 +00:00
logger . Info ( "starting pprof and fgprof server on :18066 /debug/pprof and /debug/fgprof" )
2022-02-07 18:29:06 +00:00
if err := http . ListenAndServe ( ":18066" , router ) ; err != nil {
2023-02-14 23:00:07 +00:00
logger . Error ( err , "error serving pprof and fgprof" )
2022-02-07 18:29:06 +00:00
}
2022-02-04 03:07:39 +00:00
} ( )
}
2022-12-20 16:14:49 +00:00
conf := & config . Config { }
if * configFilename != "" {
var err error
conf , err = config . Read ( * configFilename )
if err != nil {
2023-02-14 23:00:07 +00:00
logFatal ( err , "error parsing the provided configuration file" )
2022-12-20 16:14:49 +00:00
}
}
2023-02-07 23:25:14 +00:00
if * archiveMaxSize != 0 {
handlers . SetArchiveMaxSize ( int ( * archiveMaxSize ) )
}
if * archiveMaxDepth != 0 {
handlers . SetArchiveMaxDepth ( * archiveMaxDepth )
}
if * archiveTimeout != 0 {
handlers . SetArchiveMaxTimeout ( * archiveTimeout )
}
2023-07-31 18:12:08 +00:00
// Set how the engine will print its results.
var printer engine . Printer
switch {
case * jsonLegacy :
printer = new ( output . LegacyJSONPrinter )
case * jsonOut :
printer = new ( output . JSONPrinter )
case * gitHubActionsFormat :
printer = new ( output . GitHubActionsPrinter )
default :
printer = new ( output . PlainPrinter )
}
2023-09-11 15:18:48 +00:00
if ! * jsonLegacy && ! * jsonOut {
fmt . Fprintf ( os . Stderr , "🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷\n\n" )
}
2024-03-15 14:19:31 +00:00
// Parse --results flag.
if * onlyVerified {
r := "verified"
results = & r
}
parsedResults , err := parseResults ( results )
if err != nil {
logFatal ( err , "failed to configure results flag" )
}
2024-06-13 20:47:09 +00:00
engConf := engine . Config {
Concurrency : * concurrency ,
Detectors : conf . Detectors ,
Verify : ! * noVerification ,
IncludeDetectors : * includeDetectors ,
ExcludeDetectors : * excludeDetectors ,
CustomVerifiersOnly : * customVerifiersOnly ,
VerifierEndpoints : * verifiers ,
Dispatcher : engine . NewPrinterDispatcher ( printer ) ,
FilterUnverified : * filterUnverified ,
FilterEntropy : * filterEntropy ,
VerificationOverlap : * allowVerificationOverlap ,
Results : parsedResults ,
PrintAvgDetectorTime : * printAvgDetectorTime ,
ShouldScanEntireChunk : * scanEntireChunk ,
2024-06-05 20:28:19 +00:00
}
if * compareDetectionStrategies {
2024-06-13 20:47:09 +00:00
if err := compareScans ( ctx , cmd , engConf ) ; err != nil {
2024-06-05 20:28:19 +00:00
logFatal ( err , "error comparing detection strategies" )
}
return
}
2024-06-13 20:47:09 +00:00
metrics , err := runSingleScan ( ctx , cmd , engConf )
2024-06-05 20:28:19 +00:00
if err != nil {
logFatal ( err , "error running scan" )
}
// Print results.
logger . Info ( "finished scanning" ,
"chunks" , metrics . ChunksScanned ,
"bytes" , metrics . BytesScanned ,
"verified_secrets" , metrics . VerifiedSecretsFound ,
"unverified_secrets" , metrics . UnverifiedSecretsFound ,
"scan_duration" , metrics . ScanDuration . String ( ) ,
"trufflehog_version" , version . BuildVersion ,
)
if metrics . hasFoundResults && * fail {
logger . V ( 2 ) . Info ( "exiting with code 183 because results were found" )
os . Exit ( 183 )
}
}
2024-06-13 20:47:09 +00:00
func compareScans ( ctx context . Context , cmd string , cfg engine . Config ) error {
2024-06-05 20:28:19 +00:00
var (
entireMetrics metrics
maxLengthMetrics metrics
err error
)
var wg sync . WaitGroup
wg . Add ( 1 )
go func ( ) {
defer wg . Done ( )
// Run scan with entire chunk span calculator.
2024-06-13 20:47:09 +00:00
cfg . ShouldScanEntireChunk = true
entireMetrics , err = runSingleScan ( ctx , cmd , cfg )
2024-06-05 20:28:19 +00:00
if err != nil {
ctx . Logger ( ) . Error ( err , "error running scan with entire chunk span calculator" )
}
} ( )
// Run scan with max-length span calculator.
2024-06-13 20:47:09 +00:00
maxLengthMetrics , err = runSingleScan ( ctx , cmd , cfg )
2024-06-05 20:28:19 +00:00
if err != nil {
return fmt . Errorf ( "error running scan with custom span calculator: %v" , err )
}
wg . Wait ( )
return compareMetrics ( maxLengthMetrics . Metrics , entireMetrics . Metrics )
}
func compareMetrics ( customMetrics , entireMetrics engine . Metrics ) error {
fmt . Printf ( "Comparison of scan results: \n" )
fmt . Printf ( "Custom span - Chunks: %d, Bytes: %d, Verified Secrets: %d, Unverified Secrets: %d, Duration: %s\n" ,
customMetrics . ChunksScanned , customMetrics . BytesScanned , customMetrics . VerifiedSecretsFound , customMetrics . UnverifiedSecretsFound , customMetrics . ScanDuration . String ( ) )
fmt . Printf ( "Entire chunk - Chunks: %d, Bytes: %d, Verified Secrets: %d, Unverified Secrets: %d, Duration: %s\n" ,
entireMetrics . ChunksScanned , entireMetrics . BytesScanned , entireMetrics . VerifiedSecretsFound , entireMetrics . UnverifiedSecretsFound , entireMetrics . ScanDuration . String ( ) )
// Check for differences in scan metrics.
if customMetrics . ChunksScanned != entireMetrics . ChunksScanned ||
customMetrics . BytesScanned != entireMetrics . BytesScanned ||
customMetrics . VerifiedSecretsFound != entireMetrics . VerifiedSecretsFound {
return fmt . Errorf ( "scan metrics do not match" )
}
return nil
}
type metrics struct {
engine . Metrics
hasFoundResults bool
}
2024-06-13 20:47:09 +00:00
func runSingleScan ( ctx context . Context , cmd string , cfg engine . Config ) ( metrics , error ) {
var scanMetrics metrics
// Setup job report writer if provided
var jobReportWriter io . WriteCloser
if * jobReportFile != nil {
jobReportWriter = * jobReportFile
}
handleFinishedMetrics := func ( ctx context . Context , finishedMetrics <- chan sources . UnitMetrics , jobReportWriter io . WriteCloser ) {
go func ( ) {
defer func ( ) {
jobReportWriter . Close ( )
if namer , ok := jobReportWriter . ( interface { Name ( ) string } ) ; ok {
ctx . Logger ( ) . Info ( "report written" , "path" , namer . Name ( ) )
} else {
ctx . Logger ( ) . Info ( "report written" )
}
} ( )
for metrics := range finishedMetrics {
metrics . Errors = common . ExportErrors ( metrics . Errors ... )
details , err := json . Marshal ( map [ string ] any {
"version" : 1 ,
"data" : metrics ,
} )
if err != nil {
ctx . Logger ( ) . Error ( err , "error marshalling job details" )
continue
}
if _ , err := jobReportWriter . Write ( append ( details , '\n' ) ) ; err != nil {
ctx . Logger ( ) . Error ( err , "error writing to file" )
}
}
} ( )
}
const defaultOutputBufferSize = 64
opts := [ ] func ( * sources . SourceManager ) {
sources . WithConcurrentSources ( cfg . Concurrency ) ,
sources . WithConcurrentUnits ( cfg . Concurrency ) ,
sources . WithSourceUnits ( ) ,
sources . WithBufferedOutput ( defaultOutputBufferSize ) ,
}
if jobReportWriter != nil {
unitHook , finishedMetrics := sources . NewUnitHook ( ctx )
opts = append ( opts , sources . WithReportHook ( unitHook ) )
handleFinishedMetrics ( ctx , finishedMetrics , jobReportWriter )
}
cfg . SourceManager = sources . NewManager ( opts ... )
eng , err := engine . NewEngine ( ctx , & cfg )
2023-07-31 18:12:08 +00:00
if err != nil {
2024-06-13 20:47:09 +00:00
return scanMetrics , fmt . Errorf ( "error initializing engine: %v" , err )
2023-07-31 18:12:08 +00:00
}
2024-06-13 20:47:09 +00:00
eng . Start ( ctx )
2022-01-13 20:02:24 +00:00
2024-06-05 20:28:19 +00:00
defer func ( ) {
// Clean up temporary artifacts.
if err := cleantemp . CleanTempArtifacts ( ctx ) ; err != nil {
ctx . Logger ( ) . Error ( err , "error cleaning temp artifacts" )
}
} ( )
2024-06-13 20:47:09 +00:00
switch cmd {
2022-01-13 20:02:24 +00:00
case gitScan . FullCommand ( ) :
2024-06-05 20:28:19 +00:00
gitCfg := sources . GitConfig {
2023-11-16 21:59:53 +00:00
URI : * gitScanURI ,
IncludePathsFile : * gitScanIncludePaths ,
ExcludePathsFile : * gitScanExcludePaths ,
HeadRef : * gitScanBranch ,
BaseRef : * gitScanSinceCommit ,
MaxDepth : * gitScanMaxDepth ,
Bare : * gitScanBare ,
ExcludeGlobs : * gitScanExcludeGlobs ,
2022-08-10 17:11:13 +00:00
}
2024-06-05 20:28:19 +00:00
if err = eng . ScanGit ( ctx , gitCfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan Git: %v" , err )
2022-01-13 20:02:24 +00:00
}
case githubScan . FullCommand ( ) :
2023-02-14 16:40:53 +00:00
filter , err := common . FilterFromFiles ( * githubScanIncludePaths , * githubScanExcludePaths )
if err != nil {
2024-06-05 20:28:19 +00:00
return scanMetrics , fmt . Errorf ( "could not create filter: %v" , err )
2023-02-14 16:40:53 +00:00
}
2022-01-20 00:13:59 +00:00
if len ( * githubScanOrgs ) == 0 && len ( * githubScanRepos ) == 0 {
2024-06-05 20:28:19 +00:00
return scanMetrics , fmt . Errorf ( "invalid config: you must specify at least one organization or repository" )
2022-01-20 00:13:59 +00:00
}
2022-08-10 17:11:13 +00:00
2023-02-10 20:43:00 +00:00
cfg := sources . GithubConfig {
2023-08-16 22:23:59 +00:00
Endpoint : * githubScanEndpoint ,
Token : * githubScanToken ,
IncludeForks : * githubIncludeForks ,
IncludeMembers : * githubIncludeMembers ,
2024-01-31 15:52:24 +00:00
IncludeWikis : * githubIncludeWikis ,
2023-08-16 22:23:59 +00:00
Concurrency : * concurrency ,
ExcludeRepos : * githubExcludeRepos ,
IncludeRepos : * githubIncludeRepos ,
Repos : * githubScanRepos ,
Orgs : * githubScanOrgs ,
IncludeIssueComments : * githubScanIssueComments ,
IncludePullRequestComments : * githubScanPRComments ,
IncludeGistComments : * githubScanGistComments ,
Filter : filter ,
2022-08-10 17:11:13 +00:00
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanGitHub ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan Github: %v" , err )
2022-01-20 00:13:59 +00:00
}
2022-01-13 20:02:24 +00:00
case gitlabScan . FullCommand ( ) :
2022-11-15 21:02:37 +00:00
filter , err := common . FilterFromFiles ( * gitlabScanIncludePaths , * gitlabScanExcludePaths )
if err != nil {
2024-06-05 20:28:19 +00:00
return scanMetrics , fmt . Errorf ( "could not create filter: %v" , err )
2022-11-15 21:02:37 +00:00
}
2023-02-10 20:43:00 +00:00
cfg := sources . GitlabConfig {
Endpoint : * gitlabScanEndpoint ,
Token : * gitlabScanToken ,
Repos : * gitlabScanRepos ,
Filter : filter ,
2022-08-10 17:11:13 +00:00
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanGitLab ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan GitLab: %v" , err )
2022-03-15 00:05:15 +00:00
}
2022-01-20 00:13:59 +00:00
case filesystemScan . FullCommand ( ) :
2023-02-27 18:15:05 +00:00
if len ( * filesystemDirectories ) > 0 {
ctx . Logger ( ) . Info ( "--directory flag is deprecated, please pass directories as arguments" )
}
paths := make ( [ ] string , 0 , len ( * filesystemPaths ) + len ( * filesystemDirectories ) )
paths = append ( paths , * filesystemPaths ... )
paths = append ( paths , * filesystemDirectories ... )
2023-02-10 20:43:00 +00:00
cfg := sources . FilesystemConfig {
2024-01-11 23:41:50 +00:00
Paths : paths ,
IncludePathsFile : * filesystemScanIncludePaths ,
ExcludePathsFile : * filesystemScanExcludePaths ,
2022-08-10 17:11:13 +00:00
}
2024-06-05 20:28:19 +00:00
if err = eng . ScanFileSystem ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan filesystem: %v" , err )
2022-03-15 00:04:19 +00:00
}
2022-01-20 00:13:59 +00:00
case s3Scan . FullCommand ( ) :
2023-02-10 20:43:00 +00:00
cfg := sources . S3Config {
2023-04-26 22:39:43 +00:00
Key : * s3ScanKey ,
Secret : * s3ScanSecret ,
SessionToken : * s3ScanSessionToken ,
Buckets : * s3ScanBuckets ,
2024-03-05 13:01:20 +00:00
IgnoreBuckets : * s3ScanIgnoreBuckets ,
2023-09-11 15:18:48 +00:00
Roles : * s3ScanRoleArns ,
2023-04-26 22:39:43 +00:00
CloudCred : * s3ScanCloudEnv ,
MaxObjectSize : int64 ( * s3ScanMaxObjectSize ) ,
2022-08-10 17:11:13 +00:00
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanS3 ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan S3: %v" , err )
2022-03-15 00:07:07 +00:00
}
2022-05-04 22:08:11 +00:00
case syslogScan . FullCommand ( ) :
2023-02-10 20:43:00 +00:00
cfg := sources . SyslogConfig {
Address : * syslogAddress ,
Format : * syslogFormat ,
Protocol : * syslogProtocol ,
CertPath : * syslogTLSCert ,
KeyPath : * syslogTLSKey ,
Concurrency : * concurrency ,
2022-08-10 17:11:13 +00:00
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanSyslog ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan syslog: %v" , err )
2022-05-04 22:08:11 +00:00
}
2023-01-06 05:44:37 +00:00
case circleCiScan . FullCommand ( ) :
2024-06-05 20:28:19 +00:00
if err := eng . ScanCircleCI ( ctx , * circleCiScanToken ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan CircleCI: %v" , err )
2023-01-06 05:44:37 +00:00
}
2023-10-30 14:28:25 +00:00
case travisCiScan . FullCommand ( ) :
2024-06-05 20:28:19 +00:00
if err := eng . ScanTravisCI ( ctx , * travisCiScanToken ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan TravisCI: %v" , err )
2023-10-30 14:28:25 +00:00
}
2023-03-08 01:32:04 +00:00
case gcsScan . FullCommand ( ) :
cfg := sources . GCSConfig {
ProjectID : * gcsProjectID ,
CloudCred : * gcsCloudEnv ,
ServiceAccount : * gcsServiceAccount ,
WithoutAuth : * gcsWithoutAuth ,
ApiKey : * gcsAPIKey ,
2023-06-21 14:15:28 +00:00
IncludeBuckets : commaSeparatedToSlice ( * gcsIncludeBuckets ) ,
ExcludeBuckets : commaSeparatedToSlice ( * gcsExcludeBuckets ) ,
IncludeObjects : commaSeparatedToSlice ( * gcsIncludeObjects ) ,
ExcludeObjects : commaSeparatedToSlice ( * gcsExcludeObjects ) ,
2023-03-08 01:32:04 +00:00
Concurrency : * concurrency ,
2023-03-17 00:53:42 +00:00
MaxObjectSize : int64 ( * gcsMaxObjectSize ) ,
2023-03-08 01:32:04 +00:00
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanGCS ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan GCS: %v" , err )
2023-03-08 01:32:04 +00:00
}
2023-06-22 15:02:25 +00:00
case dockerScan . FullCommand ( ) :
2024-05-14 18:30:11 +00:00
cfg := sources . DockerConfig {
BearerToken : * dockerScanToken ,
Images : * dockerScanImages ,
UseDockerKeychain : * dockerScanToken == "" ,
2023-06-22 15:02:25 +00:00
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanDocker ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan Docker: %v" , err )
2023-06-22 15:02:25 +00:00
}
2024-03-20 16:36:20 +00:00
case postmanScan . FullCommand ( ) :
2024-05-10 17:30:08 +00:00
// handle deprecated flag
workspaceIDs := make ( [ ] string , 0 , len ( * postmanWorkspaceIDs ) + len ( * postmanWorkspaces ) )
workspaceIDs = append ( workspaceIDs , * postmanWorkspaceIDs ... )
workspaceIDs = append ( workspaceIDs , * postmanWorkspaces ... )
// handle deprecated flag
collectionIDs := make ( [ ] string , 0 , len ( * postmanCollectionIDs ) + len ( * postmanCollections ) )
collectionIDs = append ( collectionIDs , * postmanCollectionIDs ... )
collectionIDs = append ( collectionIDs , * postmanCollections ... )
// handle deprecated flag
includeCollectionIDs := make ( [ ] string , 0 , len ( * postmanIncludeCollectionIDs ) + len ( * postmanIncludeCollections ) )
includeCollectionIDs = append ( includeCollectionIDs , * postmanIncludeCollectionIDs ... )
includeCollectionIDs = append ( includeCollectionIDs , * postmanIncludeCollections ... )
// handle deprecated flag
excludeCollectionIDs := make ( [ ] string , 0 , len ( * postmanExcludeCollectionIDs ) + len ( * postmanExcludeCollections ) )
excludeCollectionIDs = append ( excludeCollectionIDs , * postmanExcludeCollectionIDs ... )
excludeCollectionIDs = append ( excludeCollectionIDs , * postmanExcludeCollections ... )
2024-03-20 16:36:20 +00:00
cfg := sources . PostmanConfig {
Token : * postmanToken ,
2024-05-10 17:30:08 +00:00
Workspaces : workspaceIDs ,
Collections : collectionIDs ,
2024-03-20 16:36:20 +00:00
Environments : * postmanEnvironments ,
2024-05-10 17:30:08 +00:00
IncludeCollections : includeCollectionIDs ,
2024-03-20 16:36:20 +00:00
IncludeEnvironments : * postmanIncludeEnvironments ,
2024-05-10 17:30:08 +00:00
ExcludeCollections : excludeCollectionIDs ,
2024-03-20 16:36:20 +00:00
ExcludeEnvironments : * postmanExcludeEnvironments ,
CollectionPaths : * postmanCollectionPaths ,
WorkspacePaths : * postmanWorkspacePaths ,
EnvironmentPaths : * postmanEnvironmentPaths ,
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanPostman ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan Postman: %v" , err )
2024-03-20 16:36:20 +00:00
}
2024-05-24 14:38:20 +00:00
case elasticsearchScan . FullCommand ( ) :
cfg := sources . ElasticsearchConfig {
Nodes : * elasticsearchNodes ,
Username : * elasticsearchUsername ,
Password : * elasticsearchPassword ,
CloudID : * elasticsearchCloudId ,
APIKey : * elasticsearchAPIKey ,
ServiceToken : * elasticsearchServiceToken ,
IndexPattern : * elasticsearchIndexPattern ,
QueryJSON : * elasticsearchQueryJSON ,
SinceTimestamp : * elasticsearchSinceTimestamp ,
BestEffortScan : * elasticsearchBestEffortScan ,
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanElasticsearch ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan Elasticsearch: %v" , err )
2024-05-24 14:38:20 +00:00
}
2024-06-04 11:13:14 +00:00
case jenkinsScan . FullCommand ( ) :
cfg := engine . JenkinsConfig {
Endpoint : * jenkinsURL ,
InsecureSkipVerifyTLS : * jenkinsInsecureSkipVerifyTLS ,
Username : * jenkinsUsername ,
Password : * jenkinsPassword ,
}
2024-06-05 20:28:19 +00:00
if err := eng . ScanJenkins ( ctx , cfg ) ; err != nil {
return scanMetrics , fmt . Errorf ( "failed to scan Jenkins: %v" , err )
2024-06-04 11:13:14 +00:00
}
2024-05-08 20:58:50 +00:00
default :
2024-06-13 20:47:09 +00:00
return scanMetrics , fmt . Errorf ( "invalid command: %s" , cmd )
2022-01-13 20:02:24 +00:00
}
2023-07-31 18:12:08 +00:00
// Wait for all workers to finish.
2024-06-05 20:28:19 +00:00
if err = eng . Finish ( ctx ) ; err != nil {
return scanMetrics , fmt . Errorf ( "engine failed to finish execution: %v" , err )
2024-02-17 16:06:24 +00:00
}
2022-02-07 18:29:06 +00:00
if * printAvgDetectorTime {
2024-06-05 20:28:19 +00:00
printAverageDetectorTime ( eng )
2022-02-07 18:29:06 +00:00
}
2022-03-01 04:38:13 +00:00
2024-06-05 20:28:19 +00:00
return metrics { Metrics : eng . GetMetrics ( ) , hasFoundResults : eng . HasFoundResults ( ) } , nil
2022-02-07 18:29:06 +00:00
}
2024-03-15 14:19:31 +00:00
// parseResults ensures that users provide valid CSV input to `--results`.
//
// This is a work-around to kingpin not supporting CSVs.
// See: https://github.com/trufflesecurity/trufflehog/pull/2372#issuecomment-1983868917
func parseResults ( input * string ) ( map [ string ] struct { } , error ) {
if * input == "" {
return nil , nil
}
var (
values = strings . Split ( strings . ToLower ( * input ) , "," )
results = make ( map [ string ] struct { } , 3 )
)
for _ , value := range values {
switch value {
2024-04-22 22:18:04 +00:00
case "verified" , "unknown" , "unverified" , "filtered_unverified" :
2024-03-15 14:19:31 +00:00
results [ value ] = struct { } { }
default :
2024-04-22 22:18:04 +00:00
return nil , fmt . Errorf ( "invalid value '%s', valid values are 'verified,unknown,unverified,filtered_unverified'" , value )
2024-03-15 14:19:31 +00:00
}
}
return results , nil
}
2023-07-31 18:12:08 +00:00
// logFatalFunc returns a log.Fatal style function. Calling the returned
// function will terminate the program without cleanup.
func logFatalFunc ( logger logr . Logger ) func ( error , string , ... any ) {
return func ( err error , message string , keyAndVals ... any ) {
logger . Error ( err , message , keyAndVals ... )
if err != nil {
os . Exit ( 1 )
return
}
os . Exit ( 0 )
}
}
2023-06-21 14:15:28 +00:00
func commaSeparatedToSlice ( s [ ] string ) [ ] string {
2023-03-17 00:53:42 +00:00
var result [ ] string
for _ , items := range s {
for _ , item := range strings . Split ( items , "," ) {
item = strings . TrimSpace ( item )
if item == "" {
continue
}
result = append ( result , item )
}
}
return result
}
2022-02-07 18:29:06 +00:00
func printAverageDetectorTime ( e * engine . Engine ) {
2024-05-08 20:58:50 +00:00
fmt . Fprintln (
os . Stderr ,
"Average detector time is the measurement of average time spent on each detector when results are returned." ,
)
2023-07-31 18:12:08 +00:00
for detectorName , duration := range e . GetDetectorsMetrics ( ) {
fmt . Fprintf ( os . Stderr , "%s: %s\n" , detectorName , duration )
2023-02-14 23:00:07 +00:00
}
}