Skip to content
1 change: 1 addition & 0 deletions docs/stackit_secrets-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ stackit secrets-manager [flags]

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

33 changes: 33 additions & 0 deletions docs/stackit_secrets-manager_user.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
## stackit secrets-manager user

Provides functionality for Secrets Manager users

### Synopsis

Provides functionality for Secrets Manager users.

```
stackit secrets-manager user [flags]
```

### Options

```
-h, --help Help for "stackit secrets-manager user"
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty"]
-p, --project-id string Project ID
```

### SEE ALSO

* [stackit secrets-manager](./stackit_secrets-manager.md) - Provides functionality for Secrets Manager
* [stackit secrets-manager user create](./stackit_secrets-manager_user_create.md) - Creates a Secrets Manager user
* [stackit secrets-manager user list](./stackit_secrets-manager_user_list.md) - Lists all Secrets Manager users

51 changes: 51 additions & 0 deletions docs/stackit_secrets-manager_user_create.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
## stackit secrets-manager user create

Creates a Secrets Manager user

### Synopsis

Creates a user for a Secrets Manager instance with generated username and password

```
stackit secrets-manager user create [flags]
```

### Examples

```
Create a Secrets Manager user for instance with ID "xxx"
$ stackit mongodbflex user create --instance-id xxx

Create a Secrets Manager user for instance with ID "xxx" and description "yyy"
$ stackit mongodbflex user create --instance-id xxx --description yyy

Create a Secrets Manager user for instance with ID "xxx" and doesn't display the password
$ stackit mongodbflex user create --instance-id xxx --hide-password

Create a Secrets Manager user for instance with ID "xxx" with write access to the secrets engine
$ stackit mongodbflex user create --instance-id xxx --write
```

### Options

```
--description string A user chosen description to differentiate between multiple users
-h, --help Help for "stackit secrets-manager user create"
--hide-password Hide password in output
--instance-id string ID of the instance
--write User write access to the secrets engine. If unset, user is read-only
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty"]
-p, --project-id string Project ID
```

### SEE ALSO

* [stackit secrets-manager user](./stackit_secrets-manager_user.md) - Provides functionality for Secrets Manager users

46 changes: 46 additions & 0 deletions docs/stackit_secrets-manager_user_list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
## stackit secrets-manager user list

Lists all Secrets Manager users

### Synopsis

Lists all Secrets Manager users.

```
stackit secrets-manager user list [flags]
```

### Examples

```
List all Secrets Manager users of instance with ID "xxx
$ stackit secrets-manager user list --instance-id xxx

List all Secrets Manager users in JSON format with ID "xxx
$ stackit secrets-manager user list --instance-id xxx --output-format json

List up to 10 Secrets Manager users with ID "xxx"
$ stackit secrets-manager user list --instance-id xxx --limit 10
```

### Options

```
-h, --help Help for "stackit secrets-manager user list"
--instance-id string Instance ID
--limit int Maximum number of entries to list
```

### Options inherited from parent commands

```
-y, --assume-yes If set, skips all confirmation prompts
--async If set, runs the command asynchronously
-o, --output-format string Output format, one of ["json" "pretty"]
-p, --project-id string Project ID
```

### SEE ALSO

* [stackit secrets-manager user](./stackit_secrets-manager_user.md) - Provides functionality for Secrets Manager users

2 changes: 2 additions & 0 deletions internal/cmd/secrets-manager/secrets_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package secretsmanager

import (
"github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/instance"
"github.com/stackitcloud/stackit-cli/internal/cmd/secrets-manager/user"
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"

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

func addSubcommands(cmd *cobra.Command) {
cmd.AddCommand(instance.NewCmd())
cmd.AddCommand(user.NewCmd())
}
141 changes: 141 additions & 0 deletions internal/cmd/secrets-manager/user/create/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package create

import (
"context"
"fmt"

"github.com/stackitcloud/stackit-cli/internal/pkg/args"
"github.com/stackitcloud/stackit-cli/internal/pkg/confirm"
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
"github.com/stackitcloud/stackit-cli/internal/pkg/flags"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/services/secrets-manager/client"
secretsManagerUtils "github.com/stackitcloud/stackit-cli/internal/pkg/services/secrets-manager/utils"
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"

"github.com/spf13/cobra"
"github.com/stackitcloud/stackit-sdk-go/services/secretsmanager"
)

const (
instanceIdFlag = "instance-id"
descriptionFlag = "description"
writeFlag = "write"
hidePasswordFlag = "hide-password"
)

type inputModel struct {
*globalflags.GlobalFlagModel

InstanceId string
Description *string
Write *bool
HidePassword bool
}

func NewCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create",
Short: "Creates a Secrets Manager user",
Long: fmt.Sprintf("%s\n%s\n%s",
"Creates a Secrets Manager user.",
"The username and password are auto-generated and provided upon creation.",
"A description can be provided to identify a user.",
),
Example: examples.Build(
examples.NewExample(
`Create a Secrets Manager user for instance with ID "xxx" and description "yyy"`,
"$ stackit secrets-manager user create --instance-id xxx --description yyy"),
examples.NewExample(
`Create a Secrets Manager user for instance with ID "xxx" and hides the generated password`,
"$ stackit secrets-manager user create --instance-id xxx --hide-password"),
examples.NewExample(
`Create a Secrets Manager user for instance with ID "xxx" with write access to the secrets engine`,
"$ stackit secrets-manager user create --instance-id xxx --write"),
),
Args: args.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := context.Background()
model, err := parseInput(cmd)
if err != nil {
return err
}

// Configure API client
apiClient, err := client.ConfigureClient(cmd)
if err != nil {
return err
}

instanceLabel, err := secretsManagerUtils.GetInstanceName(ctx, apiClient, model.ProjectId, model.InstanceId)
if err != nil {
instanceLabel = model.InstanceId
}

if !model.AssumeYes {
prompt := fmt.Sprintf("Are you sure you want to create a user for instance %q?", instanceLabel)
err = confirm.PromptForConfirmation(cmd, prompt)
if err != nil {
return err
}
}

// Call API
req := buildRequest(ctx, model, apiClient)
resp, err := req.Execute()
if err != nil {
return fmt.Errorf("create Secrets Manager user: %w", err)
}

cmd.Printf("Created user for instance %q. User ID: %s\n\n", instanceLabel, *resp.Id)
cmd.Printf("Username: %s\n", *resp.Username)
if model.HidePassword {
cmd.Printf("Password: <hidden>\n")
} else {
cmd.Printf("Password: %s\n", *resp.Password)
}
cmd.Printf("Description: %s\n", *resp.Description)
cmd.Printf("Write Access: %t\n", *resp.Write)

return nil
},
}

configureFlags(cmd)
return cmd
}

func configureFlags(cmd *cobra.Command) {
cmd.Flags().Var(flags.UUIDFlag(), instanceIdFlag, "ID of the instance")
cmd.Flags().String(descriptionFlag, "", "A user chosen description to differentiate between multiple users")
cmd.Flags().Bool(writeFlag, false, "User write access to the secrets engine. If unset, user is read-only")
cmd.Flags().Bool(hidePasswordFlag, false, "Hide password in output")

err := flags.MarkFlagsRequired(cmd, instanceIdFlag)
cobra.CheckErr(err)
}

func parseInput(cmd *cobra.Command) (*inputModel, error) {
globalFlags := globalflags.Parse(cmd)
if globalFlags.ProjectId == "" {
return nil, &errors.ProjectIdError{}
}

return &inputModel{
GlobalFlagModel: globalFlags,
InstanceId: flags.FlagToStringValue(cmd, instanceIdFlag),
Description: utils.Ptr(flags.FlagToStringValue(cmd, descriptionFlag)),
Write: utils.Ptr(flags.FlagToBoolValue(cmd, writeFlag)),
HidePassword: flags.FlagToBoolValue(cmd, hidePasswordFlag),
}, nil
}

func buildRequest(ctx context.Context, model *inputModel, apiClient *secretsmanager.APIClient) secretsmanager.ApiCreateUserRequest {
req := apiClient.CreateUser(ctx, model.ProjectId, model.InstanceId)
req = req.CreateUserPayload(secretsmanager.CreateUserPayload{
Description: model.Description,
Write: model.Write,
})
return req
}
Loading