Skip to content

Commit

Permalink
command/agent/host: redact environment variables a couple of ways
Browse files Browse the repository at this point in the history
  • Loading branch information
langmartin committed Jul 1, 2020
1 parent b39a3f7 commit c4f59b8
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 15 deletions.
1 change: 1 addition & 0 deletions client/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
var (
// DefaultEnvBlacklist is the default set of environment variables that are
// filtered when passing the environment variables of the host to a task.
// duplicated in command/agent/host, update that if this changes.
DefaultEnvBlacklist = strings.Join([]string{
"CONSUL_TOKEN",
"CONSUL_HTTP_TOKEN",
Expand Down
58 changes: 43 additions & 15 deletions command/agent/host/host.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package host

import (
"io/ioutil"
"os"
"strings"
)
Expand Down Expand Up @@ -60,36 +61,63 @@ func diskUsage(path string) (du DiskUsage, err error) {
return du, nil
}

var (
envRedactSet = makeEnvRedactSet()
)

// environment returns the process environment in a map
func environment() map[string]string {
env := make(map[string]string)

for _, e := range os.Environ() {
s := strings.SplitN(e, "=", 2)
env[s[0]] = s[1]
k := s[0]
up := strings.ToUpper(k)
v := s[1]

_, redact := envRedactSet[k]
if redact ||
strings.Contains(up, "TOKEN") ||
strings.Contains(up, "SECRET") {
v = "<redacted>"
}

env[k] = v
}
return env
}

// slurp returns the file contents as a string, ignoring errors
// makeEnvRedactSet creates a set of well known environment variables that should be
// redacted in the output
func makeEnvRedactSet() map[string]struct{} {
// Duplicated from config.DefaultEnvBlacklist in order to avoid an import cycle
configDefault := []string{
"CONSUL_TOKEN",
"CONSUL_HTTP_TOKEN",
"VAULT_TOKEN",
"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN",
"GOOGLE_APPLICATION_CREDENTIALS",
}

set := make(map[string]struct{})
for _, e := range configDefault {
set[e] = struct{}{}
}

return set
}

// slurp returns the file contents as a string, returning an error string
func slurp(path string) string {
var sb strings.Builder
buf := make([]byte, 512)
fh, err := os.Open(path)
if err != nil {
return err.Error()
}

var l int
for {
l, err = fh.Read(buf)
if err != nil {
if l > 0 {
sb.Write(buf[0 : l-1])
}
break
}
sb.Write(buf[0 : l-1])
bs, err := ioutil.ReadAll(fh)
if err != nil {
return err.Error()
}
return sb.String()

return string(bs)
}
15 changes: 15 additions & 0 deletions command/agent/host/host_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package host

import (
"os"
"testing"

"github.com/stretchr/testify/require"
Expand All @@ -17,11 +18,25 @@ func TestHostUtils(t *testing.T) {
}

func TestMakeHostData(t *testing.T) {
// setenv variables that should be redacted
prev := os.Getenv("VAULT_TOKEN")
os.Setenv("VAULT_TOKEN", "foo")
defer os.Setenv("VAULT_TOKEN", prev)

os.Setenv("BOGUS_TOKEN", "foo")
os.Setenv("BOGUS_SECRET", "foo")
os.Setenv("ryanSECRETS", "foo")

host, err := MakeHostData()
require.NoError(t, err)
require.NotEmpty(t, host.OS)
require.NotEmpty(t, host.Network)
require.NotEmpty(t, host.ResolvConf)
require.NotEmpty(t, host.Hosts)
require.NotEmpty(t, host.Disk)
require.NotEmpty(t, host.Environment)
require.Equal(t, "<redacted>", host.Environment["VAULT_TOKEN"])
require.Equal(t, "<redacted>", host.Environment["BOGUS_TOKEN"])
require.Equal(t, "<redacted>", host.Environment["BOGUS_SECRET"])
require.Equal(t, "<redacted>", host.Environment["ryanSECRETS"])
}

0 comments on commit c4f59b8

Please sign in to comment.