Skip to content

Commit

Permalink
use allow/deny instead of the colored alternatives (hashicorp#9019)
Browse files Browse the repository at this point in the history
Signed-off-by: Yoan Blanc <yoan@dosimple.ch>
  • Loading branch information
greut authored and fredrikhgrelland committed Oct 22, 2020
1 parent 287af0c commit 3c6b7c0
Show file tree
Hide file tree
Showing 18 changed files with 136 additions and 74 deletions.
7 changes: 6 additions & 1 deletion client/allocrunner/taskrunner/task_dir_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ func setEnvvars(envBuilder *taskenv.Builder, fsi drivers.FSIsolation, taskDir *a

// Set the host environment variables for non-image based drivers
if fsi != drivers.FSIsolationImage {
filter := strings.Split(conf.ReadDefault("env.blacklist", cconfig.DefaultEnvBlacklist), ",")
// COMPAT(0.13) using inclusive language, blacklist is kept for backward compatibility.
denylist := conf.ReadAlternativeDefault(
[]string{"env.denylist", "env.blacklist"},
cconfig.DefaultEnvDenylist,
)
filter := strings.Split(denylist, ",")
envBuilder.SetHostEnvvars(filter)
}
}
6 changes: 5 additions & 1 deletion client/allocrunner/taskrunner/validate_hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,11 @@ func validateTask(task *structs.Task, taskEnv *taskenv.TaskEnv, conf *config.Con
var mErr multierror.Error

// Validate the user
unallowedUsers := conf.ReadStringListToMapDefault("user.blacklist", config.DefaultUserBlacklist)
// COMPAT(0.13) uses inclusive language. blacklist is kept for backward compatilibity.
unallowedUsers := conf.ReadStringListAlternativeToMapDefault(
[]string{"user.denylist", "user.blacklist"},
config.DefaultUserDenylist,
)
checkDrivers := conf.ReadStringListToMapDefault("user.checked_drivers", config.DefaultUserCheckedDrivers)
if _, driverMatch := checkDrivers[task.Driver]; driverMatch {
if _, unallowed := unallowedUsers[task.User]; unallowed {
Expand Down
7 changes: 4 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,9 +409,10 @@ func NewClient(cfg *config.Config, consulCatalog consul.CatalogAPI, consulServic
return nil, fmt.Errorf("fingerprinting failed: %v", err)
}

// Build the white/blacklists of drivers.
allowlistDrivers := cfg.ReadStringListToMap("driver.whitelist")
blocklistDrivers := cfg.ReadStringListToMap("driver.blacklist")
// Build the allow/denylists of drivers.
// COMPAT(0.13) uses inclusive language. white/blacklist are there for backward compatible reasons only.
allowlistDrivers := cfg.ReadStringListToMap("driver.allowlist", "driver.whitelist")
blocklistDrivers := cfg.ReadStringListToMap("driver.denylist", "driver.blacklist")

// Setup the csi manager
csiConfig := &csimanager.Config{
Expand Down
4 changes: 2 additions & 2 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ func TestClient_UpdateNodeFromFingerprintKeepsConfig(t *testing.T) {
client, cleanup = TestClient(t, func(c *config.Config) {
c.NetworkInterface = dev
c.Node.Name = name
c.Options["fingerprint.blacklist"] = "network"
c.Options["fingerprint.denylist"] = "network"
// Node is already a mock.Node, with a device
c.Node.NodeResources.Networks[0].Device = dev
})
Expand Down Expand Up @@ -1265,7 +1265,7 @@ func Test_UpdateNodeFromFingerprintMultiIP(t *testing.T) {
// Client without network configured updates to match fingerprint
client, cleanup := TestClient(t, func(c *config.Config) {
c.NetworkInterface = dev
c.Options["fingerprint.blacklist"] = "network,cni,bridge"
c.Options["fingerprint.denylist"] = "network,cni,bridge"
c.Node.Resources.Networks = c.Node.NodeResources.Networks
})
defer cleanup()
Expand Down
59 changes: 35 additions & 24 deletions client/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,26 +19,26 @@ import (
)

var (
// DefaultEnvBlacklist is the default set of environment variables that are
// DefaultEnvDenylist 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{
DefaultEnvDenylist = strings.Join([]string{
"CONSUL_TOKEN",
"CONSUL_HTTP_TOKEN",
"VAULT_TOKEN",
"AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_SESSION_TOKEN",
"GOOGLE_APPLICATION_CREDENTIALS",
}, ",")

// DefaultUserBlacklist is the default set of users that tasks are not
// DefaultUserDenylist is the default set of users that tasks are not
// allowed to run as when using a driver in "user.checked_drivers"
DefaultUserBlacklist = strings.Join([]string{
DefaultUserDenylist = strings.Join([]string{
"root",
"Administrator",
}, ",")

// DefaultUserCheckedDrivers is the set of drivers we apply the user
// blacklist onto. For virtualized drivers it often doesn't make sense to
// denylist onto. For virtualized drivers it often doesn't make sense to
// make this stipulation so by default they are ignored.
DefaultUserCheckedDrivers = strings.Join([]string{
"exec",
Expand Down Expand Up @@ -344,11 +344,20 @@ func (c *Config) Read(id string) string {
// ReadDefault returns the specified configuration value, or the specified
// default value if none is set.
func (c *Config) ReadDefault(id string, defaultValue string) string {
val, ok := c.Options[id]
if !ok {
return defaultValue
return c.ReadAlternativeDefault([]string{id}, defaultValue)
}

// ReadAlternativeDefault returns the specified configuration value, or the
// specified value if none is set.
func (c *Config) ReadAlternativeDefault(ids []string, defaultValue string) string {
for _, id := range ids {
val, ok := c.Options[id]
if ok {
return val
}
}
return val

return defaultValue
}

// ReadBool parses the specified option as a boolean.
Expand Down Expand Up @@ -420,28 +429,30 @@ func (c *Config) ReadDurationDefault(id string, defaultValue time.Duration) time
return val
}

// ReadStringListToMap tries to parse the specified option as a comma separated list.
// ReadStringListToMap tries to parse the specified option(s) as a comma separated list.
// If there is an error in parsing, an empty list is returned.
func (c *Config) ReadStringListToMap(key string) map[string]struct{} {
s := strings.TrimSpace(c.Read(key))
list := make(map[string]struct{})
if s != "" {
for _, e := range strings.Split(s, ",") {
trimmed := strings.TrimSpace(e)
list[trimmed] = struct{}{}
}
}
return list
func (c *Config) ReadStringListToMap(keys ...string) map[string]struct{} {
val := c.ReadAlternativeDefault(keys, "")

return splitValue(val)
}

// ReadStringListToMap tries to parse the specified option as a comma separated list.
// If there is an error in parsing, an empty list is returned.
func (c *Config) ReadStringListToMapDefault(key, defaultValue string) map[string]struct{} {
val, ok := c.Options[key]
if !ok {
val = defaultValue
}
return c.ReadStringListAlternativeToMapDefault([]string{key}, defaultValue)
}

// ReadStringListAlternativeToMapDefault tries to parse the specified options as a comma sparated list.
// If there is an error in parsing, an empty list is returned.
func (c *Config) ReadStringListAlternativeToMapDefault(keys []string, defaultValue string) map[string]struct{} {
val := c.ReadAlternativeDefault(keys, defaultValue)

return splitValue(val)
}

// splitValue parses the value as a comma separated list.
func splitValue(val string) map[string]struct{} {
list := make(map[string]struct{})
if val != "" {
for _, e := range strings.Split(val, ",") {
Expand Down
20 changes: 11 additions & 9 deletions client/fingerprint_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,28 +65,30 @@ func (fm *FingerprintManager) getNode() *structs.Node {
}

// Run starts the process of fingerprinting the node. It does an initial pass,
// identifying whitelisted and blacklisted fingerprints/drivers. Then, for
// identifying allowlisted and denylisted fingerprints/drivers. Then, for
// those which require periotic checking, it starts a periodic process for
// each.
func (fp *FingerprintManager) Run() error {
// First, set up all fingerprints
cfg := fp.getConfig()
whitelistFingerprints := cfg.ReadStringListToMap("fingerprint.whitelist")
whitelistFingerprintsEnabled := len(whitelistFingerprints) > 0
blacklistFingerprints := cfg.ReadStringListToMap("fingerprint.blacklist")
// COMPAT(0.13) using inclusive language, whitelist is kept for backward compatibility.
allowlistFingerprints := cfg.ReadStringListToMap("fingerprint.allowlist", "fingerprint.whitelist")
allowlistFingerprintsEnabled := len(allowlistFingerprints) > 0
// COMPAT(0.13) using inclusive language, blacklist is kept for backward compatibility.
denylistFingerprints := cfg.ReadStringListToMap("fingerprint.denylist", "fingerprint.blacklist")

fp.logger.Debug("built-in fingerprints", "fingerprinters", fingerprint.BuiltinFingerprints())

var availableFingerprints []string
var skippedFingerprints []string
for _, name := range fingerprint.BuiltinFingerprints() {
// Skip modules that are not in the whitelist if it is enabled.
if _, ok := whitelistFingerprints[name]; whitelistFingerprintsEnabled && !ok {
// Skip modules that are not in the allowlist if it is enabled.
if _, ok := allowlistFingerprints[name]; allowlistFingerprintsEnabled && !ok {
skippedFingerprints = append(skippedFingerprints, name)
continue
}
// Skip modules that are in the blacklist
if _, ok := blacklistFingerprints[name]; ok {
// Skip modules that are in the denylist
if _, ok := denylistFingerprints[name]; ok {
skippedFingerprints = append(skippedFingerprints, name)
continue
}
Expand All @@ -99,7 +101,7 @@ func (fp *FingerprintManager) Run() error {
}

if len(skippedFingerprints) != 0 {
fp.logger.Debug("fingerprint modules skipped due to white/blacklist",
fp.logger.Debug("fingerprint modules skipped due to allow/denylist",
"skipped_fingerprinters", skippedFingerprints)
}

Expand Down
38 changes: 35 additions & 3 deletions client/fingerprint_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,13 @@ func TestFimgerprintManager_Run_InWhitelist(t *testing.T) {
require.NotEqual(node.Attributes["cpu.frequency"], "")
}

func TestFingerprintManager_Run_InBlacklist(t *testing.T) {
func TestFingerprintManager_Run_InDenylist(t *testing.T) {
t.Parallel()
require := require.New(t)
testClient, cleanup := TestClient(t, func(c *config.Config) {
c.Options = map[string]string{
"fingerprint.whitelist": " arch,memory,foo,bar ",
"fingerprint.blacklist": " cpu ",
"fingerprint.allowlist": " arch,memory,foo,bar ",
"fingerprint.denylist": " cpu ",
}
})
defer cleanup()
Expand All @@ -94,6 +94,38 @@ func TestFingerprintManager_Run_Combination(t *testing.T) {
t.Parallel()
require := require.New(t)

testClient, cleanup := TestClient(t, func(c *config.Config) {
c.Options = map[string]string{
"fingerprint.allowlist": " arch,cpu,memory,foo,bar ",
"fingerprint.denylist": " memory,host ",
}
})
defer cleanup()

fm := NewFingerprintManager(
testClient.config.PluginSingletonLoader,
testClient.GetConfig,
testClient.config.Node,
testClient.shutdownCh,
testClient.updateNodeFromFingerprint,
testClient.logger,
)

err := fm.Run()
require.Nil(err)

node := testClient.config.Node

require.NotEqual(node.Attributes["cpu.frequency"], "")
require.NotEqual(node.Attributes["cpu.arch"], "")
require.NotContains(node.Attributes, "memory.totalbytes")
require.NotContains(node.Attributes, "os.name")
}

func TestFingerprintManager_Run_CombinationLegacyNames(t *testing.T) {
t.Parallel()
require := require.New(t)

testClient, cleanup := TestClient(t, func(c *config.Config) {
c.Options = map[string]string{
"fingerprint.whitelist": " arch,cpu,memory,foo,bar ",
Expand Down
2 changes: 1 addition & 1 deletion command/acl_policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Usage: nomad acl policy <subcommand> [options] [args]
This command groups subcommands for interacting with ACL policies. Nomad's ACL
system can be used to control access to data and APIs. ACL policies allow a
set of capabilities or actions to be granted or whitelisted. For a full guide
set of capabilities or actions to be granted or allowlisted. For a full guide
see: https://www.nomadproject.io/guides/acl.html
Create an ACL policy:
Expand Down
2 changes: 1 addition & 1 deletion command/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ type ClientTemplateConfig struct {
// are unsafe because they expose information from the client host.
FunctionDenylist []string `hcl:"function_denylist"`

// COMPAT(0.13) consul-template uses inclusive language from v0.25.0 - function_blacklist is kept for compatibility
// Deprecated: COMPAT(0.13) consul-template uses inclusive language from v0.25.0 - function_blacklist is kept for compatibility
FunctionBlacklist []string `hcl:"function_blacklist"`

// DisableSandbox allows templates to access arbitrary files on the
Expand Down
2 changes: 1 addition & 1 deletion command/agent/testdata/obj-len-one.hcl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
client {
options {
driver.whitelist = "docker"
driver.allowlist = "docker"
}
}
2 changes: 1 addition & 1 deletion command/agent/testdata/obj-len-one.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"client": {
"options": {
"driver.whitelist": "docker"
"driver.allowlist": "docker"
}
},
"server": {}
Expand Down
7 changes: 5 additions & 2 deletions drivers/docker/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ func PluginLoader(opts map[string]string) (map[string]interface{}, error) {
conf["volumes"] = volConf

// capabilities
if v, ok := opts["docker.caps.whitelist"]; ok {
// COMPAT(0.13) uses inclusive language. whitelist is used for backward compatibility.
if v, ok := opts["docker.caps.allowlist"]; ok {
conf["allow_caps"] = strings.Split(v, ",")
} else if v, ok := opts["docker.caps.whitelist"]; ok {
conf["allow_caps"] = strings.Split(v, ",")
}

Expand Down Expand Up @@ -497,7 +500,7 @@ type DockerMount struct {

func (m DockerMount) toDockerHostMount() (docker.HostMount, error) {
if m.Type == "" {
// for backward compatbility, as type is optional
// for backward compatibility, as type is optional
m.Type = "volume"
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/docker/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ func (d *Driver) createContainerConfig(task *drivers.TaskConfig, driverConfig *T
}
}
if len(missingCaps) > 0 {
return c, fmt.Errorf("Docker driver doesn't have the following caps whitelisted on this Nomad agent: %s", missingCaps)
return c, fmt.Errorf("Docker driver doesn't have the following caps allowlisted on this Nomad agent: %s", missingCaps)
}
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/docker/driver_darwin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
// be mounted into Docker containers on macOS without needing dev performing
// special setup.
//
// macOS sets tempdir as `/var`, which Docker does not whitelist as a path that
// macOS sets tempdir as `/var`, which Docker does not allowlist as a path that
// can be bind-mounted.
func TestMain(m *testing.M) {
tmpdir := fmt.Sprintf("/tmp/nomad-docker-tests-%d", time.Now().Unix())
Expand Down
Loading

0 comments on commit 3c6b7c0

Please sign in to comment.