Skip to content

Commit

Permalink
Merge branch 'main' into peteski22/VAULT-17149/consul-template-logs-json
Browse files Browse the repository at this point in the history
  • Loading branch information
peteski22 authored Nov 29, 2023
2 parents 77e4343 + 2dd3ab9 commit 88d6251
Show file tree
Hide file tree
Showing 60 changed files with 727 additions and 629 deletions.
32 changes: 28 additions & 4 deletions .github/workflows/test-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -286,14 +286,37 @@ jobs:
"runsc": {
"path": "/usr/local/bin/runsc",
"runtimeArgs": [
"--host-uds=all",
"--host-fifo=open"
"--host-uds=create"
]
}
}
}
EOF
sudo systemctl reload docker
- name: Install rootless Docker
# Enterprise repo runners do not allow sudo, so can't system packages there yet.
if: ${{ !inputs.enterprise }}
run: |
sudo apt-get install -y uidmap dbus-user-session
export FORCE_ROOTLESS_INSTALL=1
curl -fsSL https://get.docker.com/rootless | sh
mkdir -p ~/.config/docker/
tee ~/.config/docker/daemon.json <<EOF
{
"runtimes": {
"runsc": {
"path": "/usr/local/bin/runsc",
"runtimeArgs": [
"--host-uds=create",
"--ignore-cgroups"
]
}
}
}
EOF
systemctl --user restart docker
# Ensure the original rootful Docker install is still the default.
docker context use default
- id: run-go-tests
name: Run Go tests
timeout-minutes: ${{ fromJSON(env.TIMEOUT_IN_MINUTES) }}
Expand Down Expand Up @@ -356,8 +379,9 @@ jobs:
fi
fi
export VAULT_TEST_LOG_DIR=$(pwd)/test-results/go-test/logs-${{ matrix.id }}
mkdir -p $VAULT_TEST_LOG_DIR
VAULT_TEST_LOG_DIR="$(pwd)/test-results/go-test/logs-${{ matrix.id }}"
export VAULT_TEST_LOG_DIR
mkdir -p "$VAULT_TEST_LOG_DIR"
# shellcheck disable=SC2086 # can't quote RERUN_FAILS
Expand Down
1 change: 1 addition & 0 deletions api/sys_plugins_runtimes.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type RegisterPluginRuntimeInput struct {
CgroupParent string `json:"cgroup_parent,omitempty"`
CPU int64 `json:"cpu_nanos,omitempty"`
Memory int64 `json:"memory_bytes,omitempty"`
Rootless bool `json:"rootless,omitempty"`
}

// RegisterPluginRuntime registers the plugin with the given information.
Expand Down
3 changes: 3 additions & 0 deletions changelog/24236.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:improvement
plugins: Containerized plugins can be run fully rootless with the runsc runtime.
```
6 changes: 6 additions & 0 deletions changelog/24250.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:change
cli: `vault plugin info` and `vault plugin deregister` now require 2 positional arguments instead of accepting either 1 or 2.
```
```release-note:improvement
cli: Improved error messages for `vault plugin` sub-commands.
```
3 changes: 3 additions & 0 deletions changelog/24270.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:change
api: add the `enterprise` parameter to the `/sys/health` endpoint
```
48 changes: 39 additions & 9 deletions command/plugin_deregister.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
package command

import (
"context"
"fmt"
"net/http"
"strings"

semver "github.com/hashicorp/go-version"
Expand Down Expand Up @@ -83,18 +85,16 @@ func (c *PluginDeregisterCommand) Run(args []string) int {

var pluginNameRaw, pluginTypeRaw string
args = f.Args()
switch len(args) {
case 0:
c.UI.Error("Not enough arguments (expected 1, or 2, got 0)")
positionalArgsCount := len(args)
switch positionalArgsCount {
case 0, 1:
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 2, got %d)", positionalArgsCount))
return 1
case 1:
pluginTypeRaw = "unknown"
pluginNameRaw = args[0]
case 2:
pluginTypeRaw = args[0]
pluginNameRaw = args[1]
default:
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, or 2, got %d)", len(args)))
c.UI.Error(fmt.Sprintf("Too many arguments (expected 2, got %d)", positionalArgsCount))
return 1
}

Expand All @@ -118,7 +118,33 @@ func (c *PluginDeregisterCommand) Run(args []string) int {
}
}

if err := client.Sys().DeregisterPlugin(&api.DeregisterPluginInput{
// The deregister endpoint returns 200 if the plugin doesn't exist, so first
// try fetching the plugin to help improve info printed to the user.
// 404 => Return early with a descriptive message.
// Other error => Continue attempting to deregister the plugin anyway.
// Plugin exists but is builtin => Error early.
// Otherwise => If deregister succeeds, we can report that the plugin really
// was deregistered (and not just already absent).
var pluginExists bool
if info, err := client.Sys().GetPluginWithContext(context.Background(), &api.GetPluginInput{
Name: pluginName,
Type: pluginType,
Version: c.flagPluginVersion,
}); err != nil {
if respErr, ok := err.(*api.ResponseError); ok && respErr.StatusCode == http.StatusNotFound {
c.UI.Output(fmt.Sprintf("Plugin %q (type: %q, version %q) does not exist in the catalog", pluginName, pluginType, c.flagPluginVersion))
return 0
}
// Best-effort check, continue trying to deregister.
} else if info != nil {
if info.Builtin {
c.UI.Error(fmt.Sprintf("Plugin %q (type: %q) is a builtin plugin and cannot be deregistered", pluginName, pluginType))
return 2
}
pluginExists = true
}

if err := client.Sys().DeregisterPluginWithContext(context.Background(), &api.DeregisterPluginInput{
Name: pluginName,
Type: pluginType,
Version: c.flagPluginVersion,
Expand All @@ -127,6 +153,10 @@ func (c *PluginDeregisterCommand) Run(args []string) int {
return 2
}

c.UI.Output(fmt.Sprintf("Success! Deregistered plugin (if it was registered): %s", pluginName))
if pluginExists {
c.UI.Output(fmt.Sprintf("Success! Deregistered %s plugin: %s", pluginType, pluginName))
} else {
c.UI.Output(fmt.Sprintf("Success! Deregistered %s plugin (if it was registered): %s", pluginType, pluginName))
}
return 0
}
31 changes: 27 additions & 4 deletions command/plugin_deregister_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
}{
{
"not_enough_args",
nil,
[]string{"foo"},
"Not enough arguments",
1,
},
Expand Down Expand Up @@ -109,7 +109,7 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
t.Errorf("expected %d to be %d", code, exp)
}

expected := "Success! Deregistered plugin (if it was registered): "
expected := "Success! Deregistered auth plugin: "
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
if !strings.Contains(combined, expected) {
t.Errorf("expected %q to contain %q", combined, expected)
Expand Down Expand Up @@ -159,7 +159,7 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
t.Errorf("expected %d to be %d", code, exp)
}

expected := "Success! Deregistered plugin (if it was registered): "
expected := "Success! Deregistered auth plugin: "
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
if !strings.Contains(combined, expected) {
t.Errorf("expected %q to contain %q", combined, expected)
Expand Down Expand Up @@ -206,7 +206,7 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
t.Errorf("expected %d to be %d", code, exp)
}

expected := "Success! Deregistered plugin (if it was registered): "
expected := "does not exist in the catalog"
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
if !strings.Contains(combined, expected) {
t.Errorf("expected %q to contain %q", combined, expected)
Expand All @@ -230,6 +230,29 @@ func TestPluginDeregisterCommand_Run(t *testing.T) {
}
})

t.Run("deregister builtin", func(t *testing.T) {
t.Parallel()

pluginDir, cleanup := corehelpers.MakeTestPluginDir(t)
defer cleanup(t)

client, _, closer := testVaultServerPluginDir(t, pluginDir)
defer closer()

ui, cmd := testPluginDeregisterCommand(t)
cmd.client = client

expected := "is a builtin plugin"
if code := cmd.Run([]string{
consts.PluginTypeCredential.String(),
"github",
}); code != 2 {
t.Errorf("expected %d to be %d", code, 2)
} else if !strings.Contains(ui.ErrorWriter.String(), expected) {
t.Errorf("expected %q to contain %q", ui.ErrorWriter.String(), expected)
}
})

t.Run("communication_failure", func(t *testing.T) {
t.Parallel()

Expand Down
20 changes: 8 additions & 12 deletions command/plugin_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,23 +77,19 @@ func (c *PluginInfoCommand) Run(args []string) int {

var pluginNameRaw, pluginTypeRaw string
args = f.Args()
positionalArgsCount := len(args)
switch {
case len(args) < 1:
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1 or 2, got %d)", len(args)))
case positionalArgsCount < 2:
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 2, got %d)", positionalArgsCount))
return 1
case len(args) > 2:
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1 or 2, got %d)", len(args)))
case positionalArgsCount > 2:
c.UI.Error(fmt.Sprintf("Too many arguments (expected 2, got %d)", positionalArgsCount))
return 1

// These cases should come after invalid cases have been checked
case len(args) == 1:
pluginTypeRaw = "unknown"
pluginNameRaw = args[0]
case len(args) == 2:
pluginTypeRaw = args[0]
pluginNameRaw = args[1]
}

pluginTypeRaw = args[0]
pluginNameRaw = args[1]

client, err := c.Client()
if err != nil {
c.UI.Error(err.Error())
Expand Down
6 changes: 6 additions & 0 deletions command/plugin_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ func TestPluginInfoCommand_Run(t *testing.T) {
out string
code int
}{
{
"not_enough_args",
[]string{"foo"},
"Not enough arguments",
1,
},
{
"too_many_args",
[]string{"foo", "bar", "fizz"},
Expand Down
8 changes: 6 additions & 2 deletions command/plugin_reload.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,16 @@ func (c *PluginReloadCommand) Run(args []string) int {
return 1
}

positionalArgs := len(f.Args())
switch {
case positionalArgs != 0:
c.UI.Error(fmt.Sprintf("Too many arguments (expected 0, got %d)", positionalArgs))
return 1
case c.plugin == "" && len(c.mounts) == 0:
c.UI.Error(fmt.Sprintf("Not enough arguments (expected 1, got %d)", len(args)))
c.UI.Error("No plugins specified, must specify exactly one of -plugin or -mounts")
return 1
case c.plugin != "" && len(c.mounts) > 0:
c.UI.Error(fmt.Sprintf("Too many arguments (expected 1, got %d)", len(args)))
c.UI.Error("Must specify exactly one of -plugin or -mounts")
return 1
case c.scope != "" && c.scope != "global":
c.UI.Error(fmt.Sprintf("Invalid reload scope: %s", c.scope))
Expand Down
6 changes: 3 additions & 3 deletions command/plugin_reload_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ func TestPluginReloadCommand_Run(t *testing.T) {
{
"not_enough_args",
nil,
"Not enough arguments",
"No plugins specified, must specify exactly one of -plugin or -mounts",
1,
},
{
"too_many_args",
[]string{"-plugin", "foo", "-mounts", "bar"},
"Too many arguments",
"Must specify exactly one of -plugin or -mounts",
1,
},
}
Expand Down Expand Up @@ -147,7 +147,7 @@ func TestPluginReloadStatusCommand_Run(t *testing.T) {
client, closer := testVaultServer(t)
defer closer()

ui, cmd := testPluginReloadCommand(t)
ui, cmd := testPluginReloadStatusCommand(t)
cmd.client = client

args := append([]string{}, tc.args...)
Expand Down
11 changes: 11 additions & 0 deletions command/plugin_runtime_register.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type PluginRuntimeRegisterCommand struct {
flagCgroupParent string
flagCPUNanos int64
flagMemoryBytes int64
flagRootless bool
}

func (c *PluginRuntimeRegisterCommand) Synopsis() string {
Expand Down Expand Up @@ -88,6 +89,15 @@ func (c *PluginRuntimeRegisterCommand) Flags() *FlagSets {
Usage: "Memory limit to set per container in bytes. Defaults to no limit.",
})

f.BoolVar(&BoolVar{
Name: "rootless",
Target: &c.flagRootless,
Completion: complete.PredictAnything,
Usage: "Whether the container runtime is configured to run as a " +
"non-privileged (non-root) user. Required if the plugin container " +
"image is also configured to run as a non-root user.",
})

return set
}

Expand Down Expand Up @@ -151,6 +161,7 @@ func (c *PluginRuntimeRegisterCommand) Run(args []string) int {
CgroupParent: cgroupParent,
CPU: c.flagCPUNanos,
Memory: c.flagMemoryBytes,
Rootless: c.flagRootless,
}); err != nil {
c.UI.Error(fmt.Sprintf("Error registering plugin runtime %s: %s", runtimeName, err))
return 2
Expand Down
8 changes: 6 additions & 2 deletions command/plugin_runtime_register_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ func TestPluginRuntimeFlagParsing(t *testing.T) {
cgroupParent string
cpu int64
memory int64
args []string
rootless bool
expectedPayload string
}{
"minimal": {
Expand All @@ -145,7 +145,8 @@ func TestPluginRuntimeFlagParsing(t *testing.T) {
ociRuntime: "runtime",
cpu: 5678,
memory: 1234,
expectedPayload: `{"type":1,"cgroup_parent":"/cpulimit/","memory_bytes":1234,"cpu_nanos":5678,"oci_runtime":"runtime"}`,
rootless: true,
expectedPayload: `{"type":1,"cgroup_parent":"/cpulimit/","memory_bytes":1234,"cpu_nanos":5678,"oci_runtime":"runtime","rootless":true}`,
},
} {
tc := tc
Expand All @@ -167,6 +168,9 @@ func TestPluginRuntimeFlagParsing(t *testing.T) {
if tc.cpu != 0 {
args = append(args, fmt.Sprintf("-cpu_nanos=%d", tc.cpu))
}
if tc.rootless {
args = append(args, "-rootless=true")
}

if tc.runtimeType != api.PluginRuntimeTypeUnsupported {
args = append(args, "-type="+tc.runtimeType.String())
Expand Down
5 changes: 2 additions & 3 deletions command/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2572,6 +2572,8 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
for _, c := range config.Seals {
if !c.Disabled {
allSealsDisabled = false
} else if c.Type == vault.SealConfigTypeShamir.String() {
return nil, errors.New("shamir seals cannot be set disabled (they should simply not be set)")
}
}
// If all seals are disabled assume they want to
Expand Down Expand Up @@ -2722,9 +2724,6 @@ func setSeal(c *ServerCommand, config *server.Config, infoKeys []string, info ma
return nil, errors.Join(sealConfigWarning, errors.New("no enabled Seals in configuration"))
case configuredSeals == 0:
return nil, errors.Join(sealConfigWarning, errors.New("no seals were successfully initialized"))
case containsShamir(enabledSealWrappers) && containsShamir(disabledSealWrappers):
return nil, errors.Join(sealConfigWarning, errors.New("shamir seals cannot be set disabled (they should simply not be set)"))

case len(enabledSealWrappers) == 1 && containsShamir(enabledSealWrappers):
// The barrier seal is Shamir. If there are any disabled seals, then we put them all in the same
// autoSeal.
Expand Down
Loading

0 comments on commit 88d6251

Please sign in to comment.