Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support blacklisting fingerprinters #1949

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,9 @@ func (c *Client) reservePorts() {
func (c *Client) fingerprint() error {
whitelist := c.config.ReadStringListToMap("fingerprint.whitelist")
whitelistEnabled := len(whitelist) > 0
blacklist := c.config.ReadStringListToMap("fingerprint.blacklist")
blacklistEnabled := len(blacklist) > 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

White list needs this since you need to know both if the whitelist is active and if the fingerprinter is whitelisted (if not active nothing will be whitelisted). For blacklist you just need to know if it is contained in the map. so remove this variable and change :737 to if _, ok := blacklist[name]; ok {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same below and update the comments on those lines


c.logger.Printf("[DEBUG] client: built-in fingerprints: %v", fingerprint.BuiltinFingerprints())

var applied []string
Expand All @@ -730,6 +733,11 @@ func (c *Client) fingerprint() error {
skipped = append(skipped, name)
continue
}
// Skip modules that are in the blacklist if it is enabled.
if _, ok := blacklist[name]; blacklistEnabled && ok {
skipped = append(skipped, name)
continue
}
f, err := fingerprint.NewFingerprint(name, c.logger)
if err != nil {
return err
Expand All @@ -754,7 +762,7 @@ func (c *Client) fingerprint() error {
}
c.logger.Printf("[DEBUG] client: applied fingerprints %v", applied)
if len(skipped) != 0 {
c.logger.Printf("[DEBUG] client: fingerprint modules skipped due to whitelist: %v", skipped)
c.logger.Printf("[DEBUG] client: fingerprint modules skipped due to white/blacklist: %v", skipped)
}
return nil
}
Expand All @@ -778,9 +786,11 @@ func (c *Client) fingerprintPeriodic(name string, f fingerprint.Fingerprint, d t

// setupDrivers is used to find the available drivers
func (c *Client) setupDrivers() error {
// Build the whitelist of drivers.
// Build the white/blacklists of drivers.
whitelist := c.config.ReadStringListToMap("driver.whitelist")
whitelistEnabled := len(whitelist) > 0
blacklist := c.config.ReadStringListToMap("driver.blacklist")
blacklistEnabled := len(blacklist) > 0

var avail []string
var skipped []string
Expand All @@ -792,6 +802,11 @@ func (c *Client) setupDrivers() error {
skipped = append(skipped, name)
continue
}
// Skip fingerprinting drivers that are in the blacklist if it is enabled.
if _, ok := blacklist[name]; blacklistEnabled && ok {
skipped = append(skipped, name)
continue
}

d, err := driver.NewDriver(name, driverCtx)
if err != nil {
Expand All @@ -817,7 +832,7 @@ func (c *Client) setupDrivers() error {
c.logger.Printf("[DEBUG] client: available drivers %v", avail)

if len(skipped) != 0 {
c.logger.Printf("[DEBUG] client: drivers skipped due to whitelist: %v", skipped)
c.logger.Printf("[DEBUG] client: drivers skipped due to white/blacklist: %v", skipped)
}

return nil
Expand Down
90 changes: 90 additions & 0 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,23 @@ func TestClient_Fingerprint_InWhitelist(t *testing.T) {
}
}

func TestClient_Fingerprint_InBlacklist(t *testing.T) {
c := testClient(t, func(c *config.Config) {
if c.Options == nil {
c.Options = make(map[string]string)
}

// Weird spacing to test trimming. Blacklist cpu.
c.Options["fingerprint.blacklist"] = " cpu "
})
defer c.Shutdown()

node := c.Node()
if node.Attributes["cpu.frequency"] != "" {
t.Fatalf("cpu fingerprint module loaded despite blacklisting")
}
}

func TestClient_Fingerprint_OutOfWhitelist(t *testing.T) {
c := testClient(t, func(c *config.Config) {
if c.Options == nil {
Expand All @@ -232,6 +249,35 @@ func TestClient_Fingerprint_OutOfWhitelist(t *testing.T) {
}
}

func TestClient_Fingerprint_WhitelistBlacklistCombination(t *testing.T) {
c := testClient(t, func(c *config.Config) {
if c.Options == nil {
c.Options = make(map[string]string)
}

// With both white- and blacklist, should return the set difference of modules (arch, cpu)
c.Options["fingerprint.whitelist"] = "arch,memory,cpu"
c.Options["fingerprint.blacklist"] = "memory,nomad"
})
defer c.Shutdown()

node := c.Node()
// Check expected modules are present
if node.Attributes["cpu.frequency"] == "" {
t.Fatalf("missing cpu fingerprint module")
}
if node.Attributes["arch"] == "" {
t.Fatalf("missing arch fingerprint module")
}
// Check remainder _not_ present
if node.Attributes["memory.totalbytes"] != "" {
t.Fatalf("found memory fingerprint module")
}
if node.Attributes["nomad.version"] != "" {
t.Fatalf("found nomad fingerprint module")
}
}

func TestClient_Drivers(t *testing.T) {
c := testClient(t, nil)
defer c.Shutdown()
Expand Down Expand Up @@ -267,6 +313,27 @@ func TestClient_Drivers_InWhitelist(t *testing.T) {
}
}

func TestClient_Drivers_InBlacklist(t *testing.T) {
c := testClient(t, func(c *config.Config) {
if c.Options == nil {
c.Options = make(map[string]string)
}

// Weird spacing to test trimming
c.Options["driver.blacklist"] = " exec , foo "
})
defer c.Shutdown()

node := c.Node()
if node.Attributes["driver.exec"] != "" {
if v, ok := osExecDriverSupport[runtime.GOOS]; !v && ok {
t.Fatalf("exec driver loaded despite blacklist")
} else {
t.Skipf("missing exec driver, no OS support")
}
}
}

func TestClient_Drivers_OutOfWhitelist(t *testing.T) {
c := testClient(t, func(c *config.Config) {
if c.Options == nil {
Expand All @@ -283,6 +350,29 @@ func TestClient_Drivers_OutOfWhitelist(t *testing.T) {
}
}

func TestClient_Drivers_WhitelistBlacklistCombination(t *testing.T) {
c := testClient(t, func(c *config.Config) {
if c.Options == nil {
c.Options = make(map[string]string)
}

// Expected output is set difference (raw_exec)
c.Options["driver.whitelist"] = "raw_exec,exec"
c.Options["driver.blacklist"] = "exec"
})
defer c.Shutdown()

node := c.Node()
// Check expected present
if node.Attributes["driver.raw_exec"] == "" {
t.Fatalf("missing raw_exec driver")
}
// Check expected absent
if node.Attributes["driver.exec"] != "" {
t.Fatalf("exec driver loaded despite blacklist")
}
}

func TestClient_Register(t *testing.T) {
s1, _ := testServer(t, nil)
defer s1.Shutdown()
Expand Down
25 changes: 25 additions & 0 deletions website/source/docs/agent/configuration/client.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,19 @@ see the [drivers documentation](/docs/drivers/index.html).
}
```

- `"driver.blacklist"` `(string: "")` - Specifies a comma-separated list of
blacklisted drivers . If specified, drivers in the blacklist will be
disabled. If the blacklist is empty, all drivers are fingerprinted and enabled
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove the last sentences in both of these since it is pretty clear what the behavior will be and the fingerprinters/drivers still need to take into account the whitelist

where applicable.

```hcl
client {
options = {
"driver.blacklist" = "docker,qemu"
}
}
```

- `"env.blacklist"` `(string: see below)` - Specifies a comma-separated list of
environment variable keys not to pass to these tasks. Nomad passes the host
environment variables to `exec`, `raw_exec` and `java` tasks. If specified,
Expand Down Expand Up @@ -213,6 +226,18 @@ see the [drivers documentation](/docs/drivers/index.html).
}
```

- `"fingerprint.blacklist"` `(string: "")` - Specifies a comma-separated list of
blacklisted fingerprinters. If specified, any fingerprinters in the blacklist
will be disabled. If the blacklist is empty, all fingerprinters are used.

```hcl
client {
options = {
"fingerprint.blacklist" = "network"
}
}
```

### `reserved` Parameters

- `cpu` `(int: 0)` - Specifies the amount of CPU to reserve, in MHz.
Expand Down