Skip to content

Commit

Permalink
add scan
Browse files Browse the repository at this point in the history
  • Loading branch information
jondot committed Apr 13, 2021
1 parent adb7d67 commit b0a7068
Show file tree
Hide file tree
Showing 36 changed files with 1,986 additions and 7 deletions.
8 changes: 3 additions & 5 deletions .teller.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ opts:
providers:
# Configure via environment:
# CONSUL_HTTP_ADDR
consul:
env_sync:
path: redis/config
dotenv:
env:
ETC_DSN:
path: redis/config/foobar
FOO:
path: ~/my-dot-env.env

29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,35 @@ Use this one liner from now on:
$ docker run --rm -it --env-file <(teller env) alpine sh
```
## Scan for hardcoded secrets
Look for your vault-kept secrets in your code by running:
```
$ teller scan
```
You can run it as a linter in your CI like so:
```
run: teller scan --silent
```
It will break your build if it finds something (returns exit code `1`).
Use Teller for productively and securely running process and you get this for free -- nothing to configure. If you have data that you're bringing that you're sure isn't sensitive, flag it in your `teller.yml`:
```
dotenv:
env:
FOO:
path: ~/my-dot-env.env
not_sensitive: true
```
By default we treat all entries as sensitive.
## Populate templates
Have a kickstarter project you want to populate quickly with some variables (not secrets though!)?
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ require (
github.com/hashicorp/vault/api v1.0.4
github.com/heroku/heroku-go/v5 v5.2.1
github.com/jftuga/ellipsis v1.0.0
github.com/karrick/godirwalk v1.16.1
github.com/miekg/dns v1.1.35 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/pkg/errors v0.9.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,8 @@ github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
Expand Down
17 changes: 17 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ var CLI struct {
TemplateFile string `arg name:"template_file" help:"Input template file (Go template format)"`
OutFile string `arg name:"out_file" help:"Output file"`
} `cmd help:"Inject vars into a template file"`

Scan struct {
Path string `arg optional name:"path" help:"Scan root, default: '.'"`
Silent bool `optional name:"silent" help:"No text, just exit code"`
} `cmd help:"Scans your codebase for sensitive keys"`
}

var (
Expand Down Expand Up @@ -103,6 +108,18 @@ func main() {
case "show":
teller.PrintEnvKeys()

case "scan":
findings, err := teller.Scan(CLI.Scan.Path, CLI.Scan.Silent)

if err != nil {
fmt.Printf("Error: %v\n", err)
os.Exit(1)
}
num := len(findings)
if num > 0 {
os.Exit(1)
}

case "template <template_file> <out_file>":
err := teller.TemplateFile(CLI.Template.TemplateFile, CLI.Template.OutFile)
if err != nil {
Expand Down
19 changes: 19 additions & 0 deletions pkg/core/types.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
package core

type Severity string

const (
High Severity = "high"
Medium Severity = "medium"
Low Severity = "low"
None Severity = "none"
)

type KeyPath struct {
Env string `yaml:"env,omitempty"`
Path string `yaml:"path"`
Field string `yaml:"field,omitempty"`
Remap map[string]string `yaml:"remap,omitempty"`
Decrypt bool `yaml:"decrypt,omitempty"`
Optional bool `yaml:"optional,omitempty"`
Severity Severity `yaml:"severity,omitempty" default:"high"`
}
type WizardAnswers struct {
Project string
Expand Down Expand Up @@ -45,6 +55,7 @@ type EnvEntry struct {
Value string
Provider string
ResolvedPath string
Severity Severity
}
type EnvEntryLookup struct {
Entries []EnvEntry
Expand Down Expand Up @@ -87,3 +98,11 @@ type Provider interface {
// in this case env is filled
Get(p KeyPath) (*EnvEntry, error)
}

type Match struct {
Path string
Line string
LineNumber int
MatchIndex int
Entry EnvEntry
}
35 changes: 34 additions & 1 deletion pkg/porcelain.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"math"
"os"
"strings"
"time"

survey "github.com/AlecAivazis/survey/v2"
"github.com/thoas/go-funk"
Expand Down Expand Up @@ -109,11 +110,43 @@ func (p *Porcelain) PrintEntries(entries []core.EnvEntry) {
if v.Value == "" {
fmt.Fprintf(&buf, "[%s %s %s] %s\n", yellow(v.Provider), gray(ep), red("missing"), green(v.Key))
} else {
fmt.Fprintf(&buf, "[%s %s] %s %s %s*****\n", yellow(v.Provider), gray(ep), green(v.Key), gray("="), v.Value[:int(math.Min(float64(len(v.Value)), 2))])
fmt.Fprintf(&buf, "[%s %s] %s %s %s\n", yellow(v.Provider), gray(ep), green(v.Key), gray("="), maskedValue(v.Value))
}
}

out := buf.String()

fmt.Fprint(p.Out, out)
}
func maskedValue(v string) string {
return fmt.Sprintf("%s*****", v[:int(math.Min(float64(len(v)), 2))])
}

func (p *Porcelain) PrintMatches(matches []core.Match) {
yellow := color.New(color.FgYellow).SprintFunc()
gray := color.New(color.FgHiBlack).SprintFunc()
green := color.New(color.FgGreen).SprintFunc()
white := color.New(color.FgWhite).SprintFunc()
red := color.New(color.FgRed).SprintFunc()
//nolint
for _, m := range matches {
sevcolor := white
if m.Entry.Severity == core.High {
sevcolor = red
}
if m.Entry.Severity == core.Medium {
sevcolor = yellow
}
fmt.Printf("[%s] %s (%s,%s): found match for %s/%s (%s)\n", sevcolor(m.Entry.Severity), green(m.Path), yellow(m.LineNumber), yellow(m.MatchIndex), gray(m.Entry.Provider), red(m.Entry.Key), gray(maskedValue(m.Entry.Value)))
}
}

func (p *Porcelain) PrintMatchSummary(findings []core.Match, entries []core.EnvEntry, elapsed time.Duration) {
yellow := color.New(color.FgYellow).SprintFunc()
goodbad := color.New(color.FgGreen).SprintFunc()
if len(findings) > 0 {
goodbad = color.New(color.FgRed).SprintFunc()
}

fmt.Printf("Scanning for %v entries: found %v matches in %v\n", yellow(len(entries)), goodbad(len(findings)), goodbad(elapsed))
}
Loading

0 comments on commit b0a7068

Please sign in to comment.