github.com/vmware/govmomi@v0.37.1/govc/extension/setcert.go (about) 1 /* 2 Copyright (c) 2015 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 extension 18 19 import ( 20 "bytes" 21 "context" 22 "crypto/rand" 23 "crypto/rsa" 24 "crypto/x509" 25 "crypto/x509/pkix" 26 "encoding/pem" 27 "flag" 28 "fmt" 29 "io" 30 "math/big" 31 "os" 32 "strings" 33 "time" 34 35 "github.com/vmware/govmomi/govc/cli" 36 "github.com/vmware/govmomi/govc/flags" 37 "github.com/vmware/govmomi/object" 38 ) 39 40 type setcert struct { 41 *flags.ClientFlag 42 43 cert string 44 org string 45 46 encodedCert bytes.Buffer 47 } 48 49 func init() { 50 cli.Register("extension.setcert", &setcert{}) 51 } 52 53 func (cmd *setcert) Register(ctx context.Context, f *flag.FlagSet) { 54 cmd.ClientFlag, ctx = flags.NewClientFlag(ctx) 55 cmd.ClientFlag.Register(ctx, f) 56 57 f.StringVar(&cmd.cert, "cert-pem", "-", "PEM encoded certificate") 58 f.StringVar(&cmd.org, "org", "VMware", "Organization for generated certificate") 59 } 60 61 func (cmd *setcert) Process(ctx context.Context) error { 62 if err := cmd.ClientFlag.Process(ctx); err != nil { 63 return err 64 } 65 return nil 66 } 67 68 func (cmd *setcert) Usage() string { 69 return "ID" 70 } 71 72 func (cmd *setcert) Description() string { 73 return `Set certificate for the extension ID. 74 75 The '-cert-pem' option can be one of the following: 76 '-' : Read the certificate from stdin 77 '+' : Generate a new key pair and save locally to ID.crt and ID.key 78 ... : Any other value is passed as-is to ExtensionManager.SetCertificate 79 80 Examples: 81 govc extension.setcert -cert-pem + -org Example com.example.extname` 82 } 83 84 func (cmd *setcert) create(id string) error { 85 certFile, err := os.Create(id + ".crt") 86 if err != nil { 87 return err 88 } 89 defer certFile.Close() 90 91 keyFile, err := os.Create(id + ".key") 92 if err != nil { 93 return err 94 } 95 defer keyFile.Close() 96 97 priv, err := rsa.GenerateKey(rand.Reader, 2048) 98 if err != nil { 99 return err 100 } 101 102 notBefore := time.Now() 103 notAfter := notBefore.Add(5 * 365 * 24 * time.Hour) // 5 years 104 105 serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) 106 serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) 107 if err != nil { 108 return err 109 } 110 111 template := x509.Certificate{ 112 SerialNumber: serialNumber, 113 Subject: pkix.Name{ 114 Organization: []string{cmd.org}, 115 }, 116 NotBefore: notBefore, 117 NotAfter: notAfter, 118 KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, 119 BasicConstraintsValid: true, 120 } 121 122 derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) 123 if err != nil { 124 return err 125 } 126 127 err = pem.Encode(&cmd.encodedCert, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) 128 if err != nil { 129 return err 130 } 131 132 _, err = certFile.Write(cmd.encodedCert.Bytes()) 133 if err != nil { 134 return err 135 } 136 137 err = pem.Encode(keyFile, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) 138 if err != nil { 139 return err 140 } 141 142 return nil 143 } 144 145 func (cmd *setcert) Run(ctx context.Context, f *flag.FlagSet) error { 146 if f.NArg() != 1 { 147 return flag.ErrHelp 148 } 149 150 key := f.Arg(0) 151 152 if cmd.cert == "-" { 153 b, err := io.ReadAll(os.Stdin) 154 if err != nil { 155 return err 156 } 157 cmd.cert = string(b) 158 } else if strings.HasPrefix(cmd.cert, "+") { 159 if err := cmd.create(key); err != nil { 160 return fmt.Errorf("creating certificate: %s", err) 161 } 162 if cmd.cert == "++" { 163 return nil // just generate a cert, useful for testing 164 } 165 cmd.cert = cmd.encodedCert.String() 166 } 167 168 c, err := cmd.Client() 169 if err != nil { 170 return err 171 } 172 173 m, err := object.GetExtensionManager(c) 174 if err != nil { 175 return err 176 } 177 178 return m.SetCertificate(ctx, key, cmd.cert) 179 }