Skip to content

Commit

Permalink
Add Jenkins scanning (#2892)
Browse files Browse the repository at this point in the history
* add jenkins

* whoops

* adding unauthenticated jenkins scanning

* update docs

---------

Co-authored-by: Joe Leon <joe.leon@trufflesec.com>
  • Loading branch information
dustin-decker and joeleonjr committed Jun 4, 2024
1 parent c86b423 commit ef41087
Show file tree
Hide file tree
Showing 15 changed files with 1,426 additions and 347 deletions.
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

---

# :mag_right: *Now Scanning*
# :mag_right: _Now Scanning_

<div align="center">

Expand Down Expand Up @@ -267,6 +267,40 @@ Use the `--workspace-id`, `--collection-id`, `--environment` flags multiple time
trufflehog postman --token=<postman api token> --workspace-id=<workspace id>
```

## 13: Scan a Jenkins server

```bash
trufflehog jenkins --url https://jenkins.example.com --username admin --password admin
```

## 14: Scan an Elasticsearch server

### Scan a Local Cluster

There are two ways to authenticate to a local cluster with TruffleHog: (1) username and password, (2) service token.

#### Connect to a local cluster with username and password

```bash
trufflehog elasticsearch --nodes 192.168.14.3 192.168.14.4 --username truffle --password hog
```

#### Connect to a local cluster with a service token

```bash
trufflehog elasticsearch --nodes 192.168.14.3 192.168.14.4 --service-token ‘AAEWVaWM...Rva2VuaSDZ’
```

### Scan an Elastic Cloud Cluster

To scan a cluster on Elastic Cloud, you’ll need a Cloud ID and API key.

```bash
trufflehog elasticsearch \
--cloud-id 'search-prod:dXMtY2Vx...YjM1ODNlOWFiZGRlNjI0NA==' \
--api-key 'MlVtVjBZ...ZSYlduYnF1djh3NG5FQQ=='
```

# :question: FAQ

- All I see is `🐷🔑🐷 TruffleHog. Unearth your secrets. 🐷🔑🐷` and the program exits, what gives?
Expand Down Expand Up @@ -307,6 +341,8 @@ TruffleHog has a sub-command for each source of data that you may want to scan:
- travisci
- gcs (Google Cloud Storage)
- postman
- jenkins
- elasticsearch

Each subcommand can have options that you can see with the `--help` flag provided to the sub command:

Expand Down Expand Up @@ -672,4 +708,3 @@ the stability of the public APIs at this time.
# License Change

Since v3.0, TruffleHog is released under a AGPL 3 license, included in [`LICENSE`](LICENSE). TruffleHog v3.0 uses none of the previous codebase, but care was taken to preserve backwards compatibility on the command line interface. The work previous to this release is still available licensed under GPL 2.0 in the history of this repository and the previous package releases and tags. A completed CLA is required for us to accept contributions going forward.

203 changes: 105 additions & 98 deletions assets/scanning_logos.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ var (
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()

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()
)

func init() {
Expand Down Expand Up @@ -661,6 +667,16 @@ func run(state overseer.State) {
if err := e.ScanElasticsearch(ctx, cfg); err != nil {
logFatal(err, "Failed to scan Elasticsearch.")
}
case jenkinsScan.FullCommand():
cfg := engine.JenkinsConfig{
Endpoint: *jenkinsURL,
InsecureSkipVerifyTLS: *jenkinsInsecureSkipVerifyTLS,
Username: *jenkinsUsername,
Password: *jenkinsPassword,
}
if err := e.ScanJenkins(ctx, cfg); err != nil {
logFatal(err, "Failed to scan Jenkins.")
}
default:
logFatal(fmt.Errorf("invalid command"), "Command not recognized.")
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/detectors/privatekey/privatekey_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ func Test_lookupFingerprint(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotFingerprints, err := lookupFingerprint(tt.publicKeyFingerprintInHex, tt.includeExpired)
gotFingerprints, err := lookupFingerprint(context.TODO(), tt.publicKeyFingerprintInHex, tt.includeExpired)
if (err != nil) != tt.wantErr {
t.Errorf("lookupFingerprint() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down
81 changes: 81 additions & 0 deletions pkg/engine/jenkins.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package engine

import (
"errors"
"runtime"
"strings"

"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"

"github.com/trufflesecurity/trufflehog/v3/pkg/context"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/credentialspb"
"github.com/trufflesecurity/trufflehog/v3/pkg/pb/sourcespb"
"github.com/trufflesecurity/trufflehog/v3/pkg/sources/jenkins"
)

type JenkinsConfig struct {
Endpoint string
Username string
Password string
Header string
InsecureSkipVerifyTLS bool
}

// ScanJenkins scans Jenkins logs.
func (e *Engine) ScanJenkins(ctx context.Context, jenkinsConfig JenkinsConfig) error {
var connection *sourcespb.Jenkins
switch {
case jenkinsConfig.Username != "" && jenkinsConfig.Password != "":
connection = &sourcespb.Jenkins{
Credential: &sourcespb.Jenkins_BasicAuth{
BasicAuth: &credentialspb.BasicAuth{
Username: jenkinsConfig.Username,
Password: jenkinsConfig.Password,
},
},
}
case jenkinsConfig.Header != "":
splits := strings.Split(jenkinsConfig.Header, ":")
if len(splits) != 2 {
return errors.New("invalid header format, expected key: value")
}
key := splits[0]
value := splits[1]

connection = &sourcespb.Jenkins{
Credential: &sourcespb.Jenkins_Header{
Header: &credentialspb.Header{
Key: key,
Value: value,
},
},
}
default:
connection = &sourcespb.Jenkins{
Credential: &sourcespb.Jenkins_Unauthenticated{
Unauthenticated: &credentialspb.Unauthenticated{},
},
}
}

connection.Endpoint = jenkinsConfig.Endpoint
connection.InsecureSkipVerifyTls = jenkinsConfig.InsecureSkipVerifyTLS

var conn anypb.Any
err := anypb.MarshalFrom(&conn, connection, proto.MarshalOptions{})
if err != nil {
ctx.Logger().Error(err, "failed to marshal Jenkins connection")
return err
}

sourceName := "trufflehog - Jenkins"
sourceID, jobID, _ := e.sourceManager.GetIDs(ctx, sourceName, jenkins.SourceType)

jenkinsSource := &jenkins.Source{}
if err := jenkinsSource.Init(ctx, "trufflehog - Jenkins", jobID, sourceID, true, &conn, runtime.NumCPU()); err != nil {
return err
}
_, err = e.sourceManager.Run(ctx, sourceName, jenkinsSource)
return err
}
4 changes: 2 additions & 2 deletions pkg/pb/credentialspb/credentials.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/pb/custom_detectorspb/custom_detectors.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/pb/detectorspb/detectors.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/pb/source_metadatapb/source_metadata.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit ef41087

Please sign in to comment.