diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 628ab28f..c28b2e91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,6 +31,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v2 with: + version: v1.33.0 args: --timeout 5m0s - name: Test diff --git a/README.md b/README.md index 409d5972..90b9ee30 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,19 @@ You can now use `teller` or `tlr` (if you like shortcuts!) in your terminal. `teller` needs a tellerfile. This is a `.teller.yml` file that lives in your repo, or one that you point teller to with `teller -c your-conf.yml`. +## Using a Github Action + +For those using Github Action, you can have a 1-click experience of installing Teller in your CI: + +```yaml + - name: Setup Teller + uses: spectralops/setup-teller@v1 + - name: Run a Teller task (show, scan, run, etc.) + run: teller run [args] +``` + +For more, check our [setup teller action](https://github.com/marketplace/actions/setup-teller) on the marketplace. + ## Create your configuration @@ -139,6 +152,34 @@ Use this one liner from now on: $ docker run --rm -it --env-file <(teller env) alpine sh ``` +## :whale: Export in YAML format +You can export in a YAML format, suitable for [GCloud](https://cloud.google.com/functions/docs/env-var): + +``` +$ teller yaml +``` + +Example format: + +```yaml +FOO: "1" +KEY: VALUE +``` +## :whale: Export in JSON format +You can export in a JSON format, suitable for piping through `jq` or other workflows: + +``` +$ teller json +``` + +Example format: + +```json +{ + "FOO": "1" +} +``` + ## :warning: Scan for secrets Teller can help you fight secret sprawl and hard coded secrets, as well as be the best productivity tool for working with your vault. @@ -199,7 +240,7 @@ $ tail -f /var/log/apache.log | teller redact Finally, if you've got some files you want to redact, you can do that too: ``` -$ teller --in dirty.csv --out clean.csv +$ teller redact --in dirty.csv --out clean.csv ``` If you omit `--in` Teller will take `stdin`, and if you omit `--out` Teller will output to `stdout`. @@ -438,7 +479,7 @@ Configuration is environment based, as defined by client standard. See variables * Sync - `yes` * Mapping - `yes` * Modes - `read+write` -* Key format - path based, has to start with `secret/data/` +* Key format - path based, usually starts with `secret/data/`, and more generically `[engine name]/data` ### Example Config diff --git a/go.mod b/go.mod index 9548fa63..b768f295 100644 --- a/go.mod +++ b/go.mod @@ -43,4 +43,5 @@ require ( golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46 // indirect google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c gopkg.in/yaml.v2 v2.4.0 + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c ) diff --git a/main.go b/main.go index e7a07a7c..91a9bc23 100644 --- a/main.go +++ b/main.go @@ -26,6 +26,12 @@ var CLI struct { Show struct { } `cmd help:"Print in a human friendly, secure format"` + Yaml struct { + } `cmd help:"Print values in a YAML format (suitable for GCloud)"` + + JSON struct { + } `cmd help:"Print values in a JSON format"` + Sh struct { } `cmd help:"Print ready to be eval'd exports for your shell"` @@ -210,6 +216,22 @@ func main() { case "env": fmt.Print(teller.ExportDotenv()) + case "yaml": + out, err := teller.ExportYAML() + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } + fmt.Print(out) + + case "json": + out, err := teller.ExportJSON() + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } + fmt.Print(out) + case "show": teller.PrintEnvKeys() diff --git a/pkg/teller.go b/pkg/teller.go index 1518b99d..f616a9fc 100644 --- a/pkg/teller.go +++ b/pkg/teller.go @@ -3,6 +3,7 @@ package pkg import ( "bufio" "bytes" + "encoding/json" "fmt" "io" "io/ioutil" @@ -16,6 +17,7 @@ import ( "github.com/karrick/godirwalk" "github.com/spectralops/teller/pkg/core" "github.com/thoas/go-funk" + "gopkg.in/yaml.v3" ) // Teller @@ -114,6 +116,34 @@ func (tl *Teller) ExportDotenv() string { return b.String() } +func (tl *Teller) ExportYAML() (out string, err error) { + valmap := map[string]string{} + + for i := range tl.Entries { + v := tl.Entries[i] + valmap[v.Key] = v.Value + } + content, err := yaml.Marshal(valmap) + if err != nil { + return "", err + } + return string(content), nil +} + +func (tl *Teller) ExportJSON() (out string, err error) { + valmap := map[string]string{} + + for i := range tl.Entries { + v := tl.Entries[i] + valmap[v.Key] = v.Value + } + content, err := json.MarshalIndent(valmap, "", " ") + if err != nil { + return "", err + } + return string(content), nil +} + func renderWizardTemplate(fname string, answers *core.WizardAnswers) error { t, err := template.New("t").Parse(TellerFileTemplate) if err != nil { diff --git a/pkg/teller_test.go b/pkg/teller_test.go index 607b3dc0..bef17afa 100644 --- a/pkg/teller_test.go +++ b/pkg/teller_test.go @@ -96,6 +96,13 @@ func TestTellerExports(t *testing.T) { b = tl.ExportEnv() assert.Equal(t, b, "#!/bin/sh\nexport k=v\n") + + b, err := tl.ExportYAML() + assert.NoError(t, err) + assert.Equal(t, b, "k: v\n") + b, err = tl.ExportJSON() + assert.NoError(t, err) + assert.Equal(t, b, "{\n \"k\": \"v\"\n}") } func TestTellerCollect(t *testing.T) { diff --git a/vendor/modules.txt b/vendor/modules.txt index ad378894..29d7f488 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -599,4 +599,5 @@ gopkg.in/square/go-jose.v2/jwt ## explicit gopkg.in/yaml.v2 # gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c +## explicit gopkg.in/yaml.v3