Skip to content

Commit

Permalink
govc: add kms commands
Browse files Browse the repository at this point in the history
  • Loading branch information
dougm committed Sep 19, 2024
1 parent 796892a commit ccf449e
Show file tree
Hide file tree
Showing 8 changed files with 701 additions and 0 deletions.
92 changes: 92 additions & 0 deletions govc/USAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,11 @@ but appear via `govc $cmd -h`:
- [import.ovf](#importovf)
- [import.spec](#importspec)
- [import.vmdk](#importvmdk)
- [kms.add](#kmsadd)
- [kms.default](#kmsdefault)
- [kms.ls](#kmsls)
- [kms.rm](#kmsrm)
- [kms.trust](#kmstrust)
- [library.checkin](#librarycheckin)
- [library.checkout](#librarycheckout)
- [library.clone](#libraryclone)
Expand Down Expand Up @@ -3582,6 +3587,93 @@ Options:
-pool= Resource pool [GOVC_RESOURCE_POOL]
```

## kms.add

```
Usage: govc kms.add [OPTIONS] NAME
Add KMS cluster.
Server name and address are required, port defaults to 5696.
Examples:
govc kms.add -n my-server -a kms.example.com my-kp
Options:
-a= Server address
-n= Server name
-p=5696 Server port
```

## kms.default

```
Usage: govc kms.default [OPTIONS] NAME
Set default KMS cluster.
Examples:
govc kms.default my-kp
govc kms.default - # clear default
govc kms.default -e /dc/host/cluster my-kp
govc kms.default -e /dc/host/cluster my-kp - # clear default
Options:
-e= Set entity default KMS cluster (cluster or host folder)
```

## kms.ls

```
Usage: govc kms.ls [OPTIONS] NAME
Display KMS info.
Examples:
govc kms.ls
govc kms.ls -json
govc kms.ls - # default provider
govc kms.ls ProviderName
govc kms.ls -json ProviderName
Options:
```

## kms.rm

```
Usage: govc kms.rm [OPTIONS] NAME
Remove KMS server or cluster.
Examples:
govc kms.rm my-kp
govc kms.rm -s my-server my-kp
Options:
-s= Server name
```

## kms.trust

```
Usage: govc kms.trust [OPTIONS] NAME
Establish trust between KMS and vCenter.
Examples:
# "Make vCenter Trust KMS"
govc kms.trust -server-cert "$(govc about.cert -show)" my-kp
# "Make KMS Trust vCenter" -> "KMS certificate and private key"
govc kms.trust -client-cert "$(cat crt.pem) -client-key "$(cat key.pem) my-kp
# "Download the vCenter certificate and upload it to the KMS"
govc about.cert -show > vcenter-cert.pem
Options:
```

## library.checkin

```
Expand Down
84 changes: 84 additions & 0 deletions govc/kms/add.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
Copyright (c) 2024-2024 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kms

import (
"context"
"flag"

"github.com/vmware/govmomi/crypto"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)

type add struct {
*flags.ClientFlag

types.KmipServerSpec
}

func init() {
cli.Register("kms.add", &add{})
}

func (cmd *add) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)

f.StringVar(&cmd.Info.Name, "n", "", "Server name")
f.StringVar(&cmd.Info.Address, "a", "", "Server address")
cmd.Info.Port = 5696 // default
f.Var(flags.NewInt32(&cmd.Info.Port), "p", "Server port")
}

func (cmd *add) Usage() string {
return "NAME"
}

func (cmd *add) Description() string {
return `Add KMS cluster.
Server name and address are required, port defaults to 5696.
Examples:
govc kms.add -n my-server -a kms.example.com my-kp`
}

func (cmd *add) Run(ctx context.Context, f *flag.FlagSet) error {
id := f.Arg(0)
if id == "" {
return flag.ErrHelp
}

c, err := cmd.Client()
if err != nil {
return err
}

m, err := crypto.GetManagerKmip(c)
if err != nil {
return err
}

spec := types.KmipServerSpec{
ClusterId: types.KeyProviderId{Id: id},
Info: cmd.Info,
}

return m.RegisterKmipServer(ctx, spec)
}
196 changes: 196 additions & 0 deletions govc/kms/ls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
/*
Copyright (c) 2024-2024 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package kms

import (
"context"
"flag"
"fmt"
"io"
"os"
"text/tabwriter"

"github.com/vmware/govmomi/crypto"
"github.com/vmware/govmomi/govc/cli"
"github.com/vmware/govmomi/govc/flags"
"github.com/vmware/govmomi/vim25/types"
)

type ls struct {
*flags.ClientFlag
*flags.OutputFlag
}

func init() {
cli.Register("kms.ls", &ls{})
}

func (cmd *ls) Register(ctx context.Context, f *flag.FlagSet) {
cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
cmd.ClientFlag.Register(ctx, f)

cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
cmd.OutputFlag.Register(ctx, f)
}

func (cmd *ls) Process(ctx context.Context) error {
if err := cmd.ClientFlag.Process(ctx); err != nil {
return err
}
return cmd.OutputFlag.Process(ctx)
}

func (cmd *ls) Usage() string {
return "NAME"
}

func (cmd *ls) Description() string {
return `Display KMS info.
Examples:
govc kms.ls
govc kms.ls -json
govc kms.ls - # default provider
govc kms.ls ProviderName
govc kms.ls -json ProviderName`
}

func (cmd *ls) Run(ctx context.Context, f *flag.FlagSet) error {
c, err := cmd.Client()
if err != nil {
return err
}

m, err := crypto.GetManagerKmip(c)
if err != nil {
return err
}

info, err := m.ListKmipServers(ctx, nil)
if err != nil {
return err
}

id := f.Arg(0)

if id == "" {
status, err := m.GetStatus(ctx, info...)
if err != nil {
return err
}
return cmd.WriteResult(&clusterResult{Info: info, Status: status})
}

if id == "-" {
for _, s := range info {
if s.UseAsDefault {
id = s.ClusterId.Id
break
}
}
}

status, err := m.GetClusterStatus(ctx, id)
if err != nil {
return err
}

format := &serverResult{Status: status}

for _, s := range info {
if s.ClusterId.Id == id {
format.Info = s
}
}

return cmd.WriteResult(format)
}

type serverResult struct {
Info types.KmipClusterInfo `json:"info"`
Status *types.CryptoManagerKmipClusterStatus `json:"status"`
}

func (r *serverResult) status(name string) types.ManagedEntityStatus {
for _, server := range r.Status.Servers {
if server.Name == name {
return server.Status
}
}
return types.ManagedEntityStatusGray
}

func (r *serverResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)

if r.Info.ManagementType == string(types.KmipClusterInfoKmsManagementTypeNativeProvider) {
boolVal := func(v *bool) bool {
if v == nil {
return false
}
return *v
}

fmt.Fprintf(tw, "Key ID: %s\tHas Backup: %t\tTPM Required: %t\n",
r.Info.KeyId, boolVal(r.Info.HasBackup), boolVal(r.Info.TpmRequired))
} else {
for _, s := range r.Info.Servers {
status := r.status(s.Name)
fmt.Fprintf(tw, "%s\t%s:%d\t%s\n", s.Name, s.Address, s.Port, status)
}
}

return tw.Flush()
}

type clusterResult struct {
Info []types.KmipClusterInfo `json:"info"`
Status []types.CryptoManagerKmipClusterStatus `json:"status"`
}

func (r *clusterResult) status(id types.KeyProviderId) types.ManagedEntityStatus {
for _, status := range r.Status {
if status.ClusterId == id {
return status.OverallStatus
}
}
return types.ManagedEntityStatusGray
}

func kmsType(kind string) string {
switch types.KmipClusterInfoKmsManagementType(kind) {
case types.KmipClusterInfoKmsManagementTypeVCenter:
return "Standard"
case types.KmipClusterInfoKmsManagementTypeNativeProvider:
return "Native"
default:
return kind
}
}

func (r *clusterResult) Write(w io.Writer) error {
tw := tabwriter.NewWriter(os.Stdout, 2, 0, 2, ' ', 0)

for _, info := range r.Info {
name := info.ClusterId.Id
kind := kmsType(info.ManagementType)
status := r.status(info.ClusterId)
fmt.Fprintf(tw, "%s\t%s\t%s\n", name, kind, status)
}

return tw.Flush()
}
Loading

0 comments on commit ccf449e

Please sign in to comment.