mirror of https://github.com/hashicorp/boundary
parent
f5cdf2a354
commit
d24ad6c2e2
@ -0,0 +1,291 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package targetscmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/go-bexpr"
|
||||
)
|
||||
|
||||
func init() {
|
||||
extraRdpActionsFlagsMapFunc = extraRdpActionsFlagsMapFuncImpl
|
||||
extraRdpFlagsFunc = extraRdpFlagsFuncImpl
|
||||
extraRdpFlagsHandlingFunc = extraRdpFlagsHandlingFuncImpl
|
||||
extraRdpSynopsisFunc = extraRdpSynopsisFuncImpl
|
||||
}
|
||||
|
||||
func extraRdpActionsFlagsMapFuncImpl() map[string][]string {
|
||||
return map[string][]string{
|
||||
"create": {
|
||||
"address", "default-port", "default-client-port", "session-max-seconds", "session-connection-limit",
|
||||
"egress-worker-filter", "ingress-worker-filter",
|
||||
"with-alias-value", "with-alias-scope-id", "with-alias-authorize-session-host-id",
|
||||
},
|
||||
"update": {
|
||||
"address", "default-port", "default-client-port", "session-max-seconds", "session-connection-limit", "egress-worker-filter", "ingress-worker-filter",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type extraRdpCmdVars struct {
|
||||
flagDefaultPort string
|
||||
flagDefaultClientPort string
|
||||
flagSessionMaxSeconds string
|
||||
flagSessionConnectionLimit string
|
||||
flagEgressWorkerFilter string
|
||||
flagIngressWorkerFilter string
|
||||
flagAddress string
|
||||
flagWithAliasValue string
|
||||
flagWithAliasScopeId string
|
||||
flagWithAliasHostId string
|
||||
}
|
||||
|
||||
func (c *RdpCommand) extraRdpHelpFunc(helpMap map[string]func() string) string {
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "create":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary targets create rdp [options] [args]",
|
||||
"",
|
||||
" Create a rdp-type target. Example:",
|
||||
"",
|
||||
` $ boundary targets create rdp -name prodops -description "Rdp target for ProdOps"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
|
||||
case "update":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary targets update rdp [options] [args]",
|
||||
"",
|
||||
" Update a rdp-type target given its ID. Example:",
|
||||
"",
|
||||
` $ boundary targets update rdp -id trdp_1234567890 -name "devops" -description "Rdp target for DevOps"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func extraRdpFlagsFuncImpl(c *RdpCommand, set *base.FlagSets, f *base.FlagSet) {
|
||||
fs := set.NewFlagSet("RDP Target Options")
|
||||
|
||||
for _, name := range flagsRdpMap[c.Func] {
|
||||
switch name {
|
||||
case "address":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "address",
|
||||
Target: &c.flagAddress,
|
||||
Usage: "Optionally, a valid network address to connect to for this target. Can not be used alongside host sources.",
|
||||
})
|
||||
case "default-port":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "default-port",
|
||||
Target: &c.flagDefaultPort,
|
||||
Usage: "Optionally, the default port to set on the target. If not specified, it will be set to 22.",
|
||||
})
|
||||
case "default-client-port":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "default-client-port",
|
||||
Target: &c.flagDefaultClientPort,
|
||||
Usage: "The default client port to set on the target.",
|
||||
})
|
||||
case "session-max-seconds":
|
||||
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":
|
||||
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 "egress-worker-filter":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "egress-worker-filter",
|
||||
Target: &c.flagEgressWorkerFilter,
|
||||
Usage: "A boolean expression to filter which egress workers can handle sessions for this target.",
|
||||
})
|
||||
case "ingress-worker-filter":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "ingress-worker-filter",
|
||||
Target: &c.flagIngressWorkerFilter,
|
||||
Usage: "A boolean expression to filter which ingress workers can handle sessions for this target.",
|
||||
})
|
||||
case "with-alias-value":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "with-alias-value",
|
||||
Target: &c.flagWithAliasValue,
|
||||
Usage: "The value for an alias to be created for and at the same time as this target.",
|
||||
})
|
||||
case "with-alias-scope-id":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "with-alias-scope-id",
|
||||
Target: &c.flagWithAliasScopeId,
|
||||
Default: "global",
|
||||
Usage: "The scope id for an alias to be created for and at the same time as this target.",
|
||||
})
|
||||
case "with-alias-authorize-session-host-id":
|
||||
fs.StringVar(&base.StringVar{
|
||||
Name: "with-alias-authorize-session-host-id",
|
||||
Target: &c.flagWithAliasHostId,
|
||||
Usage: "The authorize session host id flag used by an alias to be created for and at the same time as this target.",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func extraRdpFlagsHandlingFuncImpl(c *RdpCommand, _ *base.FlagSets, opts *[]targets.Option) bool {
|
||||
switch c.flagDefaultPort {
|
||||
case "":
|
||||
case "null":
|
||||
*opts = append(*opts, targets.DefaultRdpTargetDefaultPort())
|
||||
default:
|
||||
port, err := strconv.ParseUint(c.flagDefaultPort, 10, 32)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error parsing %q: %s", c.flagDefaultPort, err))
|
||||
return false
|
||||
}
|
||||
*opts = append(*opts, targets.WithRdpTargetDefaultPort(uint32(port)))
|
||||
}
|
||||
|
||||
switch c.flagDefaultClientPort {
|
||||
case "":
|
||||
case "null":
|
||||
*opts = append(*opts, targets.DefaultRdpTargetDefaultClientPort())
|
||||
default:
|
||||
port, err := strconv.ParseUint(c.flagDefaultClientPort, 10, 32)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error parsing %q: %s", c.flagDefaultClientPort, err))
|
||||
return false
|
||||
}
|
||||
*opts = append(*opts, targets.WithRdpTargetDefaultClientPort(uint32(port)))
|
||||
}
|
||||
|
||||
switch c.flagSessionMaxSeconds {
|
||||
case "":
|
||||
case "null":
|
||||
*opts = append(*opts, targets.DefaultSessionMaxSeconds())
|
||||
default:
|
||||
var final uint32
|
||||
dur, err := strconv.ParseUint(c.flagSessionMaxSeconds, 10, 32)
|
||||
if err == nil {
|
||||
final = uint32(dur)
|
||||
} else {
|
||||
dur, err := time.ParseDuration(c.flagSessionMaxSeconds)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error parsing %q: %s", c.flagSessionMaxSeconds, err))
|
||||
return false
|
||||
}
|
||||
final = uint32(dur.Seconds())
|
||||
}
|
||||
*opts = append(*opts, targets.WithSessionMaxSeconds(final))
|
||||
}
|
||||
|
||||
switch c.flagSessionConnectionLimit {
|
||||
case "":
|
||||
case "null":
|
||||
*opts = append(*opts, targets.DefaultSessionConnectionLimit())
|
||||
default:
|
||||
limit, err := strconv.ParseInt(c.flagSessionConnectionLimit, 10, 32)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error parsing %q: %s", c.flagSessionConnectionLimit, err))
|
||||
return false
|
||||
}
|
||||
*opts = append(*opts, targets.WithSessionConnectionLimit(int32(limit)))
|
||||
}
|
||||
switch c.flagEgressWorkerFilter {
|
||||
case "":
|
||||
case "null":
|
||||
*opts = append(*opts, targets.DefaultEgressWorkerFilter())
|
||||
default:
|
||||
if _, err := bexpr.CreateEvaluator(c.flagEgressWorkerFilter); err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Unable to successfully parse egress filter expression: %s", err))
|
||||
return false
|
||||
}
|
||||
*opts = append(*opts, targets.WithEgressWorkerFilter(c.flagEgressWorkerFilter))
|
||||
}
|
||||
switch c.flagIngressWorkerFilter {
|
||||
case "":
|
||||
case "null":
|
||||
*opts = append(*opts, targets.DefaultIngressWorkerFilter())
|
||||
default:
|
||||
if _, err := bexpr.CreateEvaluator(c.flagIngressWorkerFilter); err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Unable to successfully parse ingress filter expression: %s", err))
|
||||
return false
|
||||
}
|
||||
*opts = append(*opts, targets.WithIngressWorkerFilter(c.flagIngressWorkerFilter))
|
||||
}
|
||||
|
||||
switch c.flagAddress {
|
||||
case "":
|
||||
case "null":
|
||||
*opts = append(*opts, targets.DefaultAddress())
|
||||
default:
|
||||
*opts = append(*opts, targets.WithAddress(c.flagAddress))
|
||||
}
|
||||
|
||||
var aliasValue string
|
||||
switch c.flagWithAliasValue {
|
||||
case "":
|
||||
case "null":
|
||||
c.UI.Error("The with-alias-value flag cannot be set to null")
|
||||
return false
|
||||
default:
|
||||
aliasValue = c.flagWithAliasValue
|
||||
}
|
||||
|
||||
var aliasScopeId string
|
||||
switch c.flagWithAliasScopeId {
|
||||
case "":
|
||||
case "null":
|
||||
c.UI.Error("The with-alias-scope-id flag cannot be set to null")
|
||||
return false
|
||||
default:
|
||||
aliasScopeId = c.flagWithAliasScopeId
|
||||
}
|
||||
|
||||
var aliasHostId string
|
||||
switch c.flagWithAliasHostId {
|
||||
case "":
|
||||
case "null":
|
||||
c.UI.Error("The with-alias-authorize-session-host-id flag cannot be set to null")
|
||||
return false
|
||||
default:
|
||||
aliasHostId = c.flagWithAliasHostId
|
||||
}
|
||||
|
||||
switch {
|
||||
case aliasValue != "" && aliasScopeId == "":
|
||||
c.UI.Error("The with-alias-value flag must be used with the with-alias-scope-id flag")
|
||||
return false
|
||||
case aliasValue != "" && aliasScopeId != "":
|
||||
a := targets.Alias{
|
||||
Value: aliasValue,
|
||||
ScopeId: aliasScopeId,
|
||||
}
|
||||
if aliasHostId != "" {
|
||||
a.Attributes = &targets.TargetAliasAttributes{
|
||||
AuthorizeSessionArguments: &targets.AuthorizeSessionArguments{
|
||||
HostId: aliasHostId,
|
||||
},
|
||||
}
|
||||
}
|
||||
*opts = append(*opts, targets.WithAliases([]targets.Alias{a}))
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func extraRdpSynopsisFuncImpl(_ *RdpCommand) string {
|
||||
return "Create a rdp-type target (HCP only)"
|
||||
}
|
||||
@ -0,0 +1,294 @@
|
||||
// Code generated by "make cli"; DO NOT EDIT.
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package targetscmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/go-secure-stdlib/strutil"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
func initRdpFlags() {
|
||||
flagsOnce.Do(func() {
|
||||
extraFlags := extraRdpActionsFlagsMapFunc()
|
||||
for k, v := range extraFlags {
|
||||
flagsRdpMap[k] = append(flagsRdpMap[k], v...)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var (
|
||||
_ cli.Command = (*RdpCommand)(nil)
|
||||
_ cli.CommandAutocomplete = (*RdpCommand)(nil)
|
||||
)
|
||||
|
||||
type RdpCommand struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
plural string
|
||||
|
||||
extraRdpCmdVars
|
||||
}
|
||||
|
||||
func (c *RdpCommand) AutocompleteArgs() complete.Predictor {
|
||||
initRdpFlags()
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *RdpCommand) AutocompleteFlags() complete.Flags {
|
||||
initRdpFlags()
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *RdpCommand) Synopsis() string {
|
||||
if extra := extraRdpSynopsisFunc(c); extra != "" {
|
||||
return extra
|
||||
}
|
||||
|
||||
synopsisStr := "target"
|
||||
|
||||
synopsisStr = fmt.Sprintf("%s %s", "rdp-type", synopsisStr)
|
||||
|
||||
return common.SynopsisFunc(c.Func, synopsisStr)
|
||||
}
|
||||
|
||||
func (c *RdpCommand) Help() string {
|
||||
initRdpFlags()
|
||||
|
||||
var helpStr string
|
||||
helpMap := common.HelpMap("target")
|
||||
|
||||
switch c.Func {
|
||||
|
||||
default:
|
||||
|
||||
helpStr = c.extraRdpHelpFunc(helpMap)
|
||||
|
||||
}
|
||||
|
||||
// Keep linter from complaining if we don't actually generate code using it
|
||||
_ = helpMap
|
||||
return helpStr
|
||||
}
|
||||
|
||||
var flagsRdpMap = map[string][]string{
|
||||
|
||||
"create": {"scope-id", "name", "description"},
|
||||
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
func (c *RdpCommand) Flags() *base.FlagSets {
|
||||
if len(flagsRdpMap[c.Func]) == 0 {
|
||||
return c.FlagSet(base.FlagSetNone)
|
||||
}
|
||||
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
f := set.NewFlagSet("Command Options")
|
||||
common.PopulateCommonFlags(c.Command, f, "rdp-type target", flagsRdpMap, c.Func)
|
||||
|
||||
extraRdpFlagsFunc(c, set, f)
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *RdpCommand) Run(args []string) int {
|
||||
initRdpFlags()
|
||||
|
||||
switch c.Func {
|
||||
case "":
|
||||
return cli.RunResultHelp
|
||||
|
||||
}
|
||||
|
||||
c.plural = "rdp-type target"
|
||||
switch c.Func {
|
||||
case "list":
|
||||
c.plural = "rdp-type targets"
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
var alias string
|
||||
alias, args = base.ExtractAliasFromArgs(args)
|
||||
|
||||
if alias != "" {
|
||||
if c.FlagId != "" {
|
||||
c.PrintCliError(errors.New("Cannot specify both an alias and id; choose one or the other"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
c.FlagId = alias
|
||||
}
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsRdpMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.PrintCliError(errors.New("ID is required but not passed in via -id"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var opts []targets.Option
|
||||
|
||||
if strutil.StrListContains(flagsRdpMap[c.Func], "scope-id") {
|
||||
switch c.Func {
|
||||
|
||||
case "create":
|
||||
if c.FlagScopeId == "" {
|
||||
c.PrintCliError(errors.New("Scope ID must be passed in via -scope-id or BOUNDARY_SCOPE_ID"))
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if c.WrapperCleanupFunc != nil {
|
||||
defer func() {
|
||||
if err := c.WrapperCleanupFunc(); err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err != nil {
|
||||
c.PrintCliError(fmt.Errorf("Error creating API client: %w", err))
|
||||
return base.CommandCliError
|
||||
}
|
||||
targetsClient := targets.NewClient(client)
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, targets.DefaultName())
|
||||
default:
|
||||
opts = append(opts, targets.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, targets.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, targets.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
switch c.FlagRecursive {
|
||||
case true:
|
||||
opts = append(opts, targets.WithRecursive(true))
|
||||
}
|
||||
|
||||
if c.FlagFilter != "" {
|
||||
opts = append(opts, targets.WithFilter(c.FlagFilter))
|
||||
}
|
||||
|
||||
var version uint32
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "update":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, targets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ok := extraRdpFlagsHandlingFunc(c, f, &opts); !ok {
|
||||
return base.CommandUserError
|
||||
}
|
||||
|
||||
var resp *api.Response
|
||||
var item *targets.Target
|
||||
|
||||
var createResult *targets.TargetCreateResult
|
||||
|
||||
var updateResult *targets.TargetUpdateResult
|
||||
|
||||
switch c.Func {
|
||||
|
||||
case "create":
|
||||
createResult, err = targetsClient.Create(c.Context, "rdp", c.FlagScopeId, opts...)
|
||||
if exitCode := c.checkFuncError(err); exitCode > 0 {
|
||||
return exitCode
|
||||
}
|
||||
resp = createResult.GetResponse()
|
||||
item = createResult.GetItem()
|
||||
|
||||
case "update":
|
||||
updateResult, err = targetsClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
if exitCode := c.checkFuncError(err); exitCode > 0 {
|
||||
return exitCode
|
||||
}
|
||||
resp = updateResult.GetResponse()
|
||||
item = updateResult.GetItem()
|
||||
|
||||
}
|
||||
|
||||
resp, item, err = executeExtraRdpActions(c, resp, item, err, targetsClient, version, opts)
|
||||
if exitCode := c.checkFuncError(err); exitCode > 0 {
|
||||
return exitCode
|
||||
}
|
||||
|
||||
output, err := printCustomRdpActionOutput(c)
|
||||
if err != nil {
|
||||
c.PrintCliError(err)
|
||||
return base.CommandUserError
|
||||
}
|
||||
if output {
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(printItemTable(item, resp))
|
||||
|
||||
case "json":
|
||||
if ok := c.PrintJsonItem(resp); !ok {
|
||||
return base.CommandCliError
|
||||
}
|
||||
}
|
||||
|
||||
return base.CommandSuccess
|
||||
}
|
||||
|
||||
func (c *RdpCommand) checkFuncError(err error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
if apiErr := api.AsServerError(err); apiErr != nil {
|
||||
c.PrintApiError(apiErr, fmt.Sprintf("Error from controller when performing %s on %s", c.Func, c.plural))
|
||||
return base.CommandApiError
|
||||
}
|
||||
c.PrintCliError(fmt.Errorf("Error trying to %s %s: %s", c.Func, c.plural, err.Error()))
|
||||
return base.CommandCliError
|
||||
}
|
||||
|
||||
var (
|
||||
extraRdpActionsFlagsMapFunc = func() map[string][]string { return nil }
|
||||
extraRdpSynopsisFunc = func(*RdpCommand) string { return "" }
|
||||
extraRdpFlagsFunc = func(*RdpCommand, *base.FlagSets, *base.FlagSet) {}
|
||||
extraRdpFlagsHandlingFunc = func(*RdpCommand, *base.FlagSets, *[]targets.Option) bool { return true }
|
||||
executeExtraRdpActions = func(_ *RdpCommand, inResp *api.Response, inItem *targets.Target, inErr error, _ *targets.Client, _ uint32, _ []targets.Option) (*api.Response, *targets.Target, error) {
|
||||
return inResp, inItem, inErr
|
||||
}
|
||||
printCustomRdpActionOutput = func(*RdpCommand) (bool, error) { return false, nil }
|
||||
)
|
||||
Loading…
Reference in new issue