Update target credential library service, API, SDK, CLI (#1343)

This commit is contained in:
Jeff Mitchell authored and GitHub committed 2021-06-25 14:06:31 -04:00
1 parent 83c65d0d4b
commit 86c9a90554
27 files changed
+1474 -1127

No files matched your search

+95 -48
View File
@@ -13,6 +13,7 @@ import (
"github.com/hashicorp/boundary/api/targets"
"github.com/hashicorp/boundary/globals"
"github.com/hashicorp/boundary/internal/cmd/base"
"github.com/hashicorp/boundary/internal/credential"
"github.com/hashicorp/boundary/sdk/strutil"
"github.com/mitchellh/go-wordwrap"
"github.com/posener/complete"
@@ -28,10 +29,10 @@ func init() {
}
type extraCmdVars struct {
flagHostSets []string
flagCredentialLibraries []string
flagHostId string
sar *targets.SessionAuthorizationResult
flagHostSets []string
flagApplicationCredentialLibraries []string
flagHostId string
sar *targets.SessionAuthorizationResult
}
func extraActionsFlagsMapFuncImpl() map[string][]string {
@@ -40,9 +41,9 @@ func extraActionsFlagsMapFuncImpl() map[string][]string {
"add-host-sets": {"id", "host-set", "version"},
"remove-host-sets": {"id", "host-set", "version"},
"set-host-sets": {"id", "host-set", "version"},
"add-credential-libraries": {"id", "credential-library", "version"},
"remove-credential-libraries": {"id", "credential-library", "version"},
"set-credential-libraries": {"id", "credential-library", "version"},
"add-credential-libraries": {"id", "application-credential-library", "version"},
"remove-credential-libraries": {"id", "application-credential-library", "version"},
"set-credential-libraries": {"id", "application-credential-library", "version"},
}
}
@@ -163,7 +164,7 @@ func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
"",
" Add credential-library resources to a tcp-type target:",
"",
` $ boundary targets add-credential-libraries -id ttcp_1234567890 -credential-library clvlt_1234567890 -credential-library clvlt_0987654321`,
` $ boundary targets add-credential-libraries -id ttcp_1234567890 -application-credential-library clvlt_1234567890 -application-credential-library clvlt_0987654321`,
"",
"",
})
@@ -175,7 +176,7 @@ func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
"",
" Remove credential-library resources from a tcp-type target:",
"",
` $ boundary targets remove-credential-libraries -id ttcp_1234567890 -credential-library clvlt_1234567890 -credential-library clvlt_0987654321`,
` $ boundary targets remove-credential-libraries -id ttcp_1234567890 -application-credential-library clvlt_1234567890 -application-credential-library clvlt_0987654321`,
"",
"",
})
@@ -187,7 +188,7 @@ func (c *Command) extraHelpFunc(helpMap map[string]func() string) string {
"",
" Set credential-library resources on a tcp-type target:",
"",
` $ boundary targets set-credential-libraries -id ttcp_1234567890 -credential-library clvlt_1234567890`,
` $ boundary targets set-credential-libraries -id ttcp_1234567890 -application-credential-library clvlt_1234567890`,
"",
"",
})
@@ -226,11 +227,11 @@ func extraFlagsFuncImpl(c *Command, _ *base.FlagSets, f *base.FlagSet) {
Target: &c.flagHostId,
Usage: "The ID of a specific host to connect to out of the hosts from the target's host sets. If not specified, one is chosen at random.",
})
case "credential-library":
case "application-credential-library":
f.StringSliceVar(&base.StringSliceVar{
Name: "credential-library",
Target: &c.flagCredentialLibraries,
Usage: "The credential-library resource to add, remove, or set. May be specified multiple times.",
Name: "application-credential-library",
Target: &c.flagApplicationCredentialLibraries,
Usage: "The credential-library resource for application purpose to add, set, or remove. May be specified multiple times.",
})
}
}
@@ -314,20 +315,27 @@ func extraFlagsHandlingFuncImpl(c *Command, _ *base.FlagSets, opts *[]targets.Op
}
case "add-credential-libraries", "remove-credential-libraries":
if len(c.flagCredentialLibraries) == 0 {
c.UI.Error("No credential-library supplied via -credential-library")
// TODO: As we add other purposes, add them to this check
if len(c.flagApplicationCredentialLibraries) == 0 {
c.UI.Error("No credential-libraries supplied via -application-credential-library")
return false
}
*opts = append(*opts, targets.WithApplicationCredentialLibraryIds(c.flagApplicationCredentialLibraries))
case "set-credential-libraries":
switch len(c.flagCredentialLibraries) {
case 0:
c.UI.Error("No credential-libraries supplied via -credential-library")
// TODO: As we add other purposes, add them to this check
if len(c.flagApplicationCredentialLibraries) == 0 {
c.UI.Error("No credential-libraries supplied via -application-credential-library")
return false
}
switch len(c.flagApplicationCredentialLibraries) {
case 0:
case 1:
if c.flagCredentialLibraries[0] == "null" {
c.flagCredentialLibraries = nil
if c.flagApplicationCredentialLibraries[0] == "null" {
*opts = append(*opts, targets.DefaultApplicationCredentialLibraryIds())
}
default:
*opts = append(*opts, targets.WithApplicationCredentialLibraryIds(c.flagApplicationCredentialLibraries))
}
case "authorize-session":
@@ -348,11 +356,11 @@ func executeExtraActionsImpl(c *Command, origResult api.GenericResult, origError
case "set-host-sets":
return targetClient.SetHostSets(c.Context, c.FlagId, version, c.flagHostSets, opts...)
case "add-credential-libraries":
return targetClient.AddCredentialLibraries(c.Context, c.FlagId, version, c.flagCredentialLibraries, opts...)
return targetClient.AddCredentialLibraries(c.Context, c.FlagId, version, opts...)
case "remove-credential-libraries":
return targetClient.RemoveCredentialLibraries(c.Context, c.FlagId, version, c.flagCredentialLibraries, opts...)
return targetClient.RemoveCredentialLibraries(c.Context, c.FlagId, version, opts...)
case "set-credential-libraries":
return targetClient.SetCredentialLibraries(c.Context, c.FlagId, version, c.flagCredentialLibraries, opts...)
return targetClient.SetCredentialLibraries(c.Context, c.FlagId, version, opts...)
case "authorize-session":
var err error
c.plural = "a session against target"
@@ -472,15 +480,20 @@ func printItemTable(result api.GenericResult) string {
}
}
var libraryMaps []map[string]interface{}
if len(item.CredentialLibraries) > 0 {
for _, lib := range item.CredentialLibraries {
var libraryMaps map[credential.Purpose][]map[string]interface{}
if len(item.ApplicationCredentialLibraries) > 0 {
if libraryMaps == nil {
libraryMaps = make(map[credential.Purpose][]map[string]interface{})
}
var applicationLibraryMaps []map[string]interface{}
for _, lib := range item.ApplicationCredentialLibraries {
m := map[string]interface{}{
"ID": lib.Id,
"Credential Store ID": lib.CredentialStoreId,
}
libraryMaps = append(libraryMaps, m)
applicationLibraryMaps = append(applicationLibraryMaps, m)
}
libraryMaps[credential.ApplicationPurpose] = applicationLibraryMaps
if l := len("Credential Store ID"); l > maxLength {
maxLength = l
}
@@ -524,15 +537,17 @@ func printItemTable(result api.GenericResult) string {
}
}
if len(item.CredentialLibraries) > 0 {
ret = append(ret,
" Credential Libraries:",
)
for _, m := range libraryMaps {
if len(libraryMaps) > 0 {
if appMap := libraryMaps[credential.ApplicationPurpose]; len(appMap) > 0 {
ret = append(ret,
base.WrapMap(4, maxLength, m),
"",
" Application Credential Libraries:",
)
for _, m := range appMap {
ret = append(ret,
base.WrapMap(4, maxLength, m),
"",
)
}
}
}
@@ -589,6 +604,10 @@ func printCustomActionOutputImpl(c *Command) (bool, error) {
)
for _, cred := range item.Credentials {
if len(cred.Secret) == 0 {
continue
}
ret = append(ret,
fmt.Sprintf(" Credential Store ID: %s", cred.CredentialLibrary.CredentialStoreId),
fmt.Sprintf(" Credential Library ID: %s", cred.CredentialLibrary.Id),
@@ -602,7 +621,7 @@ func printCustomActionOutputImpl(c *Command) (bool, error) {
ret = append(ret,
fmt.Sprintf(" Credential Library Description: %s", cred.CredentialLibrary.Description))
}
var secretStr string
var secretStr []string
switch cred.CredentialLibrary.Type {
case "vault":
// If it's Vault, the result will be JSON, except in
@@ -610,26 +629,28 @@ func printCustomActionOutputImpl(c *Command) (bool, error) {
// credential fetching. So we can take the bytes
// as-is (after base64-decoding), but we'll format
// it nicely.
in, err := base64.StdEncoding.DecodeString(cred.Secret)
in, err := base64.StdEncoding.DecodeString(strings.Trim(string(cred.Secret), `"`))
if err != nil {
return false, fmt.Errorf("Error decoding secret as base64: %w", err)
}
dst := new(bytes.Buffer)
if err := json.Indent(dst, in, "", " "); err != nil {
if err := json.Indent(dst, in, " ", " "); err != nil {
return false, fmt.Errorf("Error pretty-printing JSON: %w", err)
}
secretStr = dst.String()
secretStr = strings.Split(dst.String(), "\n")
if len(secretStr) > 0 {
// Indent doesn't apply to the first line 🙄
secretStr[0] = fmt.Sprintf(" %s", secretStr[0])
}
default:
// If it's not Vault, and not another known type,
// print out the base64-encoded value and leave it
// to the user to sort out.
secretStr = fmt.Sprintf(" %s", secretStr)
secretStr = []string{fmt.Sprintf(" %s", secretStr)}
}
ret = append(ret,
fmt.Sprintf(" Secret:"),
fmt.Sprintf(" %s", secretStr),
"",
)
ret = append(ret, " Secret:")
ret = append(ret, secretStr...)
ret = append(ret, "")
}
}
@@ -637,7 +658,33 @@ func printCustomActionOutputImpl(c *Command) (bool, error) {
return true, nil
case "json":
if ok := c.PrintJsonItem(c.sar); !ok {
if len(item.Credentials) > 0 {
for _, cred := range item.Credentials {
if len(cred.Secret) == 0 {
continue
}
switch cred.CredentialLibrary.Type {
case "vault":
// If it's Vault, the result will be JSON, except in
// specific circumstances that aren't used for
// credential fetching. So we can take the bytes
// as-is (after base64-decoding), but we'll format
// it nicely.
in, err := base64.StdEncoding.DecodeString(strings.Trim(string(cred.Secret), `"`))
if err != nil {
return false, fmt.Errorf("Error decoding secret as base64: %w", err)
}
// Now that it's decoded, pop it back in the same place
// as marshaled JSON
cred.Secret = in
default:
// If it's not Vault, and not another known type,
// leave it alone.
}
}
}
if ok := c.PrintJsonItem(c.sar, base.WithDecodedCredentials(item.Credentials)); !ok {
return false, fmt.Errorf("Error formatting as JSON")
}
return true, nil
@@ -675,8 +722,8 @@ func exampleOutput() string {
HostCatalogId: "hcst_1234567890",
},
},
CredentialLibraryIds: []string{"clvlt_1234567890", "clvlt_0987654321"},
CredentialLibraries: []*targets.CredentialLibrary{
ApplicationCredentialLibraryIds: []string{"clvlt_1234567890", "clvlt_0987654321"},
ApplicationCredentialLibraries: []*targets.CredentialLibrary{
{
Id: "clvlt_1234567890",
CredentialStoreId: "csvlt_1234567890",
@@ -59,30 +59,30 @@ func (c *TcpCommand) extraTcpHelpFunc(helpMap map[string]func() string) string {
}
func extraTcpFlagsFuncImpl(c *TcpCommand, set *base.FlagSets, f *base.FlagSet) {
f = set.NewFlagSet("TCP Target Options")
fs := set.NewFlagSet("TCP Target Options")
for _, name := range flagsTcpMap[c.Func] {
switch name {
case "default-port":
f.StringVar(&base.StringVar{
fs.StringVar(&base.StringVar{
Name: "default-port",
Target: &c.flagDefaultPort,
Usage: "The default port to set on the target.",
})
case "session-max-seconds":
f.StringVar(&base.StringVar{
fs.StringVar(&base.StringVar{
Name: "session-max-seconds",
Target: &c.flagSessionMaxSeconds,
Usage: `The maximum lifetime of the session, including all connections. Can be specified as an integer number of seconds or a duration string.`,
})
case "session-connection-limit":
f.StringVar(&base.StringVar{
fs.StringVar(&base.StringVar{
Name: "session-connection-limit",
Target: &c.flagSessionConnectionLimit,
Usage: "The maximum number of connections allowed for a session. -1 means unlimited.",
})
case "worker-filter":
f.StringVar(&base.StringVar{
fs.StringVar(&base.StringVar{
Name: "worker-filter",
Target: &c.flagWorkerFilter,
Usage: "A boolean expression to filter which workers can handle sessions for this target.",