Add WithOptions methods to audit/auth enabling (#2383)

This commit is contained in:
Jeff Mitchell 2017-02-16 11:37:27 -05:00 committed by GitHub
parent 0044ea8917
commit e0c9bfd926
10 changed files with 167 additions and 17 deletions

View File

@ -3,6 +3,7 @@ package api
import (
"fmt"
"github.com/fatih/structs"
"github.com/mitchellh/mapstructure"
)
@ -71,13 +72,18 @@ func (c *Sys) ListAudit() (map[string]*Audit, error) {
return mounts, nil
}
// DEPRECATED: Use EnableAuditWithOptions instead
func (c *Sys) EnableAudit(
path string, auditType string, desc string, opts map[string]string) error {
body := map[string]interface{}{
"type": auditType,
"description": desc,
"options": opts,
}
return c.EnableAuditWithOptions(path, &EnableAuditOptions{
Type: auditType,
Description: desc,
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))
if err := r.SetJSONBody(body); err != nil {
@ -106,9 +112,17 @@ func (c *Sys) DisableAudit(path string) error {
// individually documented because the map almost directly to the raw HTTP API
// 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 {
Path string
Type string
Description string
Options map[string]string
Local bool
}

View File

@ -3,6 +3,7 @@ package api
import (
"fmt"
"github.com/fatih/structs"
"github.com/mitchellh/mapstructure"
)
@ -42,11 +43,16 @@ func (c *Sys) ListAuth() (map[string]*AuthMount, error) {
return mounts, nil
}
// DEPRECATED: Use EnableAuthWithOptions instead
func (c *Sys) EnableAuth(path, authType, desc string) error {
body := map[string]string{
"type": authType,
"description": desc,
}
return c.EnableAuthWithOptions(path, &EnableAuthOptions{
Type: authType,
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))
if err := r.SetJSONBody(body); err != nil {
@ -75,10 +81,17 @@ func (c *Sys) DisableAuth(path string) error {
// individually documentd because the map almost directly to the raw HTTP API
// 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 string `json:"type" structs:"type" mapstructure:"type"`
Description string `json:"description" structs:"description" mapstructure:"description"`
Config AuthConfigOutput `json:"config" structs:"config" mapstructure:"config"`
Local bool `json:"local" structs:"local" mapstructure:"local"`
}
type AuthConfigOutput struct {

View File

@ -123,6 +123,7 @@ type MountInput struct {
Type string `json:"type" structs:"type"`
Description string `json:"description" structs:"description"`
Config MountConfigInput `json:"config" structs:"config"`
Local bool `json:"local" structs:"local"`
}
type MountConfigInput struct {
@ -134,6 +135,7 @@ type MountOutput struct {
Type string `json:"type" structs:"type"`
Description string `json:"description" structs:"description"`
Config MountConfigOutput `json:"config" structs:"config"`
Local bool `json:"local" structs:"local"`
}
type MountConfigOutput struct {

View File

@ -3,6 +3,7 @@ package command
import (
"testing"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/meta"
"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())
}
}
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())
}
}

View File

@ -6,6 +6,7 @@ import (
"os"
"strings"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/helper/kv-builder"
"github.com/hashicorp/vault/meta"
"github.com/mitchellh/mapstructure"
@ -21,9 +22,11 @@ type AuditEnableCommand struct {
func (c *AuditEnableCommand) Run(args []string) int {
var desc, path string
var local bool
flags := c.Meta.FlagSet("audit-enable", meta.FlagSetDefault)
flags.StringVar(&desc, "description", "", "")
flags.StringVar(&path, "path", "", "")
flags.BoolVar(&local, "local", false, "")
flags.Usage = func() { c.Ui.Error(c.Help()) }
if err := flags.Parse(args); err != nil {
return 1
@ -68,7 +71,12 @@ func (c *AuditEnableCommand) Run(args []string) int {
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 {
c.Ui.Error(fmt.Sprintf(
"Error enabling audit backend: %s", err))
@ -113,6 +121,9 @@ Audit Enable Options:
is purely for referencing this audit backend. By
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)
}

View File

@ -48,16 +48,19 @@ func (c *AuditListCommand) Run(args []string) int {
}
sort.Strings(paths)
columns := []string{"Path | Type | Description | Options"}
columns := []string{"Path | Type | Description | Replication Behavior | Options"}
for _, path := range paths {
audit := audits[path]
opts := make([]string, 0, len(audit.Options))
for k, v := range audit.Options {
opts = append(opts, k+"="+v)
}
replicatedBehavior := "replicated"
if audit.Local {
replicatedBehavior = "local"
}
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))

View File

@ -3,6 +3,7 @@ package command
import (
"testing"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/meta"
"github.com/hashicorp/vault/vault"
@ -34,7 +35,11 @@ func TestAuditList(t *testing.T) {
if err != nil {
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)
}

View File

@ -281,7 +281,7 @@ func (c *AuthCommand) listMethods() int {
}
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 {
auth := auth[path]
defTTL := "system"
@ -292,8 +292,12 @@ func (c *AuthCommand) listMethods() int {
if auth.Config.MaxLeaseTTL != 0 {
maxTTL = strconv.Itoa(auth.Config.MaxLeaseTTL)
}
replicatedBehavior := "replicated"
if auth.Local {
replicatedBehavior = "local"
}
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))

View File

@ -3,6 +3,7 @@ package command
import (
"testing"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/meta"
"github.com/hashicorp/vault/vault"
@ -52,3 +53,50 @@ func TestAuthDisable(t *testing.T) {
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")
}
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"strings"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/meta"
)
@ -14,9 +15,11 @@ type AuthEnableCommand struct {
func (c *AuthEnableCommand) Run(args []string) int {
var description, path string
var local bool
flags := c.Meta.FlagSet("auth-enable", meta.FlagSetDefault)
flags.StringVar(&description, "description", "", "")
flags.StringVar(&path, "path", "", "")
flags.BoolVar(&local, "local", false, "")
flags.Usage = func() { c.Ui.Error(c.Help()) }
if err := flags.Parse(args); err != nil {
return 1
@ -44,7 +47,11 @@ func (c *AuthEnableCommand) Run(args []string) int {
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(
"Error: %s", err))
return 2
@ -82,6 +89,9 @@ Auth Enable Options:
to the type of the mount. This will make the auth
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)
}