mirror of
https://github.com/status-im/consul.git
synced 2025-01-10 13:55:55 +00:00
cli: Add -config flag to "acl authmethod update/create" (#7776)
This commit is contained in:
parent
68499f0204
commit
f9956c1c46
@ -1,6 +1,7 @@
|
||||
package authmethodcreate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -33,6 +34,7 @@ type cmd struct {
|
||||
k8sHost string
|
||||
k8sCACert string
|
||||
k8sServiceAccountJWT string
|
||||
config string
|
||||
|
||||
showMeta bool
|
||||
format string
|
||||
@ -105,6 +107,14 @@ func (c *cmd) init() {
|
||||
authmethod.PrettyFormat,
|
||||
fmt.Sprintf("Output format {%s}", strings.Join(authmethod.GetSupportedFormats(), "|")),
|
||||
)
|
||||
c.flags.StringVar(
|
||||
&c.config,
|
||||
"config",
|
||||
"",
|
||||
"The configuration for the auth method. Must be JSON. May be prefixed with '@' "+
|
||||
"to indicate that the value is a file path to load the config from. '-' may also be "+
|
||||
"given to indicate that the config is available on stdin",
|
||||
)
|
||||
|
||||
c.http = &flags.HTTPFlags{}
|
||||
flags.Merge(c.flags, c.http.ClientFlags())
|
||||
@ -141,6 +151,24 @@ func (c *cmd) Run(args []string) int {
|
||||
Description: c.description,
|
||||
}
|
||||
|
||||
if c.config != "" {
|
||||
if c.k8sHost != "" || c.k8sCACert != "" || c.k8sServiceAccountJWT != "" {
|
||||
c.UI.Error(fmt.Sprintf("Cannot use command line arguments with '-config' flags"))
|
||||
return 1
|
||||
}
|
||||
data, err := helpers.LoadDataSource(c.config, c.testStdin)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error loading configuration file: %v", err))
|
||||
return 1
|
||||
}
|
||||
err = json.Unmarshal([]byte(data), &newAuthMethod.Config)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error parsing JSON configuration file: %v", err))
|
||||
return 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if c.authMethodType == "kubernetes" {
|
||||
if c.k8sHost == "" {
|
||||
c.UI.Error(fmt.Sprintf("Missing required '-kubernetes-host' flag"))
|
||||
|
@ -2,6 +2,7 @@ package authmethodcreate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -282,7 +283,7 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
|
||||
cmd := New(ui)
|
||||
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, code, 0)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
|
||||
got := getTestMethod(t, client, name)
|
||||
@ -334,6 +335,96 @@ func TestAuthMethodCreateCommand_k8s(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthMethodCreateCommand_config(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testDir := testutil.TempDir(t, "auth-method")
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
a := agent.NewTestAgent(t, `
|
||||
primary_datacenter = "dc1"
|
||||
acl {
|
||||
enabled = true
|
||||
tokens {
|
||||
master = "root"
|
||||
}
|
||||
}`)
|
||||
|
||||
defer a.Shutdown()
|
||||
testrpc.WaitForLeader(t, a.RPC, "dc1")
|
||||
client := a.Client()
|
||||
|
||||
checkMethod := func(t *testing.T, methodName string) {
|
||||
|
||||
method, _, err := client.ACL().AuthMethodRead(
|
||||
methodName,
|
||||
&api.QueryOptions{Token: "root"},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, method)
|
||||
require.Equal(t, "foo", method.Config["SessionID"])
|
||||
}
|
||||
|
||||
t.Run("config file", func(t *testing.T) {
|
||||
configFile := filepath.Join(testDir, "config.json")
|
||||
jsonConfig := `{"SessionID":"foo"}`
|
||||
require.NoError(t, ioutil.WriteFile(configFile, []byte(jsonConfig), 0644))
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + a.HTTPAddr(),
|
||||
"-token=root",
|
||||
"-type=testing",
|
||||
"-name=test",
|
||||
"-config=@" + configFile,
|
||||
}
|
||||
ui := cli.NewMockUi()
|
||||
cmd := New(ui)
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
checkMethod(t, "test")
|
||||
})
|
||||
|
||||
t.Run("config std-in", func(t *testing.T) {
|
||||
stdinR, stdinW := io.Pipe()
|
||||
ui := cli.NewMockUi()
|
||||
cmd := New(ui)
|
||||
cmd.testStdin = stdinR
|
||||
go func() {
|
||||
stdinW.Write([]byte(`{"SessionID":"foo"}`))
|
||||
stdinW.Close()
|
||||
}()
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + a.HTTPAddr(),
|
||||
"-token=root",
|
||||
"-type=testing",
|
||||
"-name=test2",
|
||||
"-config=-",
|
||||
}
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
checkMethod(t, "test2")
|
||||
|
||||
})
|
||||
t.Run("config string", func(t *testing.T) {
|
||||
ui := cli.NewMockUi()
|
||||
cmd := New(ui)
|
||||
args := []string{
|
||||
"-http-addr=" + a.HTTPAddr(),
|
||||
"-token=root",
|
||||
"-type=testing",
|
||||
"-name=test3",
|
||||
"-config=" + `{"SessionID":"foo"}`,
|
||||
}
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
checkMethod(t, "test3")
|
||||
})
|
||||
}
|
||||
|
||||
func getTestMethod(t *testing.T, client *api.Client, methodName string) *api.ACLAuthMethod {
|
||||
t.Helper()
|
||||
|
||||
@ -357,4 +448,5 @@ func getTestName(t *testing.T) string {
|
||||
id, err := uuid.GenerateUUID()
|
||||
require.NoError(t, err)
|
||||
return "test-" + id
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package authmethodupdate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -27,9 +28,9 @@ type cmd struct {
|
||||
|
||||
name string
|
||||
|
||||
displayName string
|
||||
description string
|
||||
|
||||
displayName string
|
||||
description string
|
||||
config string
|
||||
k8sHost string
|
||||
k8sCACert string
|
||||
k8sServiceAccountJWT string
|
||||
@ -73,6 +74,15 @@ func (c *cmd) init() {
|
||||
"A description of the auth method.",
|
||||
)
|
||||
|
||||
c.flags.StringVar(
|
||||
&c.config,
|
||||
"config",
|
||||
"",
|
||||
"The configuration for the auth method. Must be JSON. The config is updated as one field"+
|
||||
"May be prefixed with '@' to indicate that the value is a file path to load the config from. "+
|
||||
"'-' may also be given to indicate that the config are available on stdin. ",
|
||||
)
|
||||
|
||||
c.flags.StringVar(
|
||||
&c.k8sHost,
|
||||
"kubernetes-host",
|
||||
@ -100,6 +110,7 @@ func (c *cmd) init() {
|
||||
c.flags.BoolVar(&c.noMerge, "no-merge", false, "Do not merge the current auth method "+
|
||||
"information with what is provided to the command. Instead overwrite all fields "+
|
||||
"with the exception of the name which is immutable.")
|
||||
|
||||
c.flags.StringVar(
|
||||
&c.format,
|
||||
"format",
|
||||
@ -158,7 +169,21 @@ func (c *cmd) Run(args []string) int {
|
||||
DisplayName: c.displayName,
|
||||
Description: c.description,
|
||||
}
|
||||
|
||||
if c.config != "" {
|
||||
if c.k8sHost != "" || c.k8sCACert != "" || c.k8sServiceAccountJWT != "" {
|
||||
c.UI.Error(fmt.Sprintf("Cannot use command line arguments with '-config' flag"))
|
||||
return 1
|
||||
}
|
||||
data, err := helpers.LoadDataSource(c.config, c.testStdin)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error loading configuration file: %v", err))
|
||||
return 1
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), &method.Config); err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error parsing JSON for auth method config: %v", err))
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if currentAuthMethod.Type == "kubernetes" {
|
||||
if c.k8sHost == "" {
|
||||
c.UI.Error(fmt.Sprintf("Missing required '-kubernetes-host' flag"))
|
||||
@ -180,12 +205,26 @@ func (c *cmd) Run(args []string) int {
|
||||
} else {
|
||||
methodCopy := *currentAuthMethod
|
||||
method = &methodCopy
|
||||
|
||||
if c.description != "" {
|
||||
method.Description = c.description
|
||||
}
|
||||
if c.displayName != "" {
|
||||
method.DisplayName = c.displayName
|
||||
}
|
||||
if c.description != "" {
|
||||
method.Description = c.description
|
||||
if c.config != "" {
|
||||
if c.k8sHost != "" || c.k8sCACert != "" || c.k8sServiceAccountJWT != "" {
|
||||
c.UI.Error(fmt.Sprintf("Cannot use command line arguments with '-config' flag"))
|
||||
return 1
|
||||
}
|
||||
data, err := helpers.LoadDataSource(c.config, c.testStdin)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error loading configuration file: %v", err))
|
||||
return 1
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), &method.Config); err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error parsing JSON for auth method config: %v", err))
|
||||
return 1
|
||||
}
|
||||
}
|
||||
if method.Config == nil {
|
||||
method.Config = make(map[string]interface{})
|
||||
|
@ -2,6 +2,7 @@ package authmethodupdate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@ -743,6 +744,138 @@ func TestAuthMethodUpdateCommand_k8s_noMerge(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestAuthMethodUpdateCommand_config(t *testing.T) {
|
||||
t.Parallel()
|
||||
testDir := testutil.TempDir(t, "auth-method")
|
||||
defer os.RemoveAll(testDir)
|
||||
|
||||
a := agent.NewTestAgent(t, `
|
||||
primary_datacenter = "dc1"
|
||||
acl {
|
||||
enabled = true
|
||||
tokens {
|
||||
master = "root"
|
||||
}
|
||||
}`)
|
||||
|
||||
defer a.Shutdown()
|
||||
testrpc.WaitForLeader(t, a.RPC, "dc1")
|
||||
|
||||
client := a.Client()
|
||||
|
||||
createAuthMethod := func(t *testing.T) string {
|
||||
id, err := uuid.GenerateUUID()
|
||||
require.NoError(t, err)
|
||||
|
||||
methodName := "test" + id
|
||||
|
||||
_, _, err = client.ACL().AuthMethodCreate(
|
||||
&api.ACLAuthMethod{
|
||||
Name: methodName,
|
||||
Type: "testing",
|
||||
Description: "test",
|
||||
Config: map[string]interface{}{
|
||||
"SessionID": "big",
|
||||
},
|
||||
},
|
||||
&api.WriteOptions{Token: "root"},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
return methodName
|
||||
}
|
||||
|
||||
readUpdate := func(t *testing.T, methodName string) {
|
||||
|
||||
method, _, err := client.ACL().AuthMethodRead(
|
||||
methodName,
|
||||
&api.QueryOptions{Token: "root"},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, method)
|
||||
require.Equal(t, "update", method.Config["SessionID"])
|
||||
}
|
||||
|
||||
t.Run("config file", func(t *testing.T) {
|
||||
methodName := createAuthMethod(t)
|
||||
configFile := filepath.Join(testDir, "config.json")
|
||||
jsonConfig := `{"SessionID":"update"}`
|
||||
require.NoError(t, ioutil.WriteFile(configFile, []byte(jsonConfig), 0644))
|
||||
|
||||
args := []string{
|
||||
"-http-addr=" + a.HTTPAddr(),
|
||||
"-token=root",
|
||||
"-name=" + methodName,
|
||||
"-no-merge=true",
|
||||
"-config=@" + configFile,
|
||||
}
|
||||
ui := cli.NewMockUi()
|
||||
cmd := New(ui)
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
readUpdate(t, methodName)
|
||||
})
|
||||
|
||||
t.Run("config stdin", func(t *testing.T) {
|
||||
methodName := createAuthMethod(t)
|
||||
ui := cli.NewMockUi()
|
||||
cmd := New(ui)
|
||||
stdinR, stdinW := io.Pipe()
|
||||
cmd.testStdin = stdinR
|
||||
|
||||
go func() {
|
||||
stdinW.Write([]byte(`{"SessionID":"update"}`))
|
||||
stdinW.Close()
|
||||
}()
|
||||
args := []string{
|
||||
"-http-addr=" + a.HTTPAddr(),
|
||||
"-token=root",
|
||||
"-name=" + methodName,
|
||||
"-no-merge=true",
|
||||
"-config=-",
|
||||
}
|
||||
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
readUpdate(t, methodName)
|
||||
})
|
||||
|
||||
t.Run("config string", func(t *testing.T) {
|
||||
methodName := createAuthMethod(t)
|
||||
args := []string{
|
||||
"-http-addr=" + a.HTTPAddr(),
|
||||
"-token=root",
|
||||
"-name=" + methodName,
|
||||
"-no-merge=true",
|
||||
"-config=" + `{"SessionID":"update"}`,
|
||||
}
|
||||
ui := cli.NewMockUi()
|
||||
cmd := New(ui)
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
readUpdate(t, methodName)
|
||||
})
|
||||
t.Run("config with no merge", func(t *testing.T) {
|
||||
methodName := createAuthMethod(t)
|
||||
args := []string{
|
||||
"-http-addr=" + a.HTTPAddr(),
|
||||
"-token=root",
|
||||
"-name=" + methodName,
|
||||
"-no-merge=false",
|
||||
"-config=" + `{"SessionID":"update"}`,
|
||||
}
|
||||
ui := cli.NewMockUi()
|
||||
cmd := New(ui)
|
||||
code := cmd.Run(args)
|
||||
require.Equal(t, 0, code)
|
||||
require.Empty(t, ui.ErrorWriter.String())
|
||||
readUpdate(t, methodName)
|
||||
})
|
||||
}
|
||||
|
||||
func getTestMethod(t *testing.T, client *api.Client, methodName string) *api.ACLAuthMethod {
|
||||
t.Helper()
|
||||
|
||||
@ -766,4 +899,5 @@ func getTestName(t *testing.T) string {
|
||||
id, err := uuid.GenerateUUID()
|
||||
require.NoError(t, err)
|
||||
return "test-" + id
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user