github.com/vmware/govmomi@v0.51.0/cli/about/cert.go (about)

     1  // © Broadcom. All Rights Reserved.
     2  // The term “Broadcom” refers to Broadcom Inc. and/or its subsidiaries.
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package about
     6  
     7  import (
     8  	"context"
     9  	"encoding/pem"
    10  	"flag"
    11  	"fmt"
    12  	"io"
    13  	"net/http"
    14  	"os"
    15  
    16  	"github.com/vmware/govmomi/cli"
    17  	"github.com/vmware/govmomi/cli/flags"
    18  	"github.com/vmware/govmomi/object"
    19  	"github.com/vmware/govmomi/vim25/soap"
    20  )
    21  
    22  type cert struct {
    23  	*flags.ClientFlag
    24  	*flags.OutputFlag
    25  
    26  	show       bool
    27  	thumbprint bool
    28  }
    29  
    30  func init() {
    31  	cli.Register("about.cert", &cert{})
    32  }
    33  
    34  func (cmd *cert) Register(ctx context.Context, f *flag.FlagSet) {
    35  	cmd.ClientFlag, ctx = flags.NewClientFlag(ctx)
    36  	cmd.ClientFlag.Register(ctx, f)
    37  
    38  	cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx)
    39  	cmd.OutputFlag.Register(ctx, f)
    40  
    41  	f.BoolVar(&cmd.show, "show", false, "Show PEM encoded server certificate only")
    42  	f.BoolVar(&cmd.thumbprint, "thumbprint", false, "Output host hash and thumbprint only")
    43  }
    44  
    45  func (cmd *cert) Description() string {
    46  	return `Display TLS certificate info for HOST.
    47  
    48  If the HOST certificate cannot be verified, about.cert will return with exit code 60 (as curl does).
    49  If the '-k' flag is provided, about.cert will return with exit code 0 in this case.
    50  The SHA1 thumbprint can also be used as '-thumbprint' for the 'host.add' and 'cluster.add' commands.
    51  
    52  Examples:
    53    govc about.cert -k -json | jq -r .thumbprintSHA1
    54    govc about.cert -k -show | sudo tee /usr/local/share/ca-certificates/host.crt
    55    govc about.cert -k -thumbprint | tee -a ~/.govmomi/known_hosts`
    56  }
    57  
    58  func (cmd *cert) Process(ctx context.Context) error {
    59  	if err := cmd.ClientFlag.Process(ctx); err != nil {
    60  		return err
    61  	}
    62  	if err := cmd.OutputFlag.Process(ctx); err != nil {
    63  		return err
    64  	}
    65  	return nil
    66  }
    67  
    68  type certResult struct {
    69  	cmd  *cert
    70  	info object.HostCertificateInfo
    71  }
    72  
    73  func (r *certResult) Write(w io.Writer) error {
    74  	if r.cmd.show {
    75  		return pem.Encode(w, &pem.Block{Type: "CERTIFICATE", Bytes: r.info.Certificate.Raw})
    76  	}
    77  
    78  	if r.cmd.thumbprint {
    79  		u := r.cmd.Session.URL
    80  		_, err := fmt.Fprintf(w, "%s %s\n", u.Host, r.info.ThumbprintSHA256)
    81  		return err
    82  	}
    83  
    84  	return r.cmd.WriteResult(&r.info)
    85  }
    86  
    87  func (cmd *cert) Run(ctx context.Context, f *flag.FlagSet) error {
    88  	u := cmd.Session.URL
    89  	c := soap.NewClient(u, false)
    90  	t := c.Client.Transport.(*http.Transport)
    91  	r := certResult{cmd: cmd}
    92  
    93  	if err := cmd.SetRootCAs(c); err != nil {
    94  		return err
    95  	}
    96  
    97  	if err := r.info.FromURL(u, t.TLSClientConfig); err != nil {
    98  		return err
    99  	}
   100  
   101  	if r.info.Err != nil && !r.cmd.Session.Insecure {
   102  		cmd.Out = os.Stderr
   103  		// using same exit code as curl:
   104  		defer os.Exit(60)
   105  	}
   106  
   107  	return r.Write(cmd.Out)
   108  }