Support creating new service-account keypairs

This commit is contained in:
John Gardiner Myers 2021-06-20 14:09:24 -07:00
parent bf5176e1bf
commit 3ca8b95005
6 changed files with 69 additions and 98 deletions

1
cmd/kops/BUILD.bazel generated
View File

@ -8,7 +8,6 @@ go_library(
"create_cluster.go",
"create_ig.go",
"create_keypair.go",
"create_keypair_ca.go",
"create_secret.go",
"create_secret_cilium_encryptionconfig.go",
"create_secret_dockerconfig.go",

View File

@ -37,47 +37,61 @@ import (
)
var (
createKeypairCaLong = templates.LongDesc(i18n.T(`
Add a cluster CA certificate and private key.
createKeypairLong = templates.LongDesc(i18n.T(`
Add a CA certificate and private key to a keyset.
`))
createKeypairCaExample = templates.Examples(i18n.T(`
Add a cluster CA certificate and private key.
createKeypairExample = templates.Examples(i18n.T(`
Add a CA certificate and private key to a keyset.
kops create keypair ca \
--cert ~/ca.pem --key ~/ca-key.pem \
--name k8s-cluster.example.com --state s3://my-state-store
`))
createKeypairCaShort = i18n.T(`Add a cluster CA cert and key`)
createKeypairShort = i18n.T(`Add a CA certificate and private key to a keyset.`)
)
type CreateKeypairCaOptions struct {
type CreateKeypairOptions struct {
ClusterName string
Keyset string
PrivateKeyPath string
CertPath string
Primary bool
}
// NewCmdCreateKeypairCa returns create ca certificate command
func NewCmdCreateKeypairCa(f *util.Factory, out io.Writer) *cobra.Command {
options := &CreateKeypairCaOptions{}
var keysetCommonNames = map[string]string{
"ca": "kubernetes",
"service-account": "service-account",
}
// NewCmdCreateKeypair returns a create keypair command.
func NewCmdCreateKeypair(f *util.Factory, out io.Writer) *cobra.Command {
options := &CreateKeypairOptions{}
cmd := &cobra.Command{
Use: "ca",
Short: createKeypairCaShort,
Long: createKeypairCaLong,
Example: createKeypairCaExample,
Use: "keypair KEYSET",
Short: createKeypairShort,
Long: createKeypairLong,
Example: createKeypairExample,
Run: func(cmd *cobra.Command, args []string) {
ctx := context.TODO()
err := rootCommand.ProcessArgs(args)
if err != nil {
exitWithError(err)
}
options.ClusterName = rootCommand.ClusterName()
err = RunCreateKeypairCa(ctx, f, out, options)
if options.ClusterName == "" {
exitWithError(fmt.Errorf("--name is required"))
return
}
if len(args) == 0 {
exitWithError(fmt.Errorf("must specify name of keyset to add keypair to"))
}
if len(args) != 1 {
exitWithError(fmt.Errorf("can only add to one keyset at a time"))
}
options.Keyset = args[0]
err := RunCreateKeypair(ctx, f, out, options)
if err != nil {
exitWithError(err)
}
@ -86,13 +100,18 @@ func NewCmdCreateKeypairCa(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&options.CertPath, "cert", options.CertPath, "Path to CA certificate")
cmd.Flags().StringVar(&options.PrivateKeyPath, "key", options.PrivateKeyPath, "Path to CA private key")
cmd.Flags().BoolVar(&options.Primary, "primary", options.Primary, "Make the CA used to issue certificates")
cmd.Flags().BoolVar(&options.Primary, "primary", options.Primary, "Make the keypair the one used to issue certificates")
return cmd
}
// RunCreateKeypairCa adds a custom ca certificate and private key
func RunCreateKeypairCa(ctx context.Context, f *util.Factory, out io.Writer, options *CreateKeypairCaOptions) error {
// RunCreateKeypair adds a custom CA certificate and private key.
func RunCreateKeypair(ctx context.Context, f *util.Factory, out io.Writer, options *CreateKeypairOptions) error {
commonName := keysetCommonNames[options.Keyset]
if commonName == "" {
return fmt.Errorf("adding keypair to %q is not supported", options.Keyset)
}
cluster, err := GetCluster(ctx, f, options.ClusterName)
if err != nil {
return fmt.Errorf("error getting cluster: %q: %v", options.ClusterName, err)
@ -133,7 +152,7 @@ func RunCreateKeypairCa(ctx context.Context, f *util.Factory, out io.Writer, opt
req := pki.IssueCertRequest{
Type: "ca",
Subject: pkix.Name{CommonName: "cn=kubernetes"},
Subject: pkix.Name{CommonName: "cn=" + commonName},
Serial: pki.BuildPKISerial(time.Now().UnixNano()),
PrivateKey: privateKey,
}
@ -154,7 +173,7 @@ func RunCreateKeypairCa(ctx context.Context, f *util.Factory, out io.Writer, opt
}
}
keyset, err := keyStore.FindKeyset(fi.CertificateIDCA)
keyset, err := keyStore.FindKeyset(options.Keyset)
if os.IsNotExist(err) || (err == nil && keyset == nil) {
keyset = &fi.Keyset{
Items: map[string]*fi.KeysetItem{},
@ -168,7 +187,7 @@ func RunCreateKeypairCa(ctx context.Context, f *util.Factory, out io.Writer, opt
return err
}
err = keyStore.StoreKeyset(fi.CertificateIDCA, keyset)
err = keyStore.StoreKeyset(options.Keyset, keyset)
if err != nil {
return fmt.Errorf("error storing user provided keys %q %q: %v", options.CertPath, options.PrivateKeyPath, err)
}

View File

@ -41,6 +41,7 @@ import (
"k8s.io/kops/pkg/jsonutils"
"k8s.io/kops/pkg/testutils"
"k8s.io/kops/pkg/testutils/golden"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
@ -475,25 +476,27 @@ func (i *integrationTest) runTest(t *testing.T, h *testutils.IntegrationTestHarn
}
{
options := &CreateKeypairCaOptions{}
options := &CreateKeypairOptions{}
options.ClusterName = i.clusterName
options.Keyset = fi.CertificateIDCA
options.PrivateKeyPath = path.Join(i.srcDir, "../ca.key")
options.CertPath = path.Join(i.srcDir, "../ca.crt")
options.Primary = true
err := RunCreateKeypairCa(ctx, factory, &stdout, options)
err := RunCreateKeypair(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running %q create CA keypair: %v", inputYAML, err)
}
}
{
options := &CreateKeypairCaOptions{}
options := &CreateKeypairOptions{}
options.ClusterName = i.clusterName
options.Keyset = fi.CertificateIDCA
options.PrivateKeyPath = path.Join(i.srcDir, "../ca-next.key")
options.CertPath = path.Join(i.srcDir, "../ca-next.crt")
options.Primary = false
err := RunCreateKeypairCa(ctx, factory, &stdout, options)
err := RunCreateKeypair(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running %q create next CA keypair: %v", inputYAML, err)
}
@ -760,25 +763,27 @@ func (i *integrationTest) runTestCloudformation(t *testing.T) {
}
{
options := &CreateKeypairCaOptions{}
options := &CreateKeypairOptions{}
options.ClusterName = i.clusterName
options.Keyset = fi.CertificateIDCA
options.PrivateKeyPath = path.Join(i.srcDir, "../ca.key")
options.CertPath = path.Join(i.srcDir, "../ca.crt")
options.Primary = true
err := RunCreateKeypairCa(ctx, factory, &stdout, options)
err := RunCreateKeypair(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running %q create CA keypair: %v", inputYAML, err)
}
}
{
options := &CreateKeypairCaOptions{}
options := &CreateKeypairOptions{}
options.ClusterName = i.clusterName
options.Keyset = fi.CertificateIDCA
options.PrivateKeyPath = path.Join(i.srcDir, "../ca-next.key")
options.CertPath = path.Join(i.srcDir, "../ca-next.crt")
options.Primary = false
err := RunCreateKeypairCa(ctx, factory, &stdout, options)
err := RunCreateKeypair(ctx, factory, &stdout, options)
if err != nil {
t.Fatalf("error running %q create next CA keypair: %v", inputYAML, err)
}

View File

@ -79,6 +79,6 @@ kops create -f FILENAME [flags]
* [kops](kops.md) - kOps is Kubernetes Operations.
* [kops create cluster](kops_create_cluster.md) - Create a Kubernetes cluster.
* [kops create instancegroup](kops_create_instancegroup.md) - Create an instancegroup.
* [kops create keypair](kops_create_keypair.md) - Create a keypair.
* [kops create keypair](kops_create_keypair.md) - Add a CA certificate and private key to a keyset.
* [kops create secret](kops_create_secret.md) - Create a secret.

View File

@ -3,16 +3,20 @@
## kops create keypair
Create a keypair.
Add a CA certificate and private key to a keyset.
### Synopsis
Create a keypair
Add a CA certificate and private key to a keyset.
```
kops create keypair KEYSET [flags]
```
### Examples
```
Add a cluster CA certificate and private key.
Add a CA certificate and private key to a keyset.
kops create keypair ca \
--cert ~/ca.pem --key ~/ca-key.pem \
--name k8s-cluster.example.com --state s3://my-state-store
@ -21,7 +25,10 @@ Create a keypair
### Options
```
-h, --help help for keypair
--cert string Path to CA certificate
-h, --help help for keypair
--key string Path to CA private key
--primary Make the keypair the one used to issue certificates
```
### Options inherited from parent commands
@ -48,5 +55,4 @@ Create a keypair
### SEE ALSO
* [kops create](kops_create.md) - Create a resource by command line, filename or stdin.
* [kops create keypair ca](kops_create_keypair_ca.md) - Add a cluster CA cert and key

View File

@ -1,58 +0,0 @@
<!--- This file is automatically generated by make gen-cli-docs; changes should be made in the go CLI command code (under cmd/kops) -->
## kops create keypair ca
Add a cluster CA cert and key
### Synopsis
Add a cluster CA certificate and private key.
```
kops create keypair ca [flags]
```
### Examples
```
Add a cluster CA certificate and private key.
kops create keypair ca \
--cert ~/ca.pem --key ~/ca-key.pem \
--name k8s-cluster.example.com --state s3://my-state-store
```
### Options
```
--cert string Path to CA certificate
-h, --help help for ca
--key string Path to CA private key
--primary Make the CA used to issue certificates
```
### Options inherited from parent commands
```
--add_dir_header If true, adds the file directory to the header of the log messages
--alsologtostderr log to standard error as well as files
--config string yaml config file (default is $HOME/.kops.yaml)
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
--log_dir string If non-empty, write log files in this directory
--log_file string If non-empty, use this log file
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
--logtostderr log to standard error instead of files (default true)
--name string Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level)
--skip_headers If true, avoid header prefixes in the log messages
--skip_log_headers If true, avoid headers when opening log files
--state string Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
-v, --v Level number for the log level verbosity
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
```
### SEE ALSO
* [kops create keypair](kops_create_keypair.md) - Create a keypair.