Skip to content

Commit 0462c0d

Browse files
committed
update BYOK CLI
1 parent 7eefd89 commit 0462c0d

31 files changed

+476
-114
lines changed

internal/byok/command.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@ type command struct {
1313
}
1414

1515
type out struct {
16-
Id string `human:"ID" serialized:"id"`
17-
Key string `human:"Key" serialized:"key"`
18-
Roles []string `human:"Roles" serialized:"roles"`
19-
Cloud string `human:"Cloud" serialized:"cloud"`
20-
State string `human:"State" serialized:"state"`
21-
CreatedAt string `human:"Created At" serialized:"created_at"`
16+
Id string `human:"ID" serialized:"id"`
17+
DisplayName string `human:"Display Name,omitempty" serialized:"display_name,omitempty"`
18+
Key string `human:"Key" serialized:"key"`
19+
Roles []string `human:"Roles" serialized:"roles"`
20+
Cloud string `human:"Cloud" serialized:"cloud"`
21+
State string `human:"State" serialized:"state"`
22+
CreatedAt string `human:"Created At" serialized:"created_at"`
23+
ValidationPhase string `human:"Validation Phase" serialized:"validation_phase"`
24+
ValidationSince string `human:"Validation Since" serialized:"validation_since"`
25+
ValidationRegion string `human:"Validation Region,omitempty" serialized:"validation_region,omitempty"`
26+
ValidationMessage string `human:"Validation Message,omitempty" serialized:"validation_message,omitempty"`
2227
}
2328

2429
func New(prerunner pcmd.PreRunner) *cobra.Command {
@@ -34,6 +39,7 @@ func New(prerunner pcmd.PreRunner) *cobra.Command {
3439
cmd.AddCommand(c.newDeleteCommand())
3540
cmd.AddCommand(c.newDescribeCommand())
3641
cmd.AddCommand(c.newListCommand())
42+
cmd.AddCommand(c.newUpdateCommand())
3743

3844
return cmd
3945
}

internal/byok/command_create.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,21 +74,26 @@ func (c *command) newCreateCommand() *cobra.Command {
7474

7575
cmd.Flags().String("key-vault", "", "The ID of the Azure Key Vault where the key is stored.")
7676
cmd.Flags().String("tenant", "", "The ID of the Azure Active Directory tenant that the key vault belongs to.")
77+
cmd.Flags().String("display-name", "", "A human-readable name for the self-managed key.")
7778
pcmd.AddOutputFlag(cmd)
7879

7980
cmd.MarkFlagsRequiredTogether("key-vault", "tenant")
8081

8182
return cmd
8283
}
8384

84-
func (c *command) createAwsKeyRequest(keyArn string) byokv1.ByokV1Key {
85-
return byokv1.ByokV1Key{Key: &byokv1.ByokV1KeyKeyOneOf{ByokV1AwsKey: &byokv1.ByokV1AwsKey{
85+
func (c *command) createAwsKeyRequest(keyArn, displayName string) byokv1.ByokV1Key {
86+
key := byokv1.ByokV1Key{Key: &byokv1.ByokV1KeyKeyOneOf{ByokV1AwsKey: &byokv1.ByokV1AwsKey{
8687
KeyArn: keyArn,
8788
Kind: "AwsKey",
8889
}}}
90+
if displayName != "" {
91+
key.SetDisplayName(displayName)
92+
}
93+
return key
8994
}
9095

91-
func (c *command) createAzureKeyRequest(cmd *cobra.Command, keyString string) (byokv1.ByokV1Key, error) {
96+
func (c *command) createAzureKeyRequest(cmd *cobra.Command, keyString, displayName string) (byokv1.ByokV1Key, error) {
9297
keyVault, err := cmd.Flags().GetString("key-vault")
9398
if err != nil {
9499
return byokv1.ByokV1Key{}, err
@@ -106,33 +111,46 @@ func (c *command) createAzureKeyRequest(cmd *cobra.Command, keyString string) (b
106111
Kind: "AzureKey",
107112
}}}
108113

114+
if displayName != "" {
115+
keyReq.SetDisplayName(displayName)
116+
}
117+
109118
return keyReq, nil
110119
}
111120

112-
func (c *command) createGcpKeyRequest(keyString string) byokv1.ByokV1Key {
113-
return byokv1.ByokV1Key{Key: &byokv1.ByokV1KeyKeyOneOf{ByokV1GcpKey: &byokv1.ByokV1GcpKey{
121+
func (c *command) createGcpKeyRequest(keyString, displayName string) byokv1.ByokV1Key {
122+
key := byokv1.ByokV1Key{Key: &byokv1.ByokV1KeyKeyOneOf{ByokV1GcpKey: &byokv1.ByokV1GcpKey{
114123
KeyId: keyString,
115124
Kind: "GcpKey",
116125
}}}
126+
if displayName != "" {
127+
key.SetDisplayName(displayName)
128+
}
129+
return key
117130
}
118131

119132
func (c *command) create(cmd *cobra.Command, args []string) error {
120133
keyString := args[0]
121134
var keyReq byokv1.ByokV1Key
122135

136+
displayName, err := cmd.Flags().GetString("display-name")
137+
if err != nil {
138+
return err
139+
}
140+
123141
switch {
124142
case cmd.Flags().Changed("key-vault") && cmd.Flags().Changed("tenant"):
125143
keyString = removeKeyVersionFromAzureKeyId(keyString)
126144

127-
request, err := c.createAzureKeyRequest(cmd, keyString)
145+
request, err := c.createAzureKeyRequest(cmd, keyString, displayName)
128146
if err != nil {
129147
return err
130148
}
131149
keyReq = request
132150
case isAWSKey(keyString):
133-
keyReq = c.createAwsKeyRequest(keyString)
151+
keyReq = c.createAwsKeyRequest(keyString, displayName)
134152
case isGcpKey(keyString):
135-
keyReq = c.createGcpKeyRequest(keyString)
153+
keyReq = c.createGcpKeyRequest(keyString, displayName)
136154
default:
137155
return fmt.Errorf("invalid key format: %s", keyString)
138156
}

internal/byok/command_describe.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,17 @@ func (c *command) outputByokKeyDescription(cmd *cobra.Command, key byokv1.ByokV1
5353

5454
table := output.NewTable(cmd)
5555
table.Add(&out{
56-
Id: key.GetId(),
57-
Key: keyString,
58-
Roles: roles,
59-
Cloud: key.GetProvider(),
60-
State: key.GetState(),
61-
CreatedAt: key.Metadata.CreatedAt.String(),
56+
Id: key.GetId(),
57+
DisplayName: key.GetDisplayName(),
58+
Key: keyString,
59+
Roles: roles,
60+
Cloud: key.GetProvider(),
61+
State: key.GetState(),
62+
CreatedAt: key.Metadata.CreatedAt.String(),
63+
ValidationPhase: key.Validation.GetPhase(),
64+
ValidationSince: key.Validation.GetSince().String(),
65+
ValidationRegion: key.Validation.GetRegion(),
66+
ValidationMessage: key.Validation.GetMessage(),
6267
})
6368
table.Print()
6469

internal/byok/command_list.go

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ func (c *command) newListCommand() *cobra.Command {
1919

2020
pcmd.AddCloudFlag(cmd)
2121
pcmd.AddByokStateFlag(cmd)
22+
cmd.Flags().String("region", "", "Filter by region.")
23+
cmd.Flags().String("phase", "", "Filter by validation phase.")
24+
cmd.Flags().String("display-name", "", "Filter by display name.")
25+
cmd.Flags().String("key", "", "Filter by key identifier.")
2226
pcmd.AddOutputFlag(cmd)
2327

2428
return cmd
@@ -49,7 +53,27 @@ func (c *command) list(cmd *cobra.Command, _ []string) error {
4953
state = "AVAILABLE"
5054
}
5155

52-
keys, err := c.V2Client.ListByokKeys(cloud, state)
56+
region, err := cmd.Flags().GetString("region")
57+
if err != nil {
58+
return err
59+
}
60+
61+
phase, err := cmd.Flags().GetString("phase")
62+
if err != nil {
63+
return err
64+
}
65+
66+
displayName, err := cmd.Flags().GetString("display-name")
67+
if err != nil {
68+
return err
69+
}
70+
71+
key, err := cmd.Flags().GetString("key")
72+
if err != nil {
73+
return err
74+
}
75+
76+
keys, err := c.V2Client.ListByokKeys(cloud, state, region, phase, displayName, key)
5377
if err != nil {
5478
return err
5579
}
@@ -69,17 +93,22 @@ func (c *command) list(cmd *cobra.Command, _ []string) error {
6993
}
7094

7195
list.Add(&out{
72-
Id: key.GetId(),
73-
Key: keyString,
74-
Cloud: key.GetProvider(),
75-
State: key.GetState(),
76-
CreatedAt: key.Metadata.CreatedAt.String(),
96+
Id: key.GetId(),
97+
DisplayName: key.GetDisplayName(),
98+
Key: keyString,
99+
Cloud: key.GetProvider(),
100+
State: key.GetState(),
101+
CreatedAt: key.Metadata.CreatedAt.String(),
102+
ValidationPhase: key.Validation.GetPhase(),
103+
ValidationSince: key.Validation.GetSince().String(),
104+
ValidationRegion: key.Validation.GetRegion(),
105+
ValidationMessage: key.Validation.GetMessage(),
77106
})
78107
}
79108

80109
// The API returns a list sorted by creation date already
81110
list.Sort(false)
82-
list.Filter([]string{"Id", "Key", "Cloud", "State", "CreatedAt"})
111+
list.Filter([]string{"Id", "DisplayName", "Key", "Cloud", "State", "CreatedAt"})
83112

84113
return list.Print()
85114
}

internal/byok/command_update.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package byok
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
6+
byokv1 "github.com/confluentinc/ccloud-sdk-go-v2/byok/v1"
7+
8+
pcmd "github.com/confluentinc/cli/v4/pkg/cmd"
9+
"github.com/confluentinc/cli/v4/pkg/errors"
10+
"github.com/confluentinc/cli/v4/pkg/examples"
11+
)
12+
13+
func (c *command) newUpdateCommand() *cobra.Command {
14+
cmd := &cobra.Command{
15+
Use: "update <id>",
16+
Short: "Update a self-managed key.",
17+
Long: "Update a self-managed key in Confluent Cloud.",
18+
Args: cobra.ExactArgs(1),
19+
ValidArgsFunction: pcmd.NewValidArgsFunction(c.validArgs),
20+
RunE: c.update,
21+
Example: examples.BuildExampleString(
22+
examples.Example{
23+
Text: `Update the display name of self-managed key "cck-12345".`,
24+
Code: `confluent byok update cck-12345 --display-name "My production key"`,
25+
},
26+
),
27+
}
28+
29+
cmd.Flags().String("display-name", "", "A human-readable name for the self-managed key.")
30+
pcmd.AddOutputFlag(cmd)
31+
32+
cobra.CheckErr(cmd.MarkFlagRequired("display-name"))
33+
34+
return cmd
35+
}
36+
37+
func (c *command) update(cmd *cobra.Command, args []string) error {
38+
keyId := args[0]
39+
40+
displayName, err := cmd.Flags().GetString("display-name")
41+
if err != nil {
42+
return err
43+
}
44+
45+
// Use dedicated update struct following the pattern from API Keys
46+
updateReq := byokv1.ByokV1KeyUpdate{
47+
DisplayName: byokv1.PtrString(displayName),
48+
}
49+
50+
key, httpResp, err := c.V2Client.UpdateByokKey(keyId, updateReq)
51+
if err != nil {
52+
return errors.CatchByokKeyNotFoundError(err, httpResp)
53+
}
54+
55+
return c.outputByokKeyDescription(cmd, key)
56+
}

pkg/ccloudv2/byok.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,21 @@ func (c *Client) GetByokKey(keyId string) (byokv1.ByokV1Key, *http.Response, err
3131
return c.ByokClient.KeysByokV1Api.GetByokV1Key(c.byokApiContext(), keyId).Execute()
3232
}
3333

34+
func (c *Client) UpdateByokKey(keyId string, keyUpdate byokv1.ByokV1KeyUpdate) (byokv1.ByokV1Key, *http.Response, error) {
35+
return c.ByokClient.KeysByokV1Api.UpdateByokV1Key(c.byokApiContext(), keyId).ByokV1KeyUpdate(keyUpdate).Execute()
36+
}
37+
3438
func (c *Client) DeleteByokKey(keyId string) (*http.Response, error) {
3539
return c.ByokClient.KeysByokV1Api.DeleteByokV1Key(c.byokApiContext(), keyId).Execute()
3640
}
3741

38-
func (c *Client) ListByokKeys(provider, state string) ([]byokv1.ByokV1Key, error) {
42+
func (c *Client) ListByokKeys(provider, state, region, phase, displayName, key string) ([]byokv1.ByokV1Key, error) {
3943
var list []byokv1.ByokV1Key
4044

4145
done := false
4246
pageToken := ""
4347
for !done {
44-
page, httpResp, err := c.executeListByokKeys(pageToken, provider, state)
48+
page, httpResp, err := c.executeListByokKeys(pageToken, provider, state, region, phase, displayName, key)
4549
if err != nil {
4650
return nil, errors.CatchCCloudV2Error(err, httpResp)
4751
}
@@ -55,14 +59,26 @@ func (c *Client) ListByokKeys(provider, state string) ([]byokv1.ByokV1Key, error
5559
return list, nil
5660
}
5761

58-
func (c *Client) executeListByokKeys(pageToken, provider, state string) (byokv1.ByokV1KeyList, *http.Response, error) {
62+
func (c *Client) executeListByokKeys(pageToken, provider, state, region, phase, displayName, key string) (byokv1.ByokV1KeyList, *http.Response, error) {
5963
req := c.ByokClient.KeysByokV1Api.ListByokV1Keys(c.byokApiContext()).PageSize(ccloudV2ListPageSize)
6064
if provider != "" {
6165
req = req.Provider(provider)
6266
}
6367
if state != "" {
6468
req = req.State(state)
6569
}
70+
if region != "" {
71+
req = req.ValidationRegion(region)
72+
}
73+
if phase != "" {
74+
req = req.ValidationPhase(phase)
75+
}
76+
if displayName != "" {
77+
req = req.DisplayName(displayName)
78+
}
79+
if key != "" {
80+
req = req.Key(key)
81+
}
6682
if pageToken != "" {
6783
req = req.PageToken(pageToken)
6884
}

pkg/cmd/flags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func AddByokKeyFlag(cmd *cobra.Command, command *AuthenticatedCLICommand) {
6767
}
6868

6969
func AutocompleteByokKeyIds(client *ccloudv2.Client) []string {
70-
keys, err := client.ListByokKeys("", "")
70+
keys, err := client.ListByokKeys("", "", "", "", "", "")
7171
if err != nil {
7272
return nil
7373
}

test/byok_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,17 @@ func (s *CLITestSuite) TestByok() {
99
{args: "byok list --state in-use", fixture: "byok/list_2.golden"},
1010
{args: "byok list --cloud aws", fixture: "byok/list_3.golden"},
1111
{args: "byok list --state in-use --cloud azure", fixture: "byok/list_4.golden"},
12+
{args: "byok list --region us-east-1", fixture: "byok/list_5.golden"},
13+
{args: "byok list --phase VALID", fixture: "byok/list_6.golden"},
14+
{args: "byok list --display-name 'Development AWS Key'", fixture: "byok/list_7.golden"},
15+
{args: "byok list --key 'a-vault'", fixture: "byok/list_8.golden"},
1216
// create tests
1317
{args: "byok create arn:aws:kms:us-west-2:037803949979:key/0e2609e3-a0bf-4f39-aedf-8b1f63b16d81", fixture: "byok/create_1.golden"},
1418
{args: "byok create https://a-vault.vault.azure.net/keys/a-key/00000000000000000000000000000000 --tenant 00000000-0000-0000-0000-000000000000 --key-vault /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/a-resourcegroups/providers/Microsoft.KeyVault/vaults/a-vault", fixture: "byok/create_2.golden"},
1519
{args: "byok create https://a-vault.vault.azure.net/keys/a-key/00000000000000000000000000000000 --tenant 00000000-0000-0000-0000-000000000000", fixture: "byok/create_3.golden", exitCode: 1},
1620
{args: "byok create https://a-vault.vault.azure.net/keys/a-key/00000000000000000000000000000000", fixture: "byok/create_4.golden", exitCode: 1},
1721
{args: "byok create projects/exampleproject/locations/us-central1/keyRings/testkeyring/cryptoKeys/testbyokkey/cryptoKeyVersions/3", fixture: "byok/create_5.golden"},
22+
{args: "byok create projects/exampleproject/locations/us-central1/keyRings/testkeyring/cryptoKeys/testbyokkey/cryptoKeyVersions/4 --display-name 'Test GCP Key'", fixture: "byok/create_6.golden"},
1823
}
1924

2025
resetConfiguration(s.T(), false)
@@ -58,6 +63,19 @@ func (s *CLITestSuite) TestByokDescribe() {
5863
}
5964
}
6065

66+
func (s *CLITestSuite) TestByokUpdate() {
67+
tests := []CLITest{
68+
{args: `byok update cck-001 --display-name "Updated Production Key"`, fixture: "byok/update-success.golden"},
69+
{args: `byok update cck-001 --display-name "Updated Production Key" -o json`, fixture: "byok/update-success-json.golden"},
70+
{args: "byok update cck-404 --display-name \"Non-existent Key\"", fixture: "byok/update-fail.golden", exitCode: 1},
71+
}
72+
73+
for _, test := range tests {
74+
test.login = "cloud"
75+
s.runIntegrationTest(test)
76+
}
77+
}
78+
6179
func (s *CLITestSuite) TestByok_Autocomplete() {
6280
test := CLITest{args: `__complete byok describe ""`, login: "cloud", fixture: "byok/describe-autocomplete.golden"}
6381
s.runIntegrationTest(test)

test/fixtures/output/byok/create_1.golden

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
+------------+-----------------------------------------------------------------------------+
2-
| ID | cck-004 |
3-
| Key | arn:aws:kms:us-west-2:037803949979:key/0e2609e3-a0bf-4f39-aedf-8b1f63b16d81 |
4-
| Roles | arn:aws:iam::123456789012:role/role1, |
5-
| | arn:aws:iam::123456789012:role/role2 |
6-
| Cloud | AWS |
7-
| State | AVAILABLE |
8-
| Created At | 2022-12-24 00:00:00 +0000 UTC |
9-
+------------+-----------------------------------------------------------------------------+
1+
+------------------+-----------------------------------------------------------------------------+
2+
| ID | cck-004 |
3+
| Key | arn:aws:kms:us-west-2:037803949979:key/0e2609e3-a0bf-4f39-aedf-8b1f63b16d81 |
4+
| Roles | arn:aws:iam::123456789012:role/role1, |
5+
| | arn:aws:iam::123456789012:role/role2 |
6+
| Cloud | AWS |
7+
| State | AVAILABLE |
8+
| Created At | 2022-12-24 00:00:00 +0000 UTC |
9+
| Validation Phase | INITIALIZING |
10+
| Validation Since | 2022-12-24 00:00:00 +0000 UTC |
11+
+------------------+-----------------------------------------------------------------------------+
1012

1113
Copy and append these permissions into the key policy "Statements" field of the ARN in your AWS key management system to authorize access for your Confluent Cloud cluster.
1214

0 commit comments

Comments
 (0)