Skip to content

Commit ccf449e

Browse files
committed
govc: add kms commands
1 parent 796892a commit ccf449e

File tree

8 files changed

+701
-0
lines changed

8 files changed

+701
-0
lines changed

govc/USAGE.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,11 @@ but appear via `govc $cmd -h`:
218218
- [import.ovf](#importovf)
219219
- [import.spec](#importspec)
220220
- [import.vmdk](#importvmdk)
221+
- [kms.add](#kmsadd)
222+
- [kms.default](#kmsdefault)
223+
- [kms.ls](#kmsls)
224+
- [kms.rm](#kmsrm)
225+
- [kms.trust](#kmstrust)
221226
- [library.checkin](#librarycheckin)
222227
- [library.checkout](#librarycheckout)
223228
- [library.clone](#libraryclone)
@@ -3582,6 +3587,93 @@ Options:
35823587
-pool= Resource pool [GOVC_RESOURCE_POOL]
35833588
```
35843589

3590+
## kms.add
3591+
3592+
```
3593+
Usage: govc kms.add [OPTIONS] NAME
3594+
3595+
Add KMS cluster.
3596+
3597+
Server name and address are required, port defaults to 5696.
3598+
3599+
Examples:
3600+
govc kms.add -n my-server -a kms.example.com my-kp
3601+
3602+
Options:
3603+
-a= Server address
3604+
-n= Server name
3605+
-p=5696 Server port
3606+
```
3607+
3608+
## kms.default
3609+
3610+
```
3611+
Usage: govc kms.default [OPTIONS] NAME
3612+
3613+
Set default KMS cluster.
3614+
3615+
Examples:
3616+
govc kms.default my-kp
3617+
govc kms.default - # clear default
3618+
govc kms.default -e /dc/host/cluster my-kp
3619+
govc kms.default -e /dc/host/cluster my-kp - # clear default
3620+
3621+
Options:
3622+
-e= Set entity default KMS cluster (cluster or host folder)
3623+
```
3624+
3625+
## kms.ls
3626+
3627+
```
3628+
Usage: govc kms.ls [OPTIONS] NAME
3629+
3630+
Display KMS info.
3631+
3632+
Examples:
3633+
govc kms.ls
3634+
govc kms.ls -json
3635+
govc kms.ls - # default provider
3636+
govc kms.ls ProviderName
3637+
govc kms.ls -json ProviderName
3638+
3639+
Options:
3640+
```
3641+
3642+
## kms.rm
3643+
3644+
```
3645+
Usage: govc kms.rm [OPTIONS] NAME
3646+
3647+
Remove KMS server or cluster.
3648+
3649+
Examples:
3650+
govc kms.rm my-kp
3651+
govc kms.rm -s my-server my-kp
3652+
3653+
Options:
3654+
-s= Server name
3655+
```
3656+
3657+
## kms.trust
3658+
3659+
```
3660+
Usage: govc kms.trust [OPTIONS] NAME
3661+
3662+
Establish trust between KMS and vCenter.
3663+
3664+
Examples:
3665+
# "Make vCenter Trust KMS"
3666+
govc kms.trust -server-cert "$(govc about.cert -show)" my-kp
3667+
3668+
# "Make KMS Trust vCenter" -> "KMS certificate and private key"
3669+
govc kms.trust -client-cert "$(cat crt.pem) -client-key "$(cat key.pem) my-kp
3670+
3671+
# "Download the vCenter certificate and upload it to the KMS"
3672+
govc about.cert -show > vcenter-cert.pem
3673+
3674+
Options:
3675+
```
3676+
35853677
## library.checkin
35863678

35873679
```

govc/kms/add.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
Copyright (c) 2024-2024 VMware, Inc. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package kms
18+
19+
import (
20+
"context"
21+
"flag"
22+
23+
"github.com/vmware/govmomi/crypto"
24+
"github.com/vmware/govmomi/govc/cli"
25+
"github.com/vmware/govmomi/govc/flags"
26+
"github.com/vmware/govmomi/vim25/types"
27+
)
28+
29+
type add struct {
30+
*flags.ClientFlag
31+
32+
types.KmipServerSpec
33+
}
34+
35+
func init() {
36+
cli.Register("kms.add", &add{})
37+
}
38+
39+
func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
40+
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
41+
cmd.ClientFlag.Register(ctx, f)
42+
43+
f.StringVar(&cmd.Info.Name, "n", "", "Server name")
44+
f.StringVar(&cmd.Info.Address, "a", "", "Server address")
45+
cmd.Info.Port = 5696 // default
46+
f.Var(flags.NewInt32(&cmd.Info.Port), "p", "Server port")
47+
}
48+
49+
func (cmd *add) Usage() string {
50+
return "NAME"
51+
}
52+
53+
func (cmd *add) Description() string {
54+
return `Add KMS cluster.
55+
56+
Server name and address are required, port defaults to 5696.
57+
58+
Examples:
59+
govc kms.add -n my-server -a kms.example.com my-kp`
60+
}
61+
62+
func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
63+
id := f.Arg(0)
64+
if id == "" {
65+
return flag.ErrHelp
66+
}
67+
68+
c, err := cmd.Client()
69+
if err != nil {
70+
return err
71+
}
72+
73+
m, err := crypto.GetManagerKmip(c)
74+
if err != nil {
75+
return err
76+
}
77+
78+
spec := types.KmipServerSpec{
79+
ClusterId: types.KeyProviderId{Id: id},
80+
Info: cmd.Info,
81+
}
82+
83+
return m.RegisterKmipServer(ctx, spec)
84+
}

govc/kms/ls.go

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/*
2+
Copyright (c) 2024-2024 VMware, Inc. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package kms
18+
19+
import (
20+
"context"
21+
"flag"
22+
"fmt"
23+
"io"
24+
"os"
25+
"text/tabwriter"
26+
27+
"github.com/vmware/govmomi/crypto"
28+
"github.com/vmware/govmomi/govc/cli"
29+
"github.com/vmware/govmomi/govc/flags"
30+
"github.com/vmware/govmomi/vim25/types"
31+
)
32+
33+
type ls struct {
34+
*flags.ClientFlag
35+
*flags.OutputFlag
36+
}
37+
38+
func init() {
39+
cli.Register("kms.ls", &ls{})
40+
}
41+
42+
func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
43+
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
44+
cmd.ClientFlag.Register(ctx, f)
45+
46+
cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
47+
cmd.OutputFlag.Register(ctx, f)
48+
}
49+
50+
func (cmd *ls) Process(ctx context.Context) error {
51+
if err := cmd.ClientFlag.Process(ctx); err != nil {
52+
return err
53+
}
54+
return cmd.OutputFlag.Process(ctx)
55+
}
56+
57+
func (cmd *ls) Usage() string {
58+
return "NAME"
59+
}
60+
61+
func (cmd *ls) Description() string {
62+
return `Display KMS info.
63+
64+
Examples:
65+
govc kms.ls
66+
govc kms.ls -json
67+
govc kms.ls - # default provider
68+
govc kms.ls ProviderName
69+
govc kms.ls -json ProviderName`
70+
}
71+
72+
func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
73+
c, err := cmd.Client()
74+
if err != nil {
75+
return err
76+
}
77+
78+
m, err := crypto.GetManagerKmip(c)
79+
if err != nil {
80+
return err
81+
}
82+
83+
info, err := m.ListKmipServers(ctx, nil)
84+
if err != nil {
85+
return err
86+
}
87+
88+
id := f.Arg(0)
89+
90+
if id == "" {
91+
status, err := m.GetStatus(ctx, info...)
92+
if err != nil {
93+
return err
94+
}
95+
return cmd.WriteResult(&clusterResult{Info: info, Status: status})
96+
}
97+
98+
if id == "-" {
99+
for _, s := range info {
100+
if s.UseAsDefault {
101+
id = s.ClusterId.Id
102+
break
103+
}
104+
}
105+
}
106+
107+
status, err := m.GetClusterStatus(ctx, id)
108+
if err != nil {
109+
return err
110+
}
111+
112+
format := &serverResult{Status: status}
113+
114+
for _, s := range info {
115+
if s.ClusterId.Id == id {
116+
format.Info = s
117+
}
118+
}
119+
120+
return cmd.WriteResult(format)
121+
}
122+
123+
type serverResult struct {
124+
Info types.KmipClusterInfo `json:"info"`
125+
Status *types.CryptoManagerKmipClusterStatus `json:"status"`
126+
}
127+
128+
func (r *serverResult) status(name string) types.ManagedEntityStatus {
129+
for _, server := range r.Status.Servers {
130+
if server.Name == name {
131+
return server.Status
132+
}
133+
}
134+
return types.ManagedEntityStatusGray
135+
}
136+
137+
func (r *serverResult) Write(w io.Writer) error {
138+
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
139+
140+
if r.Info.ManagementType == string(types.KmipClusterInfoKmsManagementTypeNativeProvider) {
141+
boolVal := func(v *bool) bool {
142+
if v == nil {
143+
return false
144+
}
145+
return *v
146+
}
147+
148+
fmt.Fprintf(tw, "Key ID: %s\tHas Backup: %t\tTPM Required: %t\n",
149+
r.Info.KeyId, boolVal(r.Info.HasBackup), boolVal(r.Info.TpmRequired))
150+
} else {
151+
for _, s := range r.Info.Servers {
152+
status := r.status(s.Name)
153+
fmt.Fprintf(tw, "%s\t%s:%d\t%s\n", s.Name, s.Address, s.Port, status)
154+
}
155+
}
156+
157+
return tw.Flush()
158+
}
159+
160+
type clusterResult struct {
161+
Info []types.KmipClusterInfo `json:"info"`
162+
Status []types.CryptoManagerKmipClusterStatus `json:"status"`
163+
}
164+
165+
func (r *clusterResult) status(id types.KeyProviderId) types.ManagedEntityStatus {
166+
for _, status := range r.Status {
167+
if status.ClusterId == id {
168+
return status.OverallStatus
169+
}
170+
}
171+
return types.ManagedEntityStatusGray
172+
}
173+
174+
func kmsType(kind string) string {
175+
switch types.KmipClusterInfoKmsManagementType(kind) {
176+
case types.KmipClusterInfoKmsManagementTypeVCenter:
177+
return "Standard"
178+
case types.KmipClusterInfoKmsManagementTypeNativeProvider:
179+
return "Native"
180+
default:
181+
return kind
182+
}
183+
}
184+
185+
func (r *clusterResult) Write(w io.Writer) error {
186+
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)
187+
188+
for _, info := range r.Info {
189+
name := info.ClusterId.Id
190+
kind := kmsType(info.ManagementType)
191+
status := r.status(info.ClusterId)
192+
fmt.Fprintf(tw, "%s\t%s\t%s\n", name, kind, status)
193+
}
194+
195+
return tw.Flush()
196+
}

0 commit comments

Comments
 (0)