Skip to content

Commit cb1c2f1

Browse files
authored
Onboard Secrets Manager user create and list commands (#111)
* Onboard secrets manager user: add list command * Onboard secrets manager user: add create command * Updated the Long helper for create command * Update create command to support hidden password * create command: fix formatting and add example for hide-password * create command: make description optional * fix linting * create command: generate docs * create command: improve examples * Address comments
1 parent 0dbae40 commit cb1c2f1

File tree

10 files changed

+877
-0
lines changed

10 files changed

+877
-0
lines changed

docs/stackit_secrets-manager.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ stackit secrets-manager [flags]
2929

3030
* [stackit](./stackit.md) - Manage STACKIT resources using the command line
3131
* [stackit secrets-manager instance](./stackit_secrets-manager_instance.md) - Provides functionality for Secrets Manager instances
32+
* [stackit secrets-manager user](./stackit_secrets-manager_user.md) - Provides functionality for Secrets Manager users
3233

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
## stackit secrets-manager user
2+
3+
Provides functionality for Secrets Manager users
4+
5+
### Synopsis
6+
7+
Provides functionality for Secrets Manager users.
8+
9+
```
10+
stackit secrets-manager user [flags]
11+
```
12+
13+
### Options
14+
15+
```
16+
-h, --help Help for "stackit secrets-manager user"
17+
```
18+
19+
### Options inherited from parent commands
20+
21+
```
22+
-y, --assume-yes If set, skips all confirmation prompts
23+
--async If set, runs the command asynchronously
24+
-o, --output-format string Output format, one of ["json" "pretty"]
25+
-p, --project-id string Project ID
26+
```
27+
28+
### SEE ALSO
29+
30+
* [stackit secrets-manager](./stackit_secrets-manager.md) - Provides functionality for Secrets Manager
31+
* [stackit secrets-manager user create](./stackit_secrets-manager_user_create.md) - Creates a Secrets Manager user
32+
* [stackit secrets-manager user list](./stackit_secrets-manager_user_list.md) - Lists all Secrets Manager users
33+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## stackit secrets-manager user create
2+
3+
Creates a Secrets Manager user
4+
5+
### Synopsis
6+
7+
Creates a user for a Secrets Manager instance with generated username and password
8+
9+
```
10+
stackit secrets-manager user create [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
Create a Secrets Manager user for instance with ID "xxx"
17+
$ stackit mongodbflex user create --instance-id xxx
18+
19+
Create a Secrets Manager user for instance with ID "xxx" and description "yyy"
20+
$ stackit mongodbflex user create --instance-id xxx --description yyy
21+
22+
Create a Secrets Manager user for instance with ID "xxx" and doesn't display the password
23+
$ stackit mongodbflex user create --instance-id xxx --hide-password
24+
25+
Create a Secrets Manager user for instance with ID "xxx" with write access to the secrets engine
26+
$ stackit mongodbflex user create --instance-id xxx --write
27+
```
28+
29+
### Options
30+
31+
```
32+
--description string A user chosen description to differentiate between multiple users
33+
-h, --help Help for "stackit secrets-manager user create"
34+
--hide-password Hide password in output
35+
--instance-id string ID of the instance
36+
--write User write access to the secrets engine. If unset, user is read-only
37+
```
38+
39+
### Options inherited from parent commands
40+
41+
```
42+
-y, --assume-yes If set, skips all confirmation prompts
43+
--async If set, runs the command asynchronously
44+
-o, --output-format string Output format, one of ["json" "pretty"]
45+
-p, --project-id string Project ID
46+
```
47+
48+
### SEE ALSO
49+
50+
* [stackit secrets-manager user](./stackit_secrets-manager_user.md) - Provides functionality for Secrets Manager users
51+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
## stackit secrets-manager user list
2+
3+
Lists all Secrets Manager users
4+
5+
### Synopsis
6+
7+
Lists all Secrets Manager users.
8+
9+
```
10+
stackit secrets-manager user list [flags]
11+
```
12+
13+
### Examples
14+
15+
```
16+
List all Secrets Manager users of instance with ID "xxx
17+
$ stackit secrets-manager user list --instance-id xxx
18+
19+
List all Secrets Manager users in JSON format with ID "xxx
20+
$ stackit secrets-manager user list --instance-id xxx --output-format json
21+
22+
List up to 10 Secrets Manager users with ID "xxx"
23+
$ stackit secrets-manager user list --instance-id xxx --limit 10
24+
```
25+
26+
### Options
27+
28+
```
29+
-h, --help Help for "stackit secrets-manager user list"
30+
--instance-id string Instance ID
31+
--limit int Maximum number of entries to list
32+
```
33+
34+
### Options inherited from parent commands
35+
36+
```
37+
-y, --assume-yes If set, skips all confirmation prompts
38+
--async If set, runs the command asynchronously
39+
-o, --output-format string Output format, one of ["json" "pretty"]
40+
-p, --project-id string Project ID
41+
```
42+
43+
### SEE ALSO
44+
45+
* [stackit secrets-manager user](./stackit_secrets-manager_user.md) - Provides functionality for Secrets Manager users
46+

internal/cmd/secrets-manager/secrets_manager.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package secretsmanager
22

33
import (
44
"github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance"
5+
"github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user"
56
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
67
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
78

@@ -22,4 +23,5 @@ func NewCmd() *cobra.Command {
2223

2324
func addSubcommands(cmd *cobra.Command) {
2425
cmd.AddCommand(instance.NewCmd())
26+
cmd.AddCommand(user.NewCmd())
2527
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package create
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
8+
"github.com/stackitcloud/stackit-cli/internal/pkg/confirm"
9+
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
10+
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
11+
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/services/secrets-manager/client"
14+
secretsManagerUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/secrets-manager/utils"
15+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
16+
17+
"github.com/spf13/cobra"
18+
"github.com/stackitcloud/stackit-sdk-go/services/secretsmanager"
19+
)
20+
21+
const (
22+
instanceIdFlag = "instance-id"
23+
descriptionFlag = "description"
24+
writeFlag = "write"
25+
hidePasswordFlag = "hide-password"
26+
)
27+
28+
type inputModel struct {
29+
*globalflags.GlobalFlagModel
30+
31+
InstanceId string
32+
Description *string
33+
Write *bool
34+
HidePassword bool
35+
}
36+
37+
func NewCmd() *cobra.Command {
38+
cmd := &cobra.Command{
39+
Use: "create",
40+
Short: "Creates a Secrets Manager user",
41+
Long: fmt.Sprintf("%s\n%s\n%s",
42+
"Creates a Secrets Manager user.",
43+
"The username and password are auto-generated and provided upon creation.",
44+
"A description can be provided to identify a user.",
45+
),
46+
Example: examples.Build(
47+
examples.NewExample(
48+
`Create a Secrets Manager user for instance with ID "xxx" and description "yyy"`,
49+
"$ stackit secrets-manager user create --instance-id xxx --description yyy"),
50+
examples.NewExample(
51+
`Create a Secrets Manager user for instance with ID "xxx" and hides the generated password`,
52+
"$ stackit secrets-manager user create --instance-id xxx --hide-password"),
53+
examples.NewExample(
54+
`Create a Secrets Manager user for instance with ID "xxx" with write access to the secrets engine`,
55+
"$ stackit secrets-manager user create --instance-id xxx --write"),
56+
),
57+
Args: args.NoArgs,
58+
RunE: func(cmd *cobra.Command, args []string) error {
59+
ctx := context.Background()
60+
model, err := parseInput(cmd)
61+
if err != nil {
62+
return err
63+
}
64+
65+
// Configure API client
66+
apiClient, err := client.ConfigureClient(cmd)
67+
if err != nil {
68+
return err
69+
}
70+
71+
instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId)
72+
if err != nil {
73+
instanceLabel = model.InstanceId
74+
}
75+
76+
if !model.AssumeYes {
77+
prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel)
78+
err = confirm.PromptForConfirmation(cmd, prompt)
79+
if err != nil {
80+
return err
81+
}
82+
}
83+
84+
// Call API
85+
req := buildRequest(ctx, model, apiClient)
86+
resp, err := req.Execute()
87+
if err != nil {
88+
return fmt.Errorf("create Secrets Manager user: %w", err)
89+
}
90+
91+
cmd.Printf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *resp.Id)
92+
cmd.Printf("Username: %s\n", *resp.Username)
93+
if model.HidePassword {
94+
cmd.Printf("Password: <hidden>\n")
95+
} else {
96+
cmd.Printf("Password: %s\n", *resp.Password)
97+
}
98+
cmd.Printf("Description: %s\n", *resp.Description)
99+
cmd.Printf("Write Access: %t\n", *resp.Write)
100+
101+
return nil
102+
},
103+
}
104+
105+
configureFlags(cmd)
106+
return cmd
107+
}
108+
109+
func configureFlags(cmd *cobra.Command) {
110+
cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance")
111+
cmd.Flags().String(descriptionFlag, "", "A user chosen description to differentiate between multiple users")
112+
cmd.Flags().Bool(writeFlag, false, "User write access to the secrets engine. If unset, user is read-only")
113+
cmd.Flags().Bool(hidePasswordFlag, false, "Hide password in output")
114+
115+
err := flags.MarkFlagsRequired(cmd, instanceIdFlag)
116+
cobra.CheckErr(err)
117+
}
118+
119+
func parseInput(cmd *cobra.Command) (*inputModel, error) {
120+
globalFlags := globalflags.Parse(cmd)
121+
if globalFlags.ProjectId == "" {
122+
return nil, &errors.ProjectIdError{}
123+
}
124+
125+
return &inputModel{
126+
GlobalFlagModel: globalFlags,
127+
InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag),
128+
Description: utils.Ptr(flags.FlagToStringValue(cmd, descriptionFlag)),
129+
Write: utils.Ptr(flags.FlagToBoolValue(cmd, writeFlag)),
130+
HidePassword: flags.FlagToBoolValue(cmd, hidePasswordFlag),
131+
}, nil
132+
}
133+
134+
func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiCreateUserRequest {
135+
req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId)
136+
req = req.CreateUserPayload(secretsmanager.CreateUserPayload{
137+
Description: model.Description,
138+
Write: model.Write,
139+
})
140+
return req
141+
}

0 commit comments

Comments
 (0)