From b560a7c0bb06df5c3e3b01973ee07355d7483dec Mon Sep 17 00:00:00 2001 From: Brad Rydzewski Date: Fri, 5 Nov 2021 21:38:28 -0400 Subject: [PATCH] initial commit --- .drone.yml | 21 ++++ .gitignore | 3 + .gitleaks.toml | 174 ++++++++++++++++++++++++++++++++++ LICENSE.md | 55 +++++++++++ README.md | 30 ++++++ docker/Dockerfile | 15 +++ docker/Dockerfile.linux.arm | 10 ++ docker/Dockerfile.linux.arm64 | 10 ++ docker/manifest.tmpl | 31 ++++++ go.mod | 10 ++ go.sum | 13 +++ main.go | 50 ++++++++++ plugin/pipeline.go | 144 ++++++++++++++++++++++++++++ plugin/plugin.go | 66 +++++++++++++ plugin/plugin_test.go | 11 +++ plugin/types.go | 23 +++++ scripts/build.sh | 18 ++++ scripts/upgrade.sh | 3 + 18 files changed, 687 insertions(+) create mode 100644 .drone.yml create mode 100644 .gitignore create mode 100644 .gitleaks.toml create mode 100644 LICENSE.md create mode 100644 README.md create mode 100644 docker/Dockerfile create mode 100644 docker/Dockerfile.linux.arm create mode 100644 docker/Dockerfile.linux.arm64 create mode 100644 docker/manifest.tmpl create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100644 plugin/pipeline.go create mode 100644 plugin/plugin.go create mode 100644 plugin/plugin_test.go create mode 100644 plugin/types.go create mode 100755 scripts/build.sh create mode 100755 scripts/upgrade.sh diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..9ffbf74 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,21 @@ +kind: pipeline +type: docker +name: default + +steps: +- name: build + image: golang:1.16 + commands: + - go build + - go test ./... + +- name: publish + image: plugins/docker + settings: + repo: plugins/gitleaks + auto_tag: true + dockerfile: docker/Dockerfile + username: + from_secret: docker_username + password: + from_secret: docker_password diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eae0aaf --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.env +release/ +drone-gitleaks diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..cbcabff --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,174 @@ +title = "gitleaks config" + +[[rules]] + description = "AWS Access Key" + regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' + tags = ["key", "AWS"] + +[[rules]] + description = "AWS Secret Key" + regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}''' + tags = ["key", "AWS"] + +[[rules]] + description = "AWS MWS key" + regex = '''amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}''' + tags = ["key", "AWS", "MWS"] + +[[rules]] + description = "Facebook Secret Key" + regex = '''(?i)(facebook|fb)(.{0,20})?(?-i)['\"][0-9a-f]{32}['\"]''' + tags = ["key", "Facebook"] + +[[rules]] + description = "Facebook Client ID" + regex = '''(?i)(facebook|fb)(.{0,20})?['\"][0-9]{13,17}['\"]''' + tags = ["key", "Facebook"] + +[[rules]] + description = "Twitter Secret Key" + regex = '''(?i)twitter(.{0,20})?['\"][0-9a-z]{35,44}['\"]''' + tags = ["key", "Twitter"] + +[[rules]] + description = "Twitter Client ID" + regex = '''(?i)twitter(.{0,20})?['\"][0-9a-z]{18,25}['\"]''' + tags = ["client", "Twitter"] + +[[rules]] + description = "Github Personal Access Token" + regex = '''ghp_[0-9a-zA-Z]{36}''' + tags = ["key", "Github"] +[[rules]] + description = "Github OAuth Access Token" + regex = '''gho_[0-9a-zA-Z]{36}''' + tags = ["key", "Github"] +[[rules]] + description = "Github App Token" + regex = '''(ghu|ghs)_[0-9a-zA-Z]{36}''' + tags = ["key", "Github"] +[[rules]] + description = "Github Refresh Token" + regex = '''ghr_[0-9a-zA-Z]{76}''' + tags = ["key", "Github"] + +[[rules]] + description = "LinkedIn Client ID" + regex = '''(?i)linkedin(.{0,20})?(?-i)[0-9a-z]{12}''' + tags = ["client", "LinkedIn"] + +[[rules]] + description = "LinkedIn Secret Key" + regex = '''(?i)linkedin(.{0,20})?[0-9a-z]{16}''' + tags = ["secret", "LinkedIn"] + +[[rules]] + description = "Slack" + regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})?''' + tags = ["key", "Slack"] + +[[rules]] + description = "Asymmetric Private Key" + regex = '''-----BEGIN ((EC|PGP|DSA|RSA|OPENSSH) )?PRIVATE KEY( BLOCK)?-----''' + tags = ["key", "AsymmetricPrivateKey"] + +[[rules]] + description = "Google API key" + regex = '''AIza[0-9A-Za-z\-_]{35}''' + tags = ["key", "Google"] + +[[rules]] + description = "Google (GCP) Service Account" + regex = '''"type": "service_account"''' + tags = ["key", "Google"] + +[[rules]] + description = "Heroku API key" + regex = '''(?i)heroku(.{0,20})?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}''' + tags = ["key", "Heroku"] + +[[rules]] + description = "MailChimp API key" + regex = '''(?i)(mailchimp|mc)(.{0,20})?[0-9a-f]{32}-us[0-9]{1,2}''' + tags = ["key", "Mailchimp"] + +[[rules]] + description = "Mailgun API key" + regex = '''((?i)(mailgun|mg)(.{0,20})?)?key-[0-9a-z]{32}''' + tags = ["key", "Mailgun"] + +[[rules]] + description = "PayPal Braintree access token" + regex = '''access_token\$production\$[0-9a-z]{16}\$[0-9a-f]{32}''' + tags = ["key", "Paypal"] + +[[rules]] + description = "Picatic API key" + regex = '''sk_live_[0-9a-z]{32}''' + tags = ["key", "Picatic"] + +[[rules]] + description = "SendGrid API Key" + regex = '''SG\.[\w_]{16,32}\.[\w_]{16,64}''' + tags = ["key", "SendGrid"] + +[[rules]] + description = "Slack Webhook" + regex = '''https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}''' + tags = ["key", "slack"] + +[[rules]] + description = "Stripe API key" + regex = '''(?i)stripe(.{0,20})?[sr]k_live_[0-9a-zA-Z]{24}''' + tags = ["key", "Stripe"] + +[[rules]] + description = "Square access token" + regex = '''sq0atp-[0-9A-Za-z\-_]{22}''' + tags = ["key", "square"] + +[[rules]] + description = "Square OAuth secret" + regex = '''sq0csp-[0-9A-Za-z\-_]{43}''' + tags = ["key", "square"] + +[[rules]] + description = "Twilio API key" + regex = '''(?i)twilio(.{0,20})?SK[0-9a-f]{32}''' + tags = ["key", "twilio"] + +[[rules]] + description = "Dynatrace ttoken" + regex = '''dt0[a-zA-Z]{1}[0-9]{2}\.[A-Z0-9]{24}\.[A-Z0-9]{64}''' + tags = ["key", "Dynatrace"] + +[[rules]] + description = "Shopify shared secret" + regex = '''shpss_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + description = "Shopify access token" + regex = '''shpat_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + description = "Shopify custom app access token" + regex = '''shpca_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + description = "Shopify private app access token" + regex = '''shppa_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + description = "PyPI upload token" + regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9-_]{50,1000}''' + tags = ["key", "pypi"] + +[allowlist] + description = "Allowlisted files" + files = ['''^\.?gitleaks.toml$''', + '''(.*?)(png|jpg|gif|doc|docx|pdf|bin|xls|pyc|zip)$''', + '''(go.mod|go.sum)$'''] diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c5402b9 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,55 @@ +# Blue Oak Model License + +Version 1.0.0 + +## Purpose + +This license gives everyone as much permission to work with +this software as possible, while protecting contributors +from liability. + +## Acceptance + +In order to receive this license, you must agree to its +rules. The rules of this license are both obligations +under that agreement and conditions to your license. +You must not do anything with this software that triggers +a rule that you cannot or will not follow. + +## Copyright + +Each contributor licenses you to do everything with this +software that would otherwise infringe that contributor's +copyright in it. + +## Notices + +You must ensure that everyone who gets a copy of +any part of this software from you, with or without +changes, also gets the text of this license or a link to +. + +## Excuse + +If anyone notifies you in writing that you have not +complied with [Notices](#notices), you can keep your +license by taking all practical steps to comply within 30 +days after the notice. If you do not do so, your license +ends immediately. + +## Patent + +Each contributor licenses you to do everything with this +software that would otherwise infringe any patent claims +they can license or become able to license. + +## Reliability + +No contributor can revoke this license. + +## No Liability + +***As far as the law allows, this software comes as is, +without any warranty or condition, and no contributor +will be liable to anyone for any damages related to this +software or this license, under any kind of legal claim.*** diff --git a/README.md b/README.md new file mode 100644 index 0000000..c16d3d2 --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +A plugin to detect hard-coded secrets and sensitive data in your source code files. + +# Building + +Build the plugin binary: + +```text +scripts/build.sh +``` + +Build the plugin image: + +```text +docker build -t plugins/gitleaks -f docker/Dockerfile . +``` + +# Testing + +Execute the plugin from your current working directory: + +```text +docker run --rm \ + -e DRONE_COMMIT_SHA=8f51ad7884c5eb69c11d260a31da7a745e6b78e2 \ + -e DRONE_COMMIT_BRANCH=master \ + -e DRONE_BUILD_NUMBER=43 \ + -e DRONE_BUILD_STATUS=success \ + -w /drone/src \ + -v $(pwd):/drone/src \ + plugins/gitleaks +``` \ No newline at end of file diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..3f34638 --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,15 @@ +FROM alpine:3 as alpine +RUN apk add -U --no-cache ca-certificates + +FROM alpine:3 +ENV GODEBUG netdns=go + +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +RUN wget https://github.com/zricethezav/gitleaks/releases/download/v7.6.1/gitleaks-linux-amd64 +RUN mv gitleaks-linux-amd64 /bin/gitleaks +RUN chmod +x /bin/gitleaks + +RUN apk add --no-cache bash git openssh-client +ADD release/linux/amd64/plugin /bin/ +ENTRYPOINT ["/bin/plugin"] \ No newline at end of file diff --git a/docker/Dockerfile.linux.arm b/docker/Dockerfile.linux.arm new file mode 100644 index 0000000..993c2e9 --- /dev/null +++ b/docker/Dockerfile.linux.arm @@ -0,0 +1,10 @@ +FROM alpine:3.6 as alpine +RUN apk add -U --no-cache ca-certificates + +FROM alpine:3.6 +ENV GODEBUG netdns=go + +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +ADD release/linux/arm/plugin /bin/ +ENTRYPOINT ["/bin/plugin"] \ No newline at end of file diff --git a/docker/Dockerfile.linux.arm64 b/docker/Dockerfile.linux.arm64 new file mode 100644 index 0000000..1223423 --- /dev/null +++ b/docker/Dockerfile.linux.arm64 @@ -0,0 +1,10 @@ +FROM alpine:3.6 as alpine +RUN apk add -U --no-cache ca-certificates + +FROM alpine:3.6 +ENV GODEBUG netdns=go + +COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ + +ADD release/linux/arm64/plugin /bin/ +ENTRYPOINT ["/bin/plugin"] \ No newline at end of file diff --git a/docker/manifest.tmpl b/docker/manifest.tmpl new file mode 100644 index 0000000..8054538 --- /dev/null +++ b/docker/manifest.tmpl @@ -0,0 +1,31 @@ +image: plugins/gitleaks:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}} +{{#if build.tags}} +tags: +{{#each build.tags}} + - {{this}} +{{/each}} +{{/if}} +manifests: + - + image: plugins/gitleaks:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64 + platform: + architecture: amd64 + os: linux + - + image: plugins/gitleaks:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64 + platform: + variant: v8 + architecture: arm64 + os: linux + - + image: plugins/gitleaks:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm + platform: + variant: v7 + architecture: arm + os: linux + - + image: plugins/gitleaks:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm + platform: + variant: v6 + architecture: arm + os: linux \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a2f9159 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module github.com/drone/drone-gitleaks + +go 1.16 + +require ( + github.com/kelseyhightower/envconfig v1.4.0 + github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect + github.com/sirupsen/logrus v1.8.1 + github.com/stretchr/objx v0.1.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..bff9ab8 --- /dev/null +++ b/go.sum @@ -0,0 +1,13 @@ +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= +github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/main.go b/main.go new file mode 100644 index 0000000..7fb3bfe --- /dev/null +++ b/main.go @@ -0,0 +1,50 @@ +// Copyright 2020 the Drone Authors. All rights reserved. +// Use of this source code is governed by the Blue Oak Model License +// that can be found in the LICENSE file. + +package main + +import ( + "context" + + "github.com/drone/drone-gitleaks/plugin" + + "github.com/kelseyhightower/envconfig" + "github.com/sirupsen/logrus" +) + +func main() { + logrus.SetFormatter(new(formatter)) + + var args plugin.Args + if err := envconfig.Process("", &args); err != nil { + logrus.Fatalln(err) + } + + switch args.Level { + case "debug": + logrus.SetLevel(logrus.DebugLevel) + case "trace": + logrus.SetLevel(logrus.TraceLevel) + } + + // set the default formatter + logrus.SetFormatter(&logrus.TextFormatter{}) + + if err := plugin.Exec(context.Background(), args); err != nil { + logrus.Fatalln(err) + } +} + +// default formatter that writes logs without including timestamp +// or level information. +type formatter struct{} + +func (*formatter) Format(entry *logrus.Entry) ([]byte, error) { + return []byte(entry.Message), nil +} + +// text formatter that writes logs with level information +var textFormatter = &logrus.TextFormatter{ + DisableTimestamp: true, +} diff --git a/plugin/pipeline.go b/plugin/pipeline.go new file mode 100644 index 0000000..2de7a79 --- /dev/null +++ b/plugin/pipeline.go @@ -0,0 +1,144 @@ +// Copyright 2020 the Drone Authors. All rights reserved. +// Use of this source code is governed by the Blue Oak Model License +// that can be found in the LICENSE file. + +package plugin + +// Pipeline provides Pipeline metadata from the environment. +type Pipeline struct { + // Build provides build metadata. + Build struct { + Branch string `envconfig:"DRONE_BUILD_BRANCH"` + Number int `envconfig:"DRONE_BUILD_NUMBER"` + Parent int `envconfig:"DRONE_BUILD_PARENT"` + Event string `envconfig:"DRONE_BUILD_EVENT"` + Action string `envconfig:"DRONE_BUILD_ACTION"` + Status string `envconfig:"DRONE_BUILD_STATUS"` + Created int64 `envconfig:"DRONE_BUILD_CREATED"` + Started int64 `envconfig:"DRONE_BUILD_STARTED"` + Finished int64 `envconfig:"DRONE_BUILD_FINISHED"` + Link string `envconfig:"DRONE_BUILD_LINK"` + } + + // Calver provides the calver details parsed from the + // git tag. If the git tag is empty or is not a valid + // calver, the values will be empty. + Calver struct { + Version string `envconfig:"DRONE_CALVER"` + Short string `envconfig:"DRONE_CALVER_SHORT"` + MajorMinor string `envconfig:"DRONE_CALVER_MAJOR_MINOR"` + Major string `envconfig:"DRONE_CALVER_MAJOR"` + Minor string `envconfig:"DRONE_CALVER_MINOR"` + Micro string `envconfig:"DRONE_CALVER_MICRO"` + Modifier string `envconfig:"DRONE_CALVER_MODIFIER"` + } + + // Commit provides the commit metadata. + Commit struct { + Rev string `envconfig:"DRONE_COMMIT_SHA"` + Before string `envconfig:"DRONE_COMMIT_BEFORE"` + After string `envconfig:"DRONE_COMMIT_AFTER"` + Ref string `envconfig:"DRONE_COMMIT_REF"` + Branch string `envconfig:"DRONE_COMMIT_BRANCH"` + Source string `envconfig:"DRONE_COMMIT_SOURCE"` + Target string `envconfig:"DRONE_COMMIT_TARGET"` + Link string `envconfig:"DRONE_COMMIT_LINK"` + Message string `envconfig:"DRONE_COMMIT_MESSAGE"` + + Author struct { + Username string `envconfig:"DRONE_COMMIT_AUTHOR"` + Name string `envconfig:"DRONE_COMMIT_AUTHOR_NAME"` + Email string `envconfig:"DRONE_COMMIT_AUTHOR_EMAIL"` + Avatar string `envconfig:"DRONE_COMMIT_AUTHOR_AVATAR"` + } + } + + // Deploy provides the deployment metadata. + Deploy struct { + ID string `envconfig:"DRONE_DEPLOY_TO"` + Target string `envconfig:"DRONE_DEPLOY_ID"` + } + + // Failed provides a list of failed steps and failed stages + // for the current pipeline. + Failed struct { + Steps []string `envconfig:"DRONE_FAILED_STEPS"` + Stages []string `envconfig:"DRONE_FAILED_STAGES"` + } + + // Git provides the git repository metadata. + Git struct { + HTTPURL string `envconfig:"DRONE_GIT_HTTP_URL"` + SSHURL string `envconfig:"DRONE_GIT_SSH_URL"` + } + + // PullRequest provides the pull request metadata. + PullRequest struct { + Number int `envconfig:"DRONE_PULL_REQUEST"` + } + + // Repo provides the repository metadata. + Repo struct { + Branch string `envconfig:"DRONE_REPO_BRANCH"` + Link string `envconfig:"DRONE_REPO_LINK"` + Namespace string `envconfig:"DRONE_REPO_NAMESPACE"` + Name string `envconfig:"DRONE_REPO_NAME"` + Private bool `envconfig:"DRONE_REPO_PRIVATE"` + Remote string `envconfig:"DRONE_GIT_HTTP_URL"` + SCM string `envconfig:"DRONE_REPO_SCM"` + Slug string `envconfig:"DRONE_REPO"` + Visibility string `envconfig:"DRONE_REPO_VISIBILITY"` + } + + // Stage provides the stage metadata. + Stage struct { + Kind string `envconfig:"DRONE_STAGE_KIND"` + Type string `envconfig:"DRONE_STAGE_TYPE"` + Name string `envconfig:"DRONE_STAGE_NAME"` + Number int `envconfig:"DRONE_STAGE_NUMBER"` + Machine string `envconfig:"DRONE_STAGE_MACHINE"` + OS string `envconfig:"DRONE_STAGE_OS"` + Arch string `envconfig:"DRONE_STAGE_ARCH"` + Variant string `envconfig:"DRONE_STAGE_VARIANT"` + Status string `envconfig:"DRONE_STAGE_STATUS"` + Started int64 `envconfig:"DRONE_STAGE_STARTED"` + Finished int64 `envconfig:"DRONE_STAGE_FINISHED"` + DependsOn []string `envconfig:"DRONE_STAGE_DEPENDS_ON"` + } + + // Step provides the step metadata. + Step struct { + Number int `envconfig:"DRONE_STEP_NUMBER"` + Name string `envconfig:"DRONE_STEP_NAME"` + } + + // Semver provides the semver details parsed from the + // git tag. If the git tag is empty or is not a valid + // semver, the values will be empty and the error field + // will be populated with the parsing error. + Semver struct { + Version string `envconfig:"DRONE_SEMVER"` + Short string `envconfig:"DRONE_SEMVER_SHORT"` + Major string `envconfig:"DRONE_SEMVER_MAJOR"` + Minor string `envconfig:"DRONE_SEMVER_MINOR"` + Patch string `envconfig:"DRONE_SEMVER_PATCH"` + Build string `envconfig:"DRONE_SEMVER_BUILD"` + PreRelease string `envconfig:"DRONE_SEMVER_PRERELEASE"` + Error string `envconfig:"DRONE_SEMVER_ERROR"` + } + + // System provides the Drone system metadata, including + // the system version of details required to create the + // drone website address. + System struct { + Proto string `envconfig:"DRONE_SYSTEM_PROTO"` + Host string `envconfig:"DRONE_SYSTEM_HOST"` + Hostname string `envconfig:"DRONE_SYSTEM_HOSTNAME"` + Version string `envconfig:"DRONE_SYSTEM_VERSION"` + } + + // Tag provides the git tag details. + Tag struct { + Name string `envconfig:"DRONE_TAG"` + } +} diff --git a/plugin/plugin.go b/plugin/plugin.go new file mode 100644 index 0000000..0d451db --- /dev/null +++ b/plugin/plugin.go @@ -0,0 +1,66 @@ +// Copyright 2020 the Drone Authors. All rights reserved. +// Use of this source code is governed by the Blue Oak Model License +// that can be found in the LICENSE file. + +package plugin + +import ( + "context" + "encoding/json" + "io/ioutil" + "os" + "os/exec" + + "github.com/sirupsen/logrus" +) + +// Args provides plugin execution arguments. +type Args struct { + Pipeline + + // Level defines the plugin log level. + Level string `envconfig:"PLUGIN_LOG_LEVEL"` + + Path string `envconfig:"PLUGIN_PATH" default:"."` + Conf string `envconfig:"PLUGIN_CONFIG"` +} + +// Exec executes the plugin. +func Exec(ctx context.Context, args Args) error { + + // generate a temp file to store the report + file, err := ioutil.TempFile("", "gitleaks") + if err != nil { + logrus.WithError(err).Warnln("Cannot generate temporary file") + return err + } + defer os.Remove(file.Name()) + + cmd := exec.Command("gitleaks", "--path="+args.Path, "--commit="+args.Commit.Rev, "--report="+file.Name()) + cmd.Stderr = os.Stderr + cmd.Stdout = os.Stdout + + if s := args.Conf; s != "" { + cmd.Args = append(cmd.Args, "--config-path="+s) + } + + // execute the command + err = cmd.Run() + + // read the generated report and unmarshal + dat := []match{} + out, ferr := ioutil.ReadFile("/tmp/report.json") + if ferr != nil { + logrus.WithError(ferr).Warnln("Cannot read report") + } + if jsonerr := json.Unmarshal(out, &dat); jsonerr != nil { + logrus.WithError(jsonerr).Warnln("Cannot unmarshal report") + } + + // loop through and print each violation + for _, match := range dat { + logrus.Errorf("%s violation in %q at line %d\n", match.Rule, match.File, match.Linenumber) + } + + return err +} diff --git a/plugin/plugin_test.go b/plugin/plugin_test.go new file mode 100644 index 0000000..cf5d77a --- /dev/null +++ b/plugin/plugin_test.go @@ -0,0 +1,11 @@ +// Copyright 2020 the Drone Authors. All rights reserved. +// Use of this source code is governed by the Blue Oak Model License +// that can be found in the LICENSE file. + +package plugin + +import "testing" + +func TestPlugin(t *testing.T) { + t.Skip() +} diff --git a/plugin/types.go b/plugin/types.go new file mode 100644 index 0000000..5dda2f4 --- /dev/null +++ b/plugin/types.go @@ -0,0 +1,23 @@ +// Copyright 2020 the Drone Authors. All rights reserved. +// Use of this source code is governed by the Blue Oak Model License +// that can be found in the LICENSE file. + +package plugin + +type match struct { + Line string `json:"line"` + Linenumber int `json:"lineNumber"` + Offender string `json:"offender"` + Offenderentropy int `json:"offenderEntropy"` + Commit string `json:"commit"` + Repo string `json:"repo"` + Repourl string `json:"repoURL"` + Leakurl string `json:"leakURL"` + Rule string `json:"rule"` + Commitmessage string `json:"commitMessage"` + Author string `json:"author"` + Email string `json:"email"` + File string `json:"file"` + Date string `json:"date"` + Tags string `json:"tags"` +} diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100755 index 0000000..74efe8b --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +# force go modules +export GOPATH="" + +# disable cgo +export CGO_ENABLED=0 + +set -e +set -x + +# linux +GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/plugin +GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/plugin +GOOS=linux GOARCH=arm go build -o release/linux/arm/plugin + +# windows +GOOS=windows go build -o release/windows/amd64/plugin.exe diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh new file mode 100755 index 0000000..dd5e50b --- /dev/null +++ b/scripts/upgrade.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +curl https://raw.githubusercontent.com/drone/boilr-plugin/master/template/plugin/pipeline.go --output plugin/pipeline.go