blob: b3fe333efd8b24f199fee792778d6aa8a8d08b60 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You 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 cmd
import (
"fmt"
"os"
)
import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
import (
dubbo_cmd "github.com/apache/dubbo-kubernetes/pkg/core/cmd"
"github.com/apache/dubbo-kubernetes/pkg/tls"
)
var NewSelfSignedCert = tls.NewSelfSignedCert
type generateCertificateContext struct {
args struct {
key string
cert string
certType string
keyType string
hostnames []string
}
}
func NewGenerateCertificateCmd(baseCmd *cobra.Command) {
ctx := &generateCertificateContext{}
cmd := &cobra.Command{
Use: "tls-certificate",
Short: "Generate a TLS certificate",
Long: `Generate self signed key and certificate pair that can be used for example in Dataplane Token Server setup.`,
Example: `
# Generate a TLS certificate for use by an HTTPS server, i.e. by the Dataplane Token server, Webhook Server
dubboctl generate tls-certificate --type=server --hostname=localhost
# Generate a TLS certificate for use by a client of an HTTPS server, i.e. by the 'dubboctl generate dataplane-token' command
dubboctl generate tls-certificate --type=client --hostname=dataplane-1`,
RunE: func(cmd *cobra.Command, args []string) error {
certType := tls.CertType(ctx.args.certType)
switch certType {
case tls.ClientCertType, tls.ServerCertType:
if len(ctx.args.hostnames) == 0 {
return errors.New("at least one hostname must be given")
}
default:
return errors.Errorf("invalid certificate type %q", certType)
}
keyType := tls.DefaultKeyType
switch ctx.args.keyType {
case "":
case "rsa":
keyType = tls.RSAKeyType
case "ecdsa":
keyType = tls.ECDSAKeyType
default:
return errors.Errorf("invalid key type %q", ctx.args.keyType)
}
keyPair, err := NewSelfSignedCert(certType, keyType, ctx.args.hostnames...)
if err != nil {
return errors.Wrap(err, "could not generate certificate")
}
if ctx.args.key == "-" {
_, err = cmd.OutOrStdout().Write(keyPair.KeyPEM)
} else {
err = os.WriteFile(ctx.args.key, keyPair.KeyPEM, 0o400)
}
if err != nil {
return errors.Wrap(err, "could not write the key file")
}
if ctx.args.cert == "-" {
_, err = cmd.OutOrStdout().Write(keyPair.CertPEM)
} else {
err = os.WriteFile(ctx.args.cert, keyPair.CertPEM, 0o600)
}
if err != nil {
return errors.Wrap(err, "could not write the cert file")
}
if ctx.args.cert != "-" && ctx.args.key != "-" {
fmt.Fprintf(cmd.OutOrStdout(), "Private key saved in %s\n", ctx.args.key)
fmt.Fprintf(cmd.OutOrStdout(), "Certificate saved in %s\n", ctx.args.cert)
}
return nil
},
}
cmd.Flags().StringVar(&ctx.args.key, "key-file", "key.pem", "path to a file with a generated private key ('-' for stdout)")
cmd.Flags().StringVar(&ctx.args.cert, "cert-file", "cert.pem", "path to a file with a generated TLS certificate ('-' for stdout)")
cmd.Flags().StringVar(&ctx.args.certType, "type", "", dubbo_cmd.UsageOptions("type of the certificate", "client", "server"))
cmd.Flags().StringVar(&ctx.args.keyType, "key-type", "", dubbo_cmd.UsageOptions("type of the private key", "rsa", "ecdsa"))
cmd.Flags().StringSliceVar(&ctx.args.hostnames, "hostname", []string{}, "DNS hostname(s) to issue the certificate for")
_ = cmd.MarkFlagRequired("type")
_ = cmd.MarkFlagRequired("hostname")
baseCmd.AddCommand(cmd)
}