github.com/vmware/govmomi@v0.37.2/govc/about/cert.go (about)

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