acl: add DisplayName field to auth methods (#7769)

Also add a few missing acl fields in the api.
pull/7725/head
R.B. Boyer 2020-05-04 15:18:25 -05:00 committed by GitHub
parent b5eab19183
commit ca52ba7068
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 224 additions and 50 deletions

View File

@ -3336,6 +3336,7 @@ func TestACLEndpoint_AuthMethodSet(t *testing.T) {
t.Run("Update - allow type to default", func(t *testing.T) { t.Run("Update - allow type to default", func(t *testing.T) {
reqMethod := newAuthMethod("test") reqMethod := newAuthMethod("test")
reqMethod.DisplayName = "updated display name 1"
reqMethod.Description = "test modified 1" reqMethod.Description = "test modified 1"
reqMethod.Type = "" // unset reqMethod.Type = "" // unset
@ -3355,12 +3356,14 @@ func TestACLEndpoint_AuthMethodSet(t *testing.T) {
method := methodResp.AuthMethod method := methodResp.AuthMethod
require.Equal(t, method.Name, "test") require.Equal(t, method.Name, "test")
require.Equal(t, method.DisplayName, "updated display name 1")
require.Equal(t, method.Description, "test modified 1") require.Equal(t, method.Description, "test modified 1")
require.Equal(t, method.Type, "testing") require.Equal(t, method.Type, "testing")
}) })
t.Run("Update - specify type", func(t *testing.T) { t.Run("Update - specify type", func(t *testing.T) {
reqMethod := newAuthMethod("test") reqMethod := newAuthMethod("test")
reqMethod.DisplayName = "updated display name 2"
reqMethod.Description = "test modified 2" reqMethod.Description = "test modified 2"
req := structs.ACLAuthMethodSetRequest{ req := structs.ACLAuthMethodSetRequest{
@ -3379,6 +3382,7 @@ func TestACLEndpoint_AuthMethodSet(t *testing.T) {
method := methodResp.AuthMethod method := methodResp.AuthMethod
require.Equal(t, method.Name, "test") require.Equal(t, method.Name, "test")
require.Equal(t, method.DisplayName, "updated display name 2")
require.Equal(t, method.Description, "test modified 2") require.Equal(t, method.Description, "test modified 2")
require.Equal(t, method.Type, "testing") require.Equal(t, method.Type, "testing")
}) })

View File

@ -994,8 +994,9 @@ func (rules ACLBindingRules) Sort() {
type ACLAuthMethodListStub struct { type ACLAuthMethodListStub struct {
Name string Name string
Description string
Type string Type string
DisplayName string `json:",omitempty"`
Description string `json:",omitempty"`
CreateIndex uint64 CreateIndex uint64
ModifyIndex uint64 ModifyIndex uint64
EnterpriseMeta EnterpriseMeta
@ -1004,8 +1005,9 @@ type ACLAuthMethodListStub struct {
func (p *ACLAuthMethod) Stub() *ACLAuthMethodListStub { func (p *ACLAuthMethod) Stub() *ACLAuthMethodListStub {
return &ACLAuthMethodListStub{ return &ACLAuthMethodListStub{
Name: p.Name, Name: p.Name,
Description: p.Description,
Type: p.Type, Type: p.Type,
DisplayName: p.DisplayName,
Description: p.Description,
CreateIndex: p.CreateIndex, CreateIndex: p.CreateIndex,
ModifyIndex: p.ModifyIndex, ModifyIndex: p.ModifyIndex,
EnterpriseMeta: p.EnterpriseMeta, EnterpriseMeta: p.EnterpriseMeta,
@ -1038,8 +1040,13 @@ type ACLAuthMethod struct {
// Immutable once set and only settable during create. // Immutable once set and only settable during create.
Type string Type string
// DisplayName is an optional name to use instead of the Name field when
// displaying information about this auth method in any kind of user
// interface.
DisplayName string `json:",omitempty"`
// Description is just an optional bunch of explanatory text. // Description is just an optional bunch of explanatory text.
Description string Description string `json:",omitempty"`
// Configuration is arbitrary configuration for the auth method. This // Configuration is arbitrary configuration for the auth method. This
// should only contain primitive values and containers (such as lists and // should only contain primitive values and containers (such as lists and

View File

@ -37,6 +37,7 @@ type ACLToken struct {
Roles []*ACLTokenRoleLink `json:",omitempty"` Roles []*ACLTokenRoleLink `json:",omitempty"`
ServiceIdentities []*ACLServiceIdentity `json:",omitempty"` ServiceIdentities []*ACLServiceIdentity `json:",omitempty"`
Local bool Local bool
AuthMethod string `json:",omitempty"`
ExpirationTTL time.Duration `json:",omitempty"` ExpirationTTL time.Duration `json:",omitempty"`
ExpirationTime *time.Time `json:",omitempty"` ExpirationTime *time.Time `json:",omitempty"`
CreateTime time.Time `json:",omitempty"` CreateTime time.Time `json:",omitempty"`
@ -60,6 +61,7 @@ type ACLTokenListEntry struct {
Roles []*ACLTokenRoleLink `json:",omitempty"` Roles []*ACLTokenRoleLink `json:",omitempty"`
ServiceIdentities []*ACLServiceIdentity `json:",omitempty"` ServiceIdentities []*ACLServiceIdentity `json:",omitempty"`
Local bool Local bool
AuthMethod string `json:",omitempty"`
ExpirationTime *time.Time `json:",omitempty"` ExpirationTime *time.Time `json:",omitempty"`
CreateTime time.Time CreateTime time.Time
Hash []byte Hash []byte
@ -180,7 +182,8 @@ type ACLBindingRule struct {
type ACLAuthMethod struct { type ACLAuthMethod struct {
Name string Name string
Type string Type string
Description string DisplayName string `json:",omitempty"`
Description string `json:",omitempty"`
// Configuration is arbitrary configuration for the auth method. This // Configuration is arbitrary configuration for the auth method. This
// should only contain primitive values and containers (such as lists and // should only contain primitive values and containers (such as lists and
@ -198,7 +201,8 @@ type ACLAuthMethod struct {
type ACLAuthMethodListEntry struct { type ACLAuthMethodListEntry struct {
Name string Name string
Type string Type string
Description string DisplayName string `json:",omitempty"`
Description string `json:",omitempty"`
CreateIndex uint64 CreateIndex uint64
ModifyIndex uint64 ModifyIndex uint64

View File

@ -27,6 +27,7 @@ type cmd struct {
authMethodType string authMethodType string
name string name string
displayName string
description string description string
k8sHost string k8sHost string
@ -62,6 +63,12 @@ func (c *cmd) init() {
"", "",
"The new auth method's name. This flag is required.", "The new auth method's name. This flag is required.",
) )
c.flags.StringVar(
&c.displayName,
"display-name",
"",
"An optional name to use instead of the name when displaying this auth method in a UI.",
)
c.flags.StringVar( c.flags.StringVar(
&c.description, &c.description,
"description", "description",
@ -130,6 +137,7 @@ func (c *cmd) Run(args []string) int {
newAuthMethod := &api.ACLAuthMethod{ newAuthMethod := &api.ACLAuthMethod{
Type: c.authMethodType, Type: c.authMethodType,
Name: c.name, Name: c.name,
DisplayName: c.displayName,
Description: c.description, Description: c.description,
} }

View File

@ -10,11 +10,12 @@ import (
"github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/agent"
"github.com/hashicorp/consul/agent/connect" "github.com/hashicorp/consul/agent/connect"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/command/acl" "github.com/hashicorp/consul/command/acl"
"github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil"
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
"github.com/hashicorp/go-uuid"
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
// activate testing auth method // activate testing auth method
@ -46,6 +47,7 @@ func TestAuthMethodCreateCommand(t *testing.T) {
defer a.Shutdown() defer a.Shutdown()
testrpc.WaitForLeader(t, a.RPC, "dc1") testrpc.WaitForLeader(t, a.RPC, "dc1")
client := a.Client()
t.Run("type required", func(t *testing.T) { t.Run("type required", func(t *testing.T) {
args := []string{ args := []string{
@ -98,6 +100,8 @@ func TestAuthMethodCreateCommand(t *testing.T) {
"-token=root", "-token=root",
"-type=testing", "-type=testing",
"-name=test", "-name=test",
"-description=desc",
"-display-name=display",
} }
ui := cli.NewMockUi() ui := cli.NewMockUi()
@ -106,6 +110,15 @@ func TestAuthMethodCreateCommand(t *testing.T) {
code := cmd.Run(args) code := cmd.Run(args)
require.Equal(t, code, 0) require.Equal(t, code, 0)
require.Empty(t, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String())
got := getTestMethod(t, client, "test")
expect := &api.ACLAuthMethod{
Name: "test",
Type: "testing",
DisplayName: "display",
Description: "desc",
}
require.Equal(t, expect, got)
}) })
} }
@ -126,6 +139,7 @@ func TestAuthMethodCreateCommand_JSON(t *testing.T) {
defer a.Shutdown() defer a.Shutdown()
testrpc.WaitForLeader(t, a.RPC, "dc1") testrpc.WaitForLeader(t, a.RPC, "dc1")
client := a.Client()
t.Run("type required", func(t *testing.T) { t.Run("type required", func(t *testing.T) {
args := []string{ args := []string{
@ -148,6 +162,8 @@ func TestAuthMethodCreateCommand_JSON(t *testing.T) {
"-token=root", "-token=root",
"-type=testing", "-type=testing",
"-name=test", "-name=test",
"-description=desc",
"-display-name=display",
"-format=json", "-format=json",
} }
@ -162,8 +178,16 @@ func TestAuthMethodCreateCommand_JSON(t *testing.T) {
require.Contains(t, out, "test") require.Contains(t, out, "test")
var jsonOutput json.RawMessage var jsonOutput json.RawMessage
err := json.Unmarshal([]byte(out), &jsonOutput) require.NoError(t, json.Unmarshal([]byte(out), &jsonOutput))
assert.NoError(t, err)
got := getTestMethod(t, client, "test")
expect := &api.ACLAuthMethod{
Name: "test",
Type: "testing",
DisplayName: "display",
Description: "desc",
}
require.Equal(t, expect, got)
}) })
} }
@ -184,13 +208,15 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
defer a.Shutdown() defer a.Shutdown()
testrpc.WaitForLeader(t, a.RPC, "dc1") testrpc.WaitForLeader(t, a.RPC, "dc1")
client := a.Client()
t.Run("k8s host required", func(t *testing.T) { t.Run("k8s host required", func(t *testing.T) {
name := getTestName(t)
args := []string{ args := []string{
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-type=kubernetes", "-type=kubernetes",
"-name=k8s", "-name", name,
} }
ui := cli.NewMockUi() ui := cli.NewMockUi()
@ -202,11 +228,12 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
}) })
t.Run("k8s ca cert required", func(t *testing.T) { t.Run("k8s ca cert required", func(t *testing.T) {
name := getTestName(t)
args := []string{ args := []string{
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-type=kubernetes", "-type=kubernetes",
"-name=k8s", "-name", name,
"-kubernetes-host=https://foo.internal:8443", "-kubernetes-host=https://foo.internal:8443",
} }
@ -221,11 +248,12 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
ca := connect.TestCA(t, nil) ca := connect.TestCA(t, nil)
t.Run("k8s jwt required", func(t *testing.T) { t.Run("k8s jwt required", func(t *testing.T) {
name := getTestName(t)
args := []string{ args := []string{
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-type=kubernetes", "-type=kubernetes",
"-name=k8s", "-name", name,
"-kubernetes-host=https://foo.internal:8443", "-kubernetes-host=https://foo.internal:8443",
"-kubernetes-ca-cert", ca.RootCert, "-kubernetes-ca-cert", ca.RootCert,
} }
@ -239,11 +267,12 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
}) })
t.Run("create k8s", func(t *testing.T) { t.Run("create k8s", func(t *testing.T) {
name := getTestName(t)
args := []string{ args := []string{
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-type=kubernetes", "-type=kubernetes",
"-name=k8s", "-name", name,
"-kubernetes-host", "https://foo.internal:8443", "-kubernetes-host", "https://foo.internal:8443",
"-kubernetes-ca-cert", ca.RootCert, "-kubernetes-ca-cert", ca.RootCert,
"-kubernetes-service-account-jwt", acl.TestKubernetesJWT_A, "-kubernetes-service-account-jwt", acl.TestKubernetesJWT_A,
@ -255,17 +284,30 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
code := cmd.Run(args) code := cmd.Run(args)
require.Equal(t, code, 0) require.Equal(t, code, 0)
require.Empty(t, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String())
got := getTestMethod(t, client, name)
expect := &api.ACLAuthMethod{
Name: name,
Type: "kubernetes",
Config: map[string]interface{}{
"Host": "https://foo.internal:8443",
"CACert": ca.RootCert,
"ServiceAccountJWT": acl.TestKubernetesJWT_A,
},
}
require.Equal(t, expect, got)
}) })
caFile := filepath.Join(testDir, "ca.crt") caFile := filepath.Join(testDir, "ca.crt")
require.NoError(t, ioutil.WriteFile(caFile, []byte(ca.RootCert), 0600)) require.NoError(t, ioutil.WriteFile(caFile, []byte(ca.RootCert), 0600))
t.Run("create k8s with cert file", func(t *testing.T) { t.Run("create k8s with cert file", func(t *testing.T) {
name := getTestName(t)
args := []string{ args := []string{
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-type=kubernetes", "-type=kubernetes",
"-name=k8s", "-name", name,
"-kubernetes-host", "https://foo.internal:8443", "-kubernetes-host", "https://foo.internal:8443",
"-kubernetes-ca-cert", "@" + caFile, "-kubernetes-ca-cert", "@" + caFile,
"-kubernetes-service-account-jwt", acl.TestKubernetesJWT_A, "-kubernetes-service-account-jwt", acl.TestKubernetesJWT_A,
@ -277,5 +319,42 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
code := cmd.Run(args) code := cmd.Run(args)
require.Equal(t, code, 0) require.Equal(t, code, 0)
require.Empty(t, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String())
got := getTestMethod(t, client, name)
expect := &api.ACLAuthMethod{
Name: name,
Type: "kubernetes",
Config: map[string]interface{}{
"Host": "https://foo.internal:8443",
"CACert": ca.RootCert,
"ServiceAccountJWT": acl.TestKubernetesJWT_A,
},
}
require.Equal(t, expect, got)
}) })
} }
func getTestMethod(t *testing.T, client *api.Client, methodName string) *api.ACLAuthMethod {
t.Helper()
method, _, err := client.ACL().AuthMethodRead(
methodName,
&api.QueryOptions{Token: "root"},
)
require.NoError(t, err)
require.NotNil(t, method)
// zero these out since we don't really care
method.CreateIndex = 0
method.ModifyIndex = 0
return method
}
func getTestName(t *testing.T) string {
t.Helper()
id, err := uuid.GenerateUUID()
require.NoError(t, err)
return "test-" + id
}

View File

@ -54,6 +54,9 @@ func (f *prettyFormatter) FormatAuthMethod(method *api.ACLAuthMethod) (string, e
if method.Namespace != "" { if method.Namespace != "" {
buffer.WriteString(fmt.Sprintf("Namespace: %s\n", method.Namespace)) buffer.WriteString(fmt.Sprintf("Namespace: %s\n", method.Namespace))
} }
if method.DisplayName != "" {
buffer.WriteString(fmt.Sprintf("DisplayName: %s\n", method.DisplayName))
}
buffer.WriteString(fmt.Sprintf("Description: %s\n", method.Description)) buffer.WriteString(fmt.Sprintf("Description: %s\n", method.Description))
if f.showMeta { if f.showMeta {
buffer.WriteString(fmt.Sprintf("Create Index: %d\n", method.CreateIndex)) buffer.WriteString(fmt.Sprintf("Create Index: %d\n", method.CreateIndex))
@ -87,6 +90,9 @@ func (f *prettyFormatter) formatAuthMethodListEntry(method *api.ACLAuthMethodLis
if method.Namespace != "" { if method.Namespace != "" {
buffer.WriteString(fmt.Sprintf(" Namespace: %s\n", method.Namespace)) buffer.WriteString(fmt.Sprintf(" Namespace: %s\n", method.Namespace))
} }
if method.DisplayName != "" {
buffer.WriteString(fmt.Sprintf(" DisplayName: %s\n", method.DisplayName))
}
buffer.WriteString(fmt.Sprintf(" Description: %s\n", method.Description)) buffer.WriteString(fmt.Sprintf(" Description: %s\n", method.Description))
if f.showMeta { if f.showMeta {
buffer.WriteString(fmt.Sprintf(" Create Index: %d\n", method.CreateIndex)) buffer.WriteString(fmt.Sprintf(" Create Index: %d\n", method.CreateIndex))

View File

@ -27,6 +27,7 @@ type cmd struct {
name string name string
displayName string
description string description string
k8sHost string k8sHost string
@ -58,6 +59,13 @@ func (c *cmd) init() {
"The auth method name.", "The auth method name.",
) )
c.flags.StringVar(
&c.displayName,
"display-name",
"",
"An optional name to use instead of the name when displaying this auth method in a UI.",
)
c.flags.StringVar( c.flags.StringVar(
&c.description, &c.description,
"description", "description",
@ -147,6 +155,7 @@ func (c *cmd) Run(args []string) int {
method = &api.ACLAuthMethod{ method = &api.ACLAuthMethod{
Name: currentAuthMethod.Name, Name: currentAuthMethod.Name,
Type: currentAuthMethod.Type, Type: currentAuthMethod.Type,
DisplayName: c.displayName,
Description: c.description, Description: c.description,
} }
@ -172,6 +181,9 @@ func (c *cmd) Run(args []string) int {
methodCopy := *currentAuthMethod methodCopy := *currentAuthMethod
method = &methodCopy method = &methodCopy
if c.displayName != "" {
method.DisplayName = c.displayName
}
if c.description != "" { if c.description != "" {
method.Description = c.description method.Description = c.description
} }

View File

@ -16,7 +16,6 @@ import (
"github.com/hashicorp/consul/testrpc" "github.com/hashicorp/consul/testrpc"
"github.com/hashicorp/go-uuid" "github.com/hashicorp/go-uuid"
"github.com/mitchellh/cli" "github.com/mitchellh/cli"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
// activate testing auth method // activate testing auth method
@ -66,10 +65,11 @@ func TestAuthMethodUpdateCommand(t *testing.T) {
}) })
t.Run("update nonexistent method", func(t *testing.T) { t.Run("update nonexistent method", func(t *testing.T) {
name := getTestName(t)
args := []string{ args := []string{
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-name=test", "-name", name,
} }
ui := cli.NewMockUi() ui := cli.NewMockUi()
@ -106,6 +106,7 @@ func TestAuthMethodUpdateCommand(t *testing.T) {
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-name=" + name, "-name=" + name,
"-display-name", "updated display",
"-description", "updated description", "-description", "updated description",
} }
@ -116,13 +117,15 @@ func TestAuthMethodUpdateCommand(t *testing.T) {
require.Equal(t, code, 0) require.Equal(t, code, 0)
require.Empty(t, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String())
method, _, err := client.ACL().AuthMethodRead( got := getTestMethod(t, client, name)
name, expect := &api.ACLAuthMethod{
&api.QueryOptions{Token: "root"}, Name: name,
) Type: "testing",
require.NoError(t, err) DisplayName: "updated display",
require.NotNil(t, method) Description: "updated description",
require.Equal(t, "updated description", method.Description) Config: map[string]interface{}{},
}
require.Equal(t, expect, got)
}) })
} }
@ -187,6 +190,7 @@ func TestAuthMethodUpdateCommand_JSON(t *testing.T) {
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-name=" + name, "-name=" + name,
"-display-name", "updated display",
"-description", "updated description", "-description", "updated description",
"-format=json", "-format=json",
} }
@ -195,22 +199,23 @@ func TestAuthMethodUpdateCommand_JSON(t *testing.T) {
cmd := New(ui) cmd := New(ui)
code := cmd.Run(args) code := cmd.Run(args)
output := ui.OutputWriter.String()
require.Equal(t, code, 0) require.Equal(t, code, 0)
require.Empty(t, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String())
method, _, err := client.ACL().AuthMethodRead(
name,
&api.QueryOptions{Token: "root"},
)
require.NoError(t, err)
require.NotNil(t, method)
require.Equal(t, "updated description", method.Description)
output := ui.OutputWriter.String()
var jsonOutput json.RawMessage var jsonOutput json.RawMessage
err = json.Unmarshal([]byte(output), &jsonOutput) require.NoError(t, json.Unmarshal([]byte(output), &jsonOutput))
assert.NoError(t, err)
got := getTestMethod(t, client, name)
expect := &api.ACLAuthMethod{
Name: name,
Type: "testing",
DisplayName: "updated display",
Description: "updated description",
Config: map[string]interface{}{},
}
require.Equal(t, expect, got)
}) })
} }
@ -250,11 +255,12 @@ func TestAuthMethodUpdateCommand_noMerge(t *testing.T) {
}) })
t.Run("update nonexistent method", func(t *testing.T) { t.Run("update nonexistent method", func(t *testing.T) {
name := getTestName(t)
args := []string{ args := []string{
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-no-merge", "-no-merge",
"-name=test", "-name", name,
} }
ui := cli.NewMockUi() ui := cli.NewMockUi()
@ -292,6 +298,7 @@ func TestAuthMethodUpdateCommand_noMerge(t *testing.T) {
"-token=root", "-token=root",
"-no-merge", "-no-merge",
"-name=" + name, "-name=" + name,
"-display-name", "updated display",
"-description", "updated description", "-description", "updated description",
} }
@ -302,13 +309,14 @@ func TestAuthMethodUpdateCommand_noMerge(t *testing.T) {
require.Equal(t, code, 0, "err: %s", ui.ErrorWriter.String()) require.Equal(t, code, 0, "err: %s", ui.ErrorWriter.String())
require.Empty(t, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String())
method, _, err := client.ACL().AuthMethodRead( got := getTestMethod(t, client, name)
name, expect := &api.ACLAuthMethod{
&api.QueryOptions{Token: "root"}, Name: name,
) Type: "testing",
require.NoError(t, err) DisplayName: "updated display",
require.NotNil(t, method) Description: "updated description",
require.Equal(t, "updated description", method.Description) }
require.Equal(t, expect, got)
}) })
} }
@ -366,6 +374,7 @@ func TestAuthMethodUpdateCommand_k8s(t *testing.T) {
"-http-addr=" + a.HTTPAddr(), "-http-addr=" + a.HTTPAddr(),
"-token=root", "-token=root",
"-name=" + name, "-name=" + name,
"-display-name", "updated display",
"-description", "updated description", "-description", "updated description",
"-kubernetes-host", "https://foo-new.internal:8443", "-kubernetes-host", "https://foo-new.internal:8443",
"-kubernetes-ca-cert", ca2.RootCert, "-kubernetes-ca-cert", ca2.RootCert,
@ -379,15 +388,22 @@ func TestAuthMethodUpdateCommand_k8s(t *testing.T) {
require.Equal(t, code, 0) require.Equal(t, code, 0)
require.Empty(t, ui.ErrorWriter.String()) require.Empty(t, ui.ErrorWriter.String())
method, _, err := client.ACL().AuthMethodRead( got := getTestMethod(t, client, name)
name, expect := &api.ACLAuthMethod{
&api.QueryOptions{Token: "root"}, Name: name,
) Type: "kubernetes",
require.NoError(t, err) DisplayName: "updated display",
require.NotNil(t, method) Description: "updated description",
require.Equal(t, "updated description", method.Description) Config: map[string]interface{}{
"Host": "https://foo-new.internal:8443",
"CACert": ca2.RootCert,
"ServiceAccountJWT": acl.TestKubernetesJWT_B,
},
}
require.Equal(t, expect, got)
config, err := api.ParseKubernetesAuthMethodConfig(method.Config) // also just double check our convenience parsing
config, err := api.ParseKubernetesAuthMethodConfig(got.Config)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, "https://foo-new.internal:8443", config.Host) require.Equal(t, "https://foo-new.internal:8443", config.Host)
require.Equal(t, ca2.RootCert, config.CACert) require.Equal(t, ca2.RootCert, config.CACert)
@ -726,3 +742,28 @@ func TestAuthMethodUpdateCommand_k8s_noMerge(t *testing.T) {
require.Equal(t, acl.TestKubernetesJWT_B, config.ServiceAccountJWT) require.Equal(t, acl.TestKubernetesJWT_B, config.ServiceAccountJWT)
}) })
} }
func getTestMethod(t *testing.T, client *api.Client, methodName string) *api.ACLAuthMethod {
t.Helper()
method, _, err := client.ACL().AuthMethodRead(
methodName,
&api.QueryOptions{Token: "root"},
)
require.NoError(t, err)
require.NotNil(t, method)
// zero these out since we don't really care
method.CreateIndex = 0
method.ModifyIndex = 0
return method
}
func getTestName(t *testing.T) string {
t.Helper()
id, err := uuid.GenerateUUID()
require.NoError(t, err)
return "test-" + id
}

View File

@ -57,6 +57,9 @@ func (f *prettyFormatter) FormatToken(token *api.ACLToken) (string, error) {
} }
buffer.WriteString(fmt.Sprintf("Description: %s\n", token.Description)) buffer.WriteString(fmt.Sprintf("Description: %s\n", token.Description))
buffer.WriteString(fmt.Sprintf("Local: %t\n", token.Local)) buffer.WriteString(fmt.Sprintf("Local: %t\n", token.Local))
if token.AuthMethod != "" {
buffer.WriteString(fmt.Sprintf("Auth Method: %s\n", token.AuthMethod))
}
buffer.WriteString(fmt.Sprintf("Create Time: %v\n", token.CreateTime)) buffer.WriteString(fmt.Sprintf("Create Time: %v\n", token.CreateTime))
if token.ExpirationTime != nil && !token.ExpirationTime.IsZero() { if token.ExpirationTime != nil && !token.ExpirationTime.IsZero() {
buffer.WriteString(fmt.Sprintf("Expiration Time: %v\n", *token.ExpirationTime)) buffer.WriteString(fmt.Sprintf("Expiration Time: %v\n", *token.ExpirationTime))
@ -121,6 +124,9 @@ func (f *prettyFormatter) formatTokenListEntry(token *api.ACLTokenListEntry) str
} }
buffer.WriteString(fmt.Sprintf("Description: %s\n", token.Description)) buffer.WriteString(fmt.Sprintf("Description: %s\n", token.Description))
buffer.WriteString(fmt.Sprintf("Local: %t\n", token.Local)) buffer.WriteString(fmt.Sprintf("Local: %t\n", token.Local))
if token.AuthMethod != "" {
buffer.WriteString(fmt.Sprintf("Auth Method: %s\n", token.AuthMethod))
}
buffer.WriteString(fmt.Sprintf("Create Time: %v\n", token.CreateTime)) buffer.WriteString(fmt.Sprintf("Create Time: %v\n", token.CreateTime))
if token.ExpirationTime != nil && !token.ExpirationTime.IsZero() { if token.ExpirationTime != nil && !token.ExpirationTime.IsZero() {
buffer.WriteString(fmt.Sprintf("Expiration Time: %v\n", *token.ExpirationTime)) buffer.WriteString(fmt.Sprintf("Expiration Time: %v\n", *token.ExpirationTime))

View File

@ -40,6 +40,7 @@ The table below shows this endpoint's support for
- `Name` `(string: <required>)` - Specifies a name for the ACL auth method. The - `Name` `(string: <required>)` - Specifies a name for the ACL auth method. The
name can contain alphanumeric characters, dashes `-`, and underscores `_`. name can contain alphanumeric characters, dashes `-`, and underscores `_`.
This field is immutable and must be unique. This field is immutable and must be unique.
- `Type` `(string: <required>)` - The type of auth method being configured. - `Type` `(string: <required>)` - The type of auth method being configured.
The only allowed value in Consul 1.5.0 is `"kubernetes"`. This field is The only allowed value in Consul 1.5.0 is `"kubernetes"`. This field is
immutable. immutable.
@ -47,6 +48,9 @@ The table below shows this endpoint's support for
- `Description` `(string: "")` - Free form human readable description of the - `Description` `(string: "")` - Free form human readable description of the
auth method. auth method.
- `DisplayName` `(string: "")` - An optional name to use instead of the `Name`
field when displaying information about this auth method. Added in Consul 1.8.0.
- `Config` `(map[string]string: <required>)` - The raw configuration to use for - `Config` `(map[string]string: <required>)` - The raw configuration to use for
the chosen auth method. Contents will vary depending upon the type chosen. the chosen auth method. Contents will vary depending upon the type chosen.
For more information on configuring specific auth method types, see the [auth For more information on configuring specific auth method types, see the [auth
@ -184,6 +188,9 @@ The table below shows this endpoint's support for
- `Description` `(string: "")` - Free form human readable description of the - `Description` `(string: "")` - Free form human readable description of the
auth method. auth method.
- `DisplayName` `(string: "")` - An optional name to use instead of the `Name`
field when displaying information about this auth method. Added in Consul 1.8.0.
- `Config` `(map[string]string: <required>)` - The raw configuration to use for - `Config` `(map[string]string: <required>)` - The raw configuration to use for
the chosen auth method. Contents will vary depending upon the type chosen. the chosen auth method. Contents will vary depending upon the type chosen.
For more information on configuring specific auth method types, see the [auth For more information on configuring specific auth method types, see the [auth