Add WithOptions methods to audit/auth enabling (#2383)
This commit is contained in:
parent
0044ea8917
commit
e0c9bfd926
|
@ -3,6 +3,7 @@ package api
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fatih/structs"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -71,14 +72,19 @@ func (c *Sys) ListAudit() (map[string]*Audit, error) {
|
||||||
return mounts, nil
|
return mounts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED: Use EnableAuditWithOptions instead
|
||||||
func (c *Sys) EnableAudit(
|
func (c *Sys) EnableAudit(
|
||||||
path string, auditType string, desc string, opts map[string]string) error {
|
path string, auditType string, desc string, opts map[string]string) error {
|
||||||
body := map[string]interface{}{
|
return c.EnableAuditWithOptions(path, &EnableAuditOptions{
|
||||||
"type": auditType,
|
Type: auditType,
|
||||||
"description": desc,
|
Description: desc,
|
||||||
"options": opts,
|
Options: opts,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Sys) EnableAuditWithOptions(path string, options *EnableAuditOptions) error {
|
||||||
|
body := structs.Map(options)
|
||||||
|
|
||||||
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit/%s", path))
|
r := c.c.NewRequest("PUT", fmt.Sprintf("/v1/sys/audit/%s", path))
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
if err := r.SetJSONBody(body); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -106,9 +112,17 @@ func (c *Sys) DisableAudit(path string) error {
|
||||||
// individually documented because the map almost directly to the raw HTTP API
|
// individually documented because the map almost directly to the raw HTTP API
|
||||||
// documentation. Please refer to that documentation for more details.
|
// documentation. Please refer to that documentation for more details.
|
||||||
|
|
||||||
|
type EnableAuditOptions struct {
|
||||||
|
Type string `json:"type" structs:"type"`
|
||||||
|
Description string `json:"description" structs:"description"`
|
||||||
|
Options map[string]string `json:"options" structs:"options"`
|
||||||
|
Local bool `json:"local" structs:"local"`
|
||||||
|
}
|
||||||
|
|
||||||
type Audit struct {
|
type Audit struct {
|
||||||
Path string
|
Path string
|
||||||
Type string
|
Type string
|
||||||
Description string
|
Description string
|
||||||
Options map[string]string
|
Options map[string]string
|
||||||
|
Local bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package api
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/fatih/structs"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -42,12 +43,17 @@ func (c *Sys) ListAuth() (map[string]*AuthMount, error) {
|
||||||
return mounts, nil
|
return mounts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DEPRECATED: Use EnableAuthWithOptions instead
|
||||||
func (c *Sys) EnableAuth(path, authType, desc string) error {
|
func (c *Sys) EnableAuth(path, authType, desc string) error {
|
||||||
body := map[string]string{
|
return c.EnableAuthWithOptions(path, &EnableAuthOptions{
|
||||||
"type": authType,
|
Type: authType,
|
||||||
"description": desc,
|
Description: desc,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Sys) EnableAuthWithOptions(path string, options *EnableAuthOptions) error {
|
||||||
|
body := structs.Map(options)
|
||||||
|
|
||||||
r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/auth/%s", path))
|
r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/auth/%s", path))
|
||||||
if err := r.SetJSONBody(body); err != nil {
|
if err := r.SetJSONBody(body); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -75,10 +81,17 @@ func (c *Sys) DisableAuth(path string) error {
|
||||||
// individually documentd because the map almost directly to the raw HTTP API
|
// individually documentd because the map almost directly to the raw HTTP API
|
||||||
// documentation. Please refer to that documentation for more details.
|
// documentation. Please refer to that documentation for more details.
|
||||||
|
|
||||||
|
type EnableAuthOptions struct {
|
||||||
|
Type string `json:"type" structs:"type"`
|
||||||
|
Description string `json:"description" structs:"description"`
|
||||||
|
Local bool `json:"local" structs:"local"`
|
||||||
|
}
|
||||||
|
|
||||||
type AuthMount struct {
|
type AuthMount struct {
|
||||||
Type string `json:"type" structs:"type" mapstructure:"type"`
|
Type string `json:"type" structs:"type" mapstructure:"type"`
|
||||||
Description string `json:"description" structs:"description" mapstructure:"description"`
|
Description string `json:"description" structs:"description" mapstructure:"description"`
|
||||||
Config AuthConfigOutput `json:"config" structs:"config" mapstructure:"config"`
|
Config AuthConfigOutput `json:"config" structs:"config" mapstructure:"config"`
|
||||||
|
Local bool `json:"local" structs:"local" mapstructure:"local"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthConfigOutput struct {
|
type AuthConfigOutput struct {
|
||||||
|
|
|
@ -123,6 +123,7 @@ type MountInput struct {
|
||||||
Type string `json:"type" structs:"type"`
|
Type string `json:"type" structs:"type"`
|
||||||
Description string `json:"description" structs:"description"`
|
Description string `json:"description" structs:"description"`
|
||||||
Config MountConfigInput `json:"config" structs:"config"`
|
Config MountConfigInput `json:"config" structs:"config"`
|
||||||
|
Local bool `json:"local" structs:"local"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MountConfigInput struct {
|
type MountConfigInput struct {
|
||||||
|
@ -134,6 +135,7 @@ type MountOutput struct {
|
||||||
Type string `json:"type" structs:"type"`
|
Type string `json:"type" structs:"type"`
|
||||||
Description string `json:"description" structs:"description"`
|
Description string `json:"description" structs:"description"`
|
||||||
Config MountConfigOutput `json:"config" structs:"config"`
|
Config MountConfigOutput `json:"config" structs:"config"`
|
||||||
|
Local bool `json:"local" structs:"local"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MountConfigOutput struct {
|
type MountConfigOutput struct {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package command
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/http"
|
"github.com/hashicorp/vault/http"
|
||||||
"github.com/hashicorp/vault/meta"
|
"github.com/hashicorp/vault/meta"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
|
@ -44,3 +45,42 @@ func TestAuditDisable(t *testing.T) {
|
||||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuditDisableWithOptions(t *testing.T) {
|
||||||
|
core, _, token := vault.TestCoreUnsealed(t)
|
||||||
|
ln, addr := http.TestServer(t, core)
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &AuditDisableCommand{
|
||||||
|
Meta: meta.Meta{
|
||||||
|
ClientToken: token,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-address", addr,
|
||||||
|
"noop",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run once to get the client
|
||||||
|
c.Run(args)
|
||||||
|
|
||||||
|
// Get the client
|
||||||
|
client, err := c.Client()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
if err := client.Sys().EnableAuditWithOptions("noop", &api.EnableAuditOptions{
|
||||||
|
Type: "noop",
|
||||||
|
Description: "noop",
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run again
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/helper/kv-builder"
|
"github.com/hashicorp/vault/helper/kv-builder"
|
||||||
"github.com/hashicorp/vault/meta"
|
"github.com/hashicorp/vault/meta"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
|
@ -21,9 +22,11 @@ type AuditEnableCommand struct {
|
||||||
|
|
||||||
func (c *AuditEnableCommand) Run(args []string) int {
|
func (c *AuditEnableCommand) Run(args []string) int {
|
||||||
var desc, path string
|
var desc, path string
|
||||||
|
var local bool
|
||||||
flags := c.Meta.FlagSet("audit-enable", meta.FlagSetDefault)
|
flags := c.Meta.FlagSet("audit-enable", meta.FlagSetDefault)
|
||||||
flags.StringVar(&desc, "description", "", "")
|
flags.StringVar(&desc, "description", "", "")
|
||||||
flags.StringVar(&path, "path", "", "")
|
flags.StringVar(&path, "path", "", "")
|
||||||
|
flags.BoolVar(&local, "local", false, "")
|
||||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
if err := flags.Parse(args); err != nil {
|
if err := flags.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
|
@ -68,7 +71,12 @@ func (c *AuditEnableCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
err = client.Sys().EnableAudit(path, auditType, desc, opts)
|
err = client.Sys().EnableAuditWithOptions(path, &api.EnableAuditOptions{
|
||||||
|
Type: auditType,
|
||||||
|
Description: desc,
|
||||||
|
Options: opts,
|
||||||
|
Local: local,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"Error enabling audit backend: %s", err))
|
"Error enabling audit backend: %s", err))
|
||||||
|
@ -113,6 +121,9 @@ Audit Enable Options:
|
||||||
is purely for referencing this audit backend. By
|
is purely for referencing this audit backend. By
|
||||||
default this will be the backend type.
|
default this will be the backend type.
|
||||||
|
|
||||||
|
-local Mark the mount as a local mount. Local mounts
|
||||||
|
are not replicated nor (if a secondary)
|
||||||
|
removed by replication.
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,16 +48,19 @@ func (c *AuditListCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
columns := []string{"Path | Type | Description | Options"}
|
columns := []string{"Path | Type | Description | Replication Behavior | Options"}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
audit := audits[path]
|
audit := audits[path]
|
||||||
opts := make([]string, 0, len(audit.Options))
|
opts := make([]string, 0, len(audit.Options))
|
||||||
for k, v := range audit.Options {
|
for k, v := range audit.Options {
|
||||||
opts = append(opts, k+"="+v)
|
opts = append(opts, k+"="+v)
|
||||||
}
|
}
|
||||||
|
replicatedBehavior := "replicated"
|
||||||
|
if audit.Local {
|
||||||
|
replicatedBehavior = "local"
|
||||||
|
}
|
||||||
columns = append(columns, fmt.Sprintf(
|
columns = append(columns, fmt.Sprintf(
|
||||||
"%s | %s | %s | %s", audit.Path, audit.Type, audit.Description, strings.Join(opts, " ")))
|
"%s | %s | %s | %s | %s", audit.Path, audit.Type, audit.Description, replicatedBehavior, strings.Join(opts, " ")))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Ui.Output(columnize.SimpleFormat(columns))
|
c.Ui.Output(columnize.SimpleFormat(columns))
|
||||||
|
|
|
@ -3,6 +3,7 @@ package command
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/http"
|
"github.com/hashicorp/vault/http"
|
||||||
"github.com/hashicorp/vault/meta"
|
"github.com/hashicorp/vault/meta"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
|
@ -34,7 +35,11 @@ func TestAuditList(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("err: %#v", err)
|
t.Fatalf("err: %#v", err)
|
||||||
}
|
}
|
||||||
if err := client.Sys().EnableAudit("foo", "noop", "", nil); err != nil {
|
if err := client.Sys().EnableAuditWithOptions("foo", &api.EnableAuditOptions{
|
||||||
|
Type: "noop",
|
||||||
|
Description: "noop",
|
||||||
|
Options: nil,
|
||||||
|
}); err != nil {
|
||||||
t.Fatalf("err: %#v", err)
|
t.Fatalf("err: %#v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -281,7 +281,7 @@ func (c *AuthCommand) listMethods() int {
|
||||||
}
|
}
|
||||||
sort.Strings(paths)
|
sort.Strings(paths)
|
||||||
|
|
||||||
columns := []string{"Path | Type | Default TTL | Max TTL | Description"}
|
columns := []string{"Path | Type | Default TTL | Max TTL | Replication Behavior | Description"}
|
||||||
for _, path := range paths {
|
for _, path := range paths {
|
||||||
auth := auth[path]
|
auth := auth[path]
|
||||||
defTTL := "system"
|
defTTL := "system"
|
||||||
|
@ -292,8 +292,12 @@ func (c *AuthCommand) listMethods() int {
|
||||||
if auth.Config.MaxLeaseTTL != 0 {
|
if auth.Config.MaxLeaseTTL != 0 {
|
||||||
maxTTL = strconv.Itoa(auth.Config.MaxLeaseTTL)
|
maxTTL = strconv.Itoa(auth.Config.MaxLeaseTTL)
|
||||||
}
|
}
|
||||||
|
replicatedBehavior := "replicated"
|
||||||
|
if auth.Local {
|
||||||
|
replicatedBehavior = "local"
|
||||||
|
}
|
||||||
columns = append(columns, fmt.Sprintf(
|
columns = append(columns, fmt.Sprintf(
|
||||||
"%s | %s | %s | %s | %s", path, auth.Type, defTTL, maxTTL, auth.Description))
|
"%s | %s | %s | %s | %s | %s", path, auth.Type, defTTL, maxTTL, replicatedBehavior, auth.Description))
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Ui.Output(columnize.SimpleFormat(columns))
|
c.Ui.Output(columnize.SimpleFormat(columns))
|
||||||
|
|
|
@ -3,6 +3,7 @@ package command
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/http"
|
"github.com/hashicorp/vault/http"
|
||||||
"github.com/hashicorp/vault/meta"
|
"github.com/hashicorp/vault/meta"
|
||||||
"github.com/hashicorp/vault/vault"
|
"github.com/hashicorp/vault/vault"
|
||||||
|
@ -52,3 +53,50 @@ func TestAuthDisable(t *testing.T) {
|
||||||
t.Fatal("should not have noop mount")
|
t.Fatal("should not have noop mount")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAuthDisableWithOptions(t *testing.T) {
|
||||||
|
core, _, token := vault.TestCoreUnsealed(t)
|
||||||
|
ln, addr := http.TestServer(t, core)
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
ui := new(cli.MockUi)
|
||||||
|
c := &AuthDisableCommand{
|
||||||
|
Meta: meta.Meta{
|
||||||
|
ClientToken: token,
|
||||||
|
Ui: ui,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{
|
||||||
|
"-address", addr,
|
||||||
|
"noop",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the command once to setup the client, it will fail
|
||||||
|
c.Run(args)
|
||||||
|
|
||||||
|
client, err := c.Client()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.Sys().EnableAuthWithOptions("noop", &api.EnableAuthOptions{
|
||||||
|
Type: "noop",
|
||||||
|
Description: "",
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatalf("err: %#v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if code := c.Run(args); code != 0 {
|
||||||
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
mounts, err := client.Sys().ListAuth()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := mounts["noop"]; ok {
|
||||||
|
t.Fatal("should not have noop mount")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/api"
|
||||||
"github.com/hashicorp/vault/meta"
|
"github.com/hashicorp/vault/meta"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,9 +15,11 @@ type AuthEnableCommand struct {
|
||||||
|
|
||||||
func (c *AuthEnableCommand) Run(args []string) int {
|
func (c *AuthEnableCommand) Run(args []string) int {
|
||||||
var description, path string
|
var description, path string
|
||||||
|
var local bool
|
||||||
flags := c.Meta.FlagSet("auth-enable", meta.FlagSetDefault)
|
flags := c.Meta.FlagSet("auth-enable", meta.FlagSetDefault)
|
||||||
flags.StringVar(&description, "description", "", "")
|
flags.StringVar(&description, "description", "", "")
|
||||||
flags.StringVar(&path, "path", "", "")
|
flags.StringVar(&path, "path", "", "")
|
||||||
|
flags.BoolVar(&local, "local", false, "")
|
||||||
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
flags.Usage = func() { c.Ui.Error(c.Help()) }
|
||||||
if err := flags.Parse(args); err != nil {
|
if err := flags.Parse(args); err != nil {
|
||||||
return 1
|
return 1
|
||||||
|
@ -44,7 +47,11 @@ func (c *AuthEnableCommand) Run(args []string) int {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.Sys().EnableAuth(path, authType, description); err != nil {
|
if err := client.Sys().EnableAuthWithOptions(path, &api.EnableAuthOptions{
|
||||||
|
Type: authType,
|
||||||
|
Description: description,
|
||||||
|
Local: local,
|
||||||
|
}); err != nil {
|
||||||
c.Ui.Error(fmt.Sprintf(
|
c.Ui.Error(fmt.Sprintf(
|
||||||
"Error: %s", err))
|
"Error: %s", err))
|
||||||
return 2
|
return 2
|
||||||
|
@ -82,6 +89,9 @@ Auth Enable Options:
|
||||||
to the type of the mount. This will make the auth
|
to the type of the mount. This will make the auth
|
||||||
provider available at "/auth/<path>"
|
provider available at "/auth/<path>"
|
||||||
|
|
||||||
|
-local Mark the mount as a local mount. Local mounts
|
||||||
|
are not replicated nor (if a secondary)
|
||||||
|
removed by replication.
|
||||||
`
|
`
|
||||||
return strings.TrimSpace(helpText)
|
return strings.TrimSpace(helpText)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue