feat: gen secrets from kubernetes pki dir
This PR allows the ability to generate `secrets.yaml` (`talosctl gen secrets`) using a Kubernetes PKI directory path (e.g. `/etc/kubernetes/pki`) as input. Also introduces the flag `--kubernetes-bootstrap-token` to be able to set a static Kubernetes bootstrap token to the generated `secrets.yaml` file instead of a randomly-generated one. Closes siderolabs/talos#5894. Signed-off-by: Utku Ozdemir <utku.ozdemir@siderolabs.com>
This commit is contained in:
parent
a1d7b535ad
commit
a75fe7600d
@ -16,8 +16,10 @@ import (
|
||||
)
|
||||
|
||||
var genSecretsCmdFlags struct {
|
||||
outputFile string
|
||||
talosVersion string
|
||||
outputFile string
|
||||
talosVersion string
|
||||
fromKubernetesPki string
|
||||
kubernetesBootstrapToken string
|
||||
}
|
||||
|
||||
// genSecretsCmd represents the `gen secrets` command.
|
||||
@ -27,18 +29,32 @@ var genSecretsCmd = &cobra.Command{
|
||||
Long: ``,
|
||||
Args: cobra.NoArgs,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
genOptions := make([]generate.GenOption, 0, 1)
|
||||
var (
|
||||
secretsBundle *generate.SecretsBundle
|
||||
versionContract *config.VersionContract
|
||||
err error
|
||||
)
|
||||
|
||||
if genSecretsCmdFlags.talosVersion != "" {
|
||||
versionContract, err := config.ParseContractFromVersion(genSecretsCmdFlags.talosVersion)
|
||||
versionContract, err = config.ParseContractFromVersion(genSecretsCmdFlags.talosVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid talos-version: %w", err)
|
||||
}
|
||||
|
||||
genOptions = append(genOptions, generate.WithVersionContract(versionContract))
|
||||
}
|
||||
|
||||
secretsBundle, err := generate.NewSecretsBundle(generate.NewClock(), genOptions...)
|
||||
if genSecretsCmdFlags.fromKubernetesPki != "" {
|
||||
secretsBundle, err = generate.NewSecretsBundleFromKubernetesPKI(genSecretsCmdFlags.fromKubernetesPki,
|
||||
genSecretsCmdFlags.kubernetesBootstrapToken, versionContract)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create secrets bundle: %w", err)
|
||||
}
|
||||
|
||||
return writeSecretsBundleToFile(secretsBundle)
|
||||
}
|
||||
|
||||
secretsBundle, err = generate.NewSecretsBundle(generate.NewClock(),
|
||||
generate.WithVersionContract(versionContract),
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create secrets bundle: %w", err)
|
||||
}
|
||||
@ -59,6 +75,8 @@ func writeSecretsBundleToFile(bundle *generate.SecretsBundle) error {
|
||||
func init() {
|
||||
genSecretsCmd.Flags().StringVarP(&genSecretsCmdFlags.outputFile, "output-file", "o", "secrets.yaml", "path of the output file")
|
||||
genSecretsCmd.Flags().StringVar(&genSecretsCmdFlags.talosVersion, "talos-version", "", "the desired Talos version to generate secrets bundle for (backwards compatibility, e.g. v0.8)")
|
||||
genSecretsCmd.Flags().StringVarP(&genSecretsCmdFlags.fromKubernetesPki, "from-kubernetes-pki", "p", "", "use a Kubernetes PKI directory (e.g. /etc/kubernetes/pki) as input")
|
||||
genSecretsCmd.Flags().StringVarP(&genSecretsCmdFlags.kubernetesBootstrapToken, "kubernetes-bootstrap-token", "t", "", "use the provided bootstrap token as input")
|
||||
|
||||
Cmd.AddCommand(genSecretsCmd)
|
||||
}
|
||||
|
@ -79,6 +79,23 @@ machine:
|
||||
```
|
||||
|
||||
Patch format is detected automatically.
|
||||
"""
|
||||
|
||||
[notes.gen-secrets-from-pki]
|
||||
title = "Generating Talos secrets from PKI directory"
|
||||
description="""\
|
||||
It is now possible to generate a secrets bundle from a Kubernetes PKI directory (e.g. `/etc/kubernetes/pki`).
|
||||
|
||||
You can also specify a bootstrap token to be used in the secrets bundle.
|
||||
|
||||
This secrets bundle can then be used to generate a machine config.
|
||||
|
||||
This facilitates migrating clusters (e.g. created using `kubeadm`) to Talos.
|
||||
|
||||
```
|
||||
talosctl gen secrets --kubernetes-bootstrap-token znzio1.1ifu15frz7jd59pv --from-kubernetes-pki /etc/kubernetes/pki
|
||||
talosctl gen config --with-secrets secrets.yaml my-cluster https://172.20.0.1:6443
|
||||
```
|
||||
"""
|
||||
|
||||
[make_deps]
|
||||
|
@ -9,7 +9,6 @@ package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
@ -209,11 +208,56 @@ func (suite *GenSuite) TestSecrets() {
|
||||
suite.RunCLI([]string{"gen", "secrets"}, base.StdoutEmpty())
|
||||
suite.Assert().FileExists("secrets.yaml")
|
||||
|
||||
defer os.Remove("secrets.yaml") // nolint:errcheck
|
||||
|
||||
suite.RunCLI([]string{"gen", "secrets", "--output-file", "/tmp/secrets2.yaml"}, base.StdoutEmpty())
|
||||
suite.Assert().FileExists("/tmp/secrets2.yaml")
|
||||
|
||||
defer os.Remove("/tmp/secrets2.yaml") // nolint:errcheck
|
||||
|
||||
suite.RunCLI([]string{"gen", "secrets", "-o", "secrets3.yaml", "--talos-version", "v0.8"}, base.StdoutEmpty())
|
||||
suite.Assert().FileExists("secrets3.yaml")
|
||||
|
||||
defer os.Remove("secrets3.yaml") // nolint:errcheck
|
||||
}
|
||||
|
||||
// TestSecretsWithPKIDirAndToken ...
|
||||
func (suite *GenSuite) TestSecretsWithPKIDirAndToken() {
|
||||
path := "/tmp/secrets-with-pki-dir-and-token.yaml"
|
||||
|
||||
tempDir := suite.T().TempDir()
|
||||
|
||||
dir, err := writeKubernetesPKIFiles(tempDir)
|
||||
suite.Assert().NoError(err)
|
||||
|
||||
defer os.RemoveAll(dir) //nolint:errcheck
|
||||
|
||||
suite.RunCLI([]string{
|
||||
"gen", "secrets", "--from-kubernetes-pki", dir,
|
||||
"--kubernetes-bootstrap-token", "test-token",
|
||||
"--output-file", path,
|
||||
}, base.StdoutEmpty())
|
||||
|
||||
suite.Assert().FileExists(path)
|
||||
|
||||
defer os.Remove(path) //nolint:errcheck
|
||||
|
||||
secretsYaml, err := os.ReadFile(path)
|
||||
suite.Assert().NoError(err)
|
||||
|
||||
var secrets generate.SecretsBundle
|
||||
|
||||
err = yaml.Unmarshal(secretsYaml, &secrets)
|
||||
suite.Assert().NoError(err)
|
||||
|
||||
suite.Assert().Equal("test-token", secrets.Secrets.BootstrapToken, "bootstrap token does not match")
|
||||
suite.Assert().Equal(pkiCACrt, secrets.Certs.K8s.Crt, "k8s ca cert does not match")
|
||||
suite.Assert().Equal(pkiCAKey, secrets.Certs.K8s.Key, "k8s ca key does not match")
|
||||
suite.Assert().Equal(pkiFrontProxyCACrt, secrets.Certs.K8sAggregator.Crt, "k8s aggregator ca cert does not match")
|
||||
suite.Assert().Equal(pkiFrontProxyCAKey, secrets.Certs.K8sAggregator.Key, "k8s aggregator ca key does not match")
|
||||
suite.Assert().Equal(pkiSAKey, secrets.Certs.K8sServiceAccount.Key, "k8s service account key does not match")
|
||||
suite.Assert().Equal(pkiEtcdCACrt, secrets.Certs.Etcd.Crt, "etcd ca cert does not match")
|
||||
suite.Assert().Equal(pkiEtcdCAKey, secrets.Certs.Etcd.Key, "etcd ca key does not match")
|
||||
}
|
||||
|
||||
// TestConfigWithSecrets tests the gen config command with secrets provided.
|
||||
@ -221,7 +265,7 @@ func (suite *GenSuite) TestConfigWithSecrets() {
|
||||
suite.RunCLI([]string{"gen", "secrets"}, base.StdoutEmpty())
|
||||
suite.Assert().FileExists("secrets.yaml")
|
||||
|
||||
secretsYaml, err := ioutil.ReadFile("secrets.yaml")
|
||||
secretsYaml, err := os.ReadFile("secrets.yaml")
|
||||
suite.Assert().NoError(err)
|
||||
|
||||
suite.RunCLI([]string{"gen", "config", "foo", "https://192.168.0.1:6443", "--with-secrets", "secrets.yaml"})
|
||||
|
67
internal/integration/cli/pki.go
Normal file
67
internal/integration/cli/pki.go
Normal file
@ -0,0 +1,67 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package cli
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed "testdata/pki/ca.crt"
|
||||
pkiCACrt []byte
|
||||
//go:embed "testdata/pki/ca.key"
|
||||
pkiCAKey []byte
|
||||
//go:embed "testdata/pki/front-proxy-ca.crt"
|
||||
pkiFrontProxyCACrt []byte
|
||||
//go:embed "testdata/pki/front-proxy-ca.key"
|
||||
pkiFrontProxyCAKey []byte
|
||||
//go:embed "testdata/pki/sa.key"
|
||||
pkiSAKey []byte
|
||||
//go:embed "testdata/pki/etcd/ca.crt"
|
||||
pkiEtcdCACrt []byte
|
||||
//go:embed "testdata/pki/etcd/ca.key"
|
||||
pkiEtcdCAKey []byte
|
||||
)
|
||||
|
||||
func writeKubernetesPKIFiles(dir string) (string, error) {
|
||||
var err error
|
||||
|
||||
if err = os.WriteFile(filepath.Join(dir, "ca.crt"), pkiCACrt, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = os.WriteFile(filepath.Join(dir, "ca.key"), pkiCAKey, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = os.WriteFile(filepath.Join(dir, "front-proxy-ca.crt"), pkiFrontProxyCACrt, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = os.WriteFile(filepath.Join(dir, "front-proxy-ca.key"), pkiFrontProxyCAKey, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = os.WriteFile(filepath.Join(dir, "sa.key"), pkiSAKey, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
etcdDir := filepath.Join(dir, "etcd")
|
||||
if err = os.Mkdir(etcdDir, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = os.WriteFile(filepath.Join(etcdDir, "ca.crt"), pkiEtcdCACrt, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = os.WriteFile(filepath.Join(etcdDir, "ca.key"), pkiEtcdCAKey, 0o777); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return dir, nil
|
||||
}
|
19
internal/integration/cli/testdata/pki/ca.crt
vendored
Normal file
19
internal/integration/cli/testdata/pki/ca.crt
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC/jCCAeagAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
|
||||
cm5ldGVzMB4XDTIyMDcwODExMTM0OFoXDTMyMDcwNTExMTM0OFowFTETMBEGA1UE
|
||||
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALGI
|
||||
T8ncEbVJ7LtRTZY6Vc2bXlMtagzCqpP+29H7HtsgV4T64QJsPRnfCh0PzOit7JJq
|
||||
SRj526wHZRfSvu0M9wZ2KaC4MVDMP2KhBUKW63nUmdXQMf+z1gHKzCMloAMa0Avb
|
||||
DVsoc9NaiiHX8m59gX328xEHQjNxnNGIretBjsjZw/Xeo2BflVXahnnxMVJqnzEa
|
||||
0jpnGh5BaO4aPKDrJbyELz8Y8F+NGJ2zkSVtBh0gYZrejnioEiSFkSvcxDw3Xhg2
|
||||
QL+NUsRrhYHq10apJhuSkPkraCogbHlN33dslJ+I85xszKt437gGkpDoTKXaxe9L
|
||||
f9xB40PgToK9QfAOIFMCAwEAAaNZMFcwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
|
||||
/wQFMAMBAf8wHQYDVR0OBBYEFF06xQ3JTko0LcX5pvAdp+mLFWgMMBUGA1UdEQQO
|
||||
MAyCCmt1YmVybmV0ZXMwDQYJKoZIhvcNAQELBQADggEBAIkhsj6yVvEoN4q7nj97
|
||||
vY0RpAOyysmhigHK0miioKsd94GDb+aMBYFLKliU48B5/n/KXblu7xsTane8uB3C
|
||||
VeBywkDXLN2a9ax4BaxIkleDOX1xZN4BtxIfdU1QGhFQU0JPDCMxbDjbfN2Kg2Wi
|
||||
iESrsXYKDq2pLNeQdszxPGNlAOjssVHY6IivWOcMRHP0yCDTl5ooq180+U7smFdz
|
||||
NM/6udMOhsgh6bUCeMu9mhaPXMBmK0Lcd68PFunAA8q7a5OfTgIhGC9n7Q0L6CMw
|
||||
7yXb97bd9bPZqeiuw7G7+UiNkJrBdIMc0AYE+wG44Uxu9usrGZZt6zLYzfnJ2vRZ
|
||||
qac=
|
||||
-----END CERTIFICATE-----
|
27
internal/integration/cli/testdata/pki/ca.key
vendored
Normal file
27
internal/integration/cli/testdata/pki/ca.key
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEAsYhPydwRtUnsu1FNljpVzZteUy1qDMKqk/7b0fse2yBXhPrh
|
||||
Amw9Gd8KHQ/M6K3skmpJGPnbrAdlF9K+7Qz3BnYpoLgxUMw/YqEFQpbredSZ1dAx
|
||||
/7PWAcrMIyWgAxrQC9sNWyhz01qKIdfybn2BffbzEQdCM3Gc0Yit60GOyNnD9d6j
|
||||
YF+VVdqGefExUmqfMRrSOmcaHkFo7ho8oOslvIQvPxjwX40YnbORJW0GHSBhmt6O
|
||||
eKgSJIWRK9zEPDdeGDZAv41SxGuFgerXRqkmG5KQ+StoKiBseU3fd2yUn4jznGzM
|
||||
q3jfuAaSkOhMpdrF70t/3EHjQ+BOgr1B8A4gUwIDAQABAoIBAQCIvqY2pfw916Mw
|
||||
5X8NqAFPTc1p5CE7kvYw6K4JH5S01ESVeWi3pQerVdFEcVc0IkOGw7dqNYqvB0Mn
|
||||
Bn1pugLMR1fpI/dYdPqdzclvcTAPt2KG/saEXtEIsFxs9h46RfzaJPA0twQAWEzt
|
||||
pJhn4uRLUlwHUb/8QBa6jrzn6KdCrLC0jc0g8c77x3omkfy0chug7q2s/yX2MwEX
|
||||
p5pbyPiGZkNIjuDeic3D0ssrH7v7gEYBdybgl78LrLkKA8gEFLrGvrT5nuLYhxkF
|
||||
dhRu3+p9mhhKmJQndto8Y4WeYhXZ7qN2YZbfcv1Xni6cq4UhLmr2czRaK0KVZ15H
|
||||
kzYh0I8BAoGBAOTjpoVVc+IgVJnGeglrJP8zOKEiwj3R+eF9DiQuTdnop0SBiqYB
|
||||
JT6/b/apdYEGz2nBs3M1k6CmNrkzGADMNins7m1MRHkljRqu1IHSF3Us2yifPUef
|
||||
lEUHtXf3ANvf3YJWuGO7RT4sird/1vXE/0TCzjWEvkHc6Zvky/DCydTJAoGBAMaP
|
||||
bWsiDSFpLV6iCiq18bmJJoUDnkXqnwsUVw9C978h2Hx5ysYfOUt6S6Q7UsR7hKW5
|
||||
iay1aiFPBjLQyD4Ac8feZFQEQ5gFYXPEfIV3OYZDz2U+gAZp33ow7/H/73kngelV
|
||||
6EXhTYgDRUwfTBOMSlzhCZwQb8Rzpv+gC3TFsmY7AoGAWewB2LIYo8bV1c/+08Jv
|
||||
N39VCSERtJ3QkMDDlH1Igop/ZE+MO+mJS1yETSCIFFerlr3NlT6AMAX8y8eB75ZK
|
||||
1S/K/8+NuxaAl/IFdLcoFhW4R/4/YesUogYESgwVH0yUxobxS+Ufr+xp1ut3dPie
|
||||
3NG3l5j98fwrHt7FLGIqTtkCgYEAjezfDQCd2g/PuiCgm77JNRDvU4wuiVMWs1iq
|
||||
keIQK7IJh4+WfN68mVKk1pMAqiiPu9VOrwBNB9nwWEoblxXDrE0t8U/K8NKHwbPk
|
||||
PZHmsC2wBHIUGIF8l157Y8LIbRTsKtiY2bodLOcJlUuZmS9hx9migMbO3OC9sWG4
|
||||
TpMw3RkCgYA8ssuhj5wrSQabCXbOU0pn/qbePHWfvh+DcRUXnTtRoothpqvDQxuS
|
||||
73j2NB42UG7j0eWRK993ONGTJ/QNMAJxXwLEuLFtoKHdh7pkq3uFolyNzR+T0vna
|
||||
awkSRmJsbuV7C4mDVHgEaqcEzv/VyeAokw/hqB1Ga9fvauj6MDPshw==
|
||||
-----END RSA PRIVATE KEY-----
|
18
internal/integration/cli/testdata/pki/etcd/ca.crt
vendored
Normal file
18
internal/integration/cli/testdata/pki/etcd/ca.crt
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIC9TCCAd2gAwIBAgIBADANBgkqhkiG9w0BAQsFADASMRAwDgYDVQQDEwdldGNk
|
||||
LWNhMB4XDTIyMDcwODExMTM0OFoXDTMyMDcwNTExMTM0OFowEjEQMA4GA1UEAxMH
|
||||
ZXRjZC1jYTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOgw+tA7odeO
|
||||
H5gKPlhWBjijuNoLlMCJSkGG0Ca/fI6Bk2Y+fzuVv8NWsRrhML3dEWJgXccMhoG0
|
||||
v9MatmvF5nYfm802ZaDCsA6RdJG3PygRTw69pmC4ETfv0+YXpFFfFBeWWb9MsXIP
|
||||
ULooepYy4bWvjG7ZDCeFQ8ACHGE17U0O5rFBqiY0okBjSkl1/oHSzlAVCxa4dOaK
|
||||
/Vj8A8CefT18JZ+jzAbgN7jRm1GWzYTWqACVa5CnRDYRglrZr9DLvaj0ASqck5DD
|
||||
zdJYVQJeVqS7L8qghXfbXzxlkKesRtQsj7V2trpDBuDASJPk6ZmwEWlaI0Wdc3eK
|
||||
nYHgaWybLykCAwEAAaNWMFQwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB/wQFMAMB
|
||||
Af8wHQYDVR0OBBYEFKN5e0IuTpOoTqWB9+MQp/k/OgXgMBIGA1UdEQQLMAmCB2V0
|
||||
Y2QtY2EwDQYJKoZIhvcNAQELBQADggEBAGmGUUqeGe4RXd3kZGTRcdJMo7OkuEK5
|
||||
hH/FHfrLLc3VNoWQafdq4oVrF9bwqDUPRuPgrXl+QY+s4/ztDyHmuKGdLWIT2dCE
|
||||
0Ztnpe17VoMrkJxmFvKEWrT74EnT0QIeFs+lf8+SJWTLYKBRpGrsQKq84uds++gV
|
||||
BPLuu8Z0e5vvkAFnX8m65SqyZwKfs3HuzaAnA57VGSJHCBrnKojsP8JdlWeQiStG
|
||||
CtmzePeLqjVJnpNF/n1ST5Ewr4Kq/Cvf707gzs+spn0bt97QyNke6b24ZrkpUNu6
|
||||
T/0bImLeYiGmSanRF3hAdN7IV0ah7tYOpmwk560kyF8tmd8jcKFgEd8=
|
||||
-----END CERTIFICATE-----
|
27
internal/integration/cli/testdata/pki/etcd/ca.key
vendored
Normal file
27
internal/integration/cli/testdata/pki/etcd/ca.key
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA6DD60Duh144fmAo+WFYGOKO42guUwIlKQYbQJr98joGTZj5/
|
||||
O5W/w1axGuEwvd0RYmBdxwyGgbS/0xq2a8Xmdh+bzTZloMKwDpF0kbc/KBFPDr2m
|
||||
YLgRN+/T5hekUV8UF5ZZv0yxcg9Quih6ljLhta+MbtkMJ4VDwAIcYTXtTQ7msUGq
|
||||
JjSiQGNKSXX+gdLOUBULFrh05or9WPwDwJ59PXwln6PMBuA3uNGbUZbNhNaoAJVr
|
||||
kKdENhGCWtmv0Mu9qPQBKpyTkMPN0lhVAl5WpLsvyqCFd9tfPGWQp6xG1CyPtXa2
|
||||
ukMG4MBIk+TpmbARaVojRZ1zd4qdgeBpbJsvKQIDAQABAoIBAHI8xun0rOfU8Q5o
|
||||
28uyZ1UumCAPWpxv76zVm0u1Ip8qeU7wqMC0KKj+2hwTd1uyjH8OUpVAQF1IhKhk
|
||||
mCPmNkEfxBPvE4lIwD4qqmOW+OfJvE/QVy924GHZCTRHpXyzfrssKfPI0/T+PAWb
|
||||
LNUBK7OsLzfKagR3uKGbaEMbuSkTn5zeCJ1vrFAuCaLmeauBsnoV7Z9AlbG6t8sp
|
||||
hyD0O+pDPGuc+J99suGiysndwjczqntIKXcdgba2XxRE0QHM+ZYDPpyvCggKfoUH
|
||||
sQ9Vz/UHpqTv8pbrTSZK59E8+16YfFyFC+iwTnTzoBAkO6NIivDTQvLcipweZEzt
|
||||
5146EEECgYEA6O+Pd1tdkTVHLgSkKrkBo4p3g2iBFl626g7vlZGvDjVNNPBWwk5f
|
||||
j3PbMKPfUfr96YB86lbetDzYdiB5LrLW5xG2GaSRziGI1/Tgdp6aR142TNljiEu7
|
||||
dv4v3eAR5VfiA5CGera+k1VzKLIygfCDkUWWdG17LvVdHFtjN6XVU2UCgYEA/y6M
|
||||
hZbZqCX9cx58rhJ38YvH9fdWSzw1r9crgM40uPHE4SHvin6/lR/rbNU4Geg/b4bn
|
||||
FWnffCem8ov2tXcFe/ZBM8ZWrsRGDinkTh8dReh8ujE90YOqf3YSRYgUvSx8ITUn
|
||||
zqhe43sGVAelKeVKPW/3Ok7RJXnRRsDIbSmfqnUCgYB7sDmON4XHxXK2jOBfjz2/
|
||||
iZdMwAFLz59xSd0Onv1FnigRJE3tf5BerDaH7Xx4G78YbpHmHZrEOkr27udqVKyo
|
||||
pk777tc9jbEMe4t1cWKa4vwScpzXkt9IoFDqkEDwd2ocWnIOV1t7ALTVt0n6laxH
|
||||
R5xM1pXCqad3l09oDTbpwQKBgDlHwqVOCkeTV4QayNPuM1xWCymsPoOe3VI+U3aT
|
||||
UwRcyNvcWT/WWbzosFj6t6AhIPQw7PhCjrb406HIRzXOpL2Btnsfv191kWAmiSf8
|
||||
Ff8WQ8ErwnugOYpo/4r6E+Wu8aImo2vhIYOgnvgHy0xPOs31ryI4hPwLjy15osPW
|
||||
Pw/tAoGBAKaT53bqIl+wzltM2ROtH9ppA98prDPM0GyZMhFed+XMLAkUX3qmFtj5
|
||||
k51bhaq7ER4yByHX17Q7y3SoJ5NpccmFUhWhttRf/IraWEKsHXW6OY22wvtZN9Lx
|
||||
Eh+rpZsjcozUCaoQWkOf20UpBSltIV5U4GmSpthnj0+zaRrorxWx
|
||||
-----END RSA PRIVATE KEY-----
|
19
internal/integration/cli/testdata/pki/front-proxy-ca.crt
vendored
Normal file
19
internal/integration/cli/testdata/pki/front-proxy-ca.crt
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDCjCCAfKgAwIBAgIBADANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDEw5mcm9u
|
||||
dC1wcm94eS1jYTAeFw0yMjA3MDgxMTEzNDhaFw0zMjA3MDUxMTEzNDhaMBkxFzAV
|
||||
BgNVBAMTDmZyb250LXByb3h5LWNhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
|
||||
CgKCAQEA4thL1utf/iXxylt24O3o3IV7oif5tiYR4SN9YnVb/GLyVtVdHuzPpigw
|
||||
j+S7aw3mldNHVWbIPq9GncvVsgvlJYHu53WRzVfV7tAylt/ssSqHFv/p1e6rC2m9
|
||||
hETHUZjSs8v0APWi8pfh15lJPqLS1lGF3QPVCPdc1t+8dBVnx8wnTgGVE7FVLjmc
|
||||
3qIcXTR1TfcB4+X1ZnY5FNK7kR/kgIS64uZqntyNSW5W0SCFgWQClwwkzVpo4v/Y
|
||||
sCHiWI7cIuXHTTd7ntHJab1Og1jAPNEmENvEtza1SqGTSEUQs5wjS+p+ii5E09b3
|
||||
Nufj1e8hJaodTxr+24hoFcYxWIgxhwIDAQABo10wWzAOBgNVHQ8BAf8EBAMCAqQw
|
||||
DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUvw91sUxAgIX7zdqTKwJ0Sdxa9TUw
|
||||
GQYDVR0RBBIwEIIOZnJvbnQtcHJveHktY2EwDQYJKoZIhvcNAQELBQADggEBAGHW
|
||||
snsEJkN3d2vNJuFu6IVKurEZM8UbwHebJ5fQUHpCOKpFqSMdngF8rdcYNmHeUFMv
|
||||
Qf9Fkm9nwKOhO9hApsQad7UgJ98YCzE+heTye7nKjrga+2lsJN/T3SgJGiAEkVjP
|
||||
rq2SQ4MLCp56PyFI5CL9zqtjuXCI8Uhqqfru6tJEA75GA6VJZmfiOgzFQum7DeC2
|
||||
9dNcvQb8p91LIl5tjvuTgPbJDjF1YX4n0iwoiA05e+rPrsPhyySQnJwFgTi+hqPZ
|
||||
cBUPwVDYeiHseRbj3ODOoCv6PO4koO5m+tiFeUXJTynMbCUkyJqZ11TAYC6snHxi
|
||||
mg+fblveomK3F3hLFdk=
|
||||
-----END CERTIFICATE-----
|
27
internal/integration/cli/testdata/pki/front-proxy-ca.key
vendored
Normal file
27
internal/integration/cli/testdata/pki/front-proxy-ca.key
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA4thL1utf/iXxylt24O3o3IV7oif5tiYR4SN9YnVb/GLyVtVd
|
||||
HuzPpigwj+S7aw3mldNHVWbIPq9GncvVsgvlJYHu53WRzVfV7tAylt/ssSqHFv/p
|
||||
1e6rC2m9hETHUZjSs8v0APWi8pfh15lJPqLS1lGF3QPVCPdc1t+8dBVnx8wnTgGV
|
||||
E7FVLjmc3qIcXTR1TfcB4+X1ZnY5FNK7kR/kgIS64uZqntyNSW5W0SCFgWQClwwk
|
||||
zVpo4v/YsCHiWI7cIuXHTTd7ntHJab1Og1jAPNEmENvEtza1SqGTSEUQs5wjS+p+
|
||||
ii5E09b3Nufj1e8hJaodTxr+24hoFcYxWIgxhwIDAQABAoIBAQDa55WQCcWxkNZa
|
||||
y5bVimBbZeif2+nKj8RTOZdGyzAAR0/K4c0iCa58jm4GfdkqftiUnrVIwY3dh/Ei
|
||||
V1CZp4byggeUjs0rlmaZNYqMM/zKHtsMI9t4mf+vXNQI7wJVSJ+T5+5IesJLTqwf
|
||||
DQo0ipXhQfxnAsqzA1ow9Ol8MCfdEeFL5SFaVNiNhany/7PR0letngwMIAje6arY
|
||||
6dPzjPYDsCjMTjoNarUADIZeVxMdbOCmiMy+yGDZlgV80fK0+Fw81axot2KOufhy
|
||||
CvqClUlJV5Csz2egHuThuVd39kX2vAAGXdPEUbXga1JTDB3cQiHXJo0hLUsUGniS
|
||||
6KdsJOyRAoGBAOmNX/V7awLiVyWsRLTNr1IeoMwHeS3Wdt5/nedqh6p2fLpfbN1D
|
||||
M8R29yqvNn1YmpZsDBhQlnddq7i7OEKjSODwNnLPys6fqalsIY/AIRJPOmHvVJl6
|
||||
er4scaiGXA/FztvxGGQh4W92+Nb69dCXXXcG1QUljr+uGwrIGXc8aqzpAoGBAPil
|
||||
4qGf/0s3Fv0tyLj+ZRWVjg5o4s/IsJyGRFc6RplU65y9VL9WsYvi5+d06w7lovac
|
||||
omycJ/z+HiqTLcixdcHse54N9HHO5Ekui6cRbGAOdlzgS84TxYrmQK/FQkFvlcmO
|
||||
rsfkDMmAgBc2yGP3N5IL60u90N2Kf3OiT5aHoCTvAoGAamdwioS6EkxQa+d6Pe1f
|
||||
rMgrdgkJmmqVKXV22VHdkTn+RWLoVD4jvaR9o0LEToMpmtKLCCDfDG7up3EUhreh
|
||||
ommOROyKd2yifX+4Iqfj6VWTQb8qCeqVNUNGXQMpuj3iqq3C8QvGi2PmpvsbNvdf
|
||||
K7U/I+MikA2gYF8dywcJitECgYArDe5UNjQqffuJE2hyP/qY5jCW5ip/+Cw8rjMf
|
||||
N4QKAN5bYZ1PFF/h7QRi26foCHNTaIPncpKqCAaJMLr4yWGulphBIgF1w3FcCqc7
|
||||
4pR1fYuZQW1e3aWTC5Of2/RBCGVTZVV2X1KngYyseFvyk1gX/eBcWR3VfqnbB/vo
|
||||
AMwGGQKBgB/MXrB2Z61WlxR0Y289k+5gjUSS9foZIkCjr1TFDvLbEStAW8Z3WFcS
|
||||
Gxzjs5s45VO3+KRRd3591WHaPWcVdNze+y5ICUr4u3WSBKg8D+9H3cMKWq8QLCRP
|
||||
bgMDGq8TzTLdGmb9vw3n5OG2aAQUQfwoAp+uUwh2EDMDYixYd2UJ
|
||||
-----END RSA PRIVATE KEY-----
|
27
internal/integration/cli/testdata/pki/sa.key
vendored
Normal file
27
internal/integration/cli/testdata/pki/sa.key
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEA0H28tj4Zgoj5y+/NF7Dhrf96+TQUolLR5j4YqoxbFRvgWtPE
|
||||
0JFueoC0n6v4l58z4vog+1JjPHMO8rr0W3q9o/wWaY1CL3XqZJIkHI/fE/Eu1VLv
|
||||
gLfDHsPevPNLczcpwXo7AadqxiUC/HRYZBJY+LA2OzWwO5ylx4YKnOzKxBXQ7a2q
|
||||
qdpwZJSTTmGKyRx5pD6V5mCr47ITVAXqcjorTtJmG3zCFRhUjMscXIWC04S0IY/C
|
||||
+cfMKaK4Jbqj1h2/9uNhbb55r9HdCEV/TLw+QL1Q+S6MWtng1S4Q3hyDXzB1LqfP
|
||||
1brz7xl1pSLh+l0vF2pXom5zYiHlX4cAddR7MQIDAQABAoIBAAQtULeR/O7Zka+d
|
||||
SU2dNJhI0wzlFzi9Ugk720CneTeuDEuljH7lOwJnS7cbOerHvMFiY4DFgMl4QKdq
|
||||
SXT/u4bqiQRqWRYcVarYJrMPytdacKbDd5rrk5QtNmwwr6VKSKLgsQfyc7gui6XF
|
||||
KvQuTewFk8CR7crz83pQ3CuSrulIwVny17HSE9NlXlv8SlHy7E2/a6H0UeOm7BRn
|
||||
13An62CfRuBVFRd96oyTMpuNf2l+fcL5nnfM/F+tdr5MRR0pnEW2UKGdCbkTkAKd
|
||||
AJnH2mmhWwbA8Gcx0Zn1X9/zu8Z3S6hTGnQmWIP25EcgipqKe/gocA9ervyR+0nb
|
||||
FgwZZXECgYEA6D/mx3dI6AUY7RVIY9GexiJWLtS9O1d7PddmajoqVpwtjXT9jUf/
|
||||
9BAAVWNKcIEs1t4foncJeYph6JnTrQjDz1LORC2kAjPUYhDQod/m6dqHxvjRAIns
|
||||
v0NezDvWQ2v8CgklDjUc5hYtvqj51OkkbKpphRClAdJZvrlxBhXTT1UCgYEA5c/c
|
||||
A6D3xIcGUrSVrjtLWUyJ9hszjjBrI5txtmwMzWDSkV3Hp1VhSfhCdIxqQxELxlxS
|
||||
A8SOU0XKxRB7QiwpgHfnbGxtQ8tJ5JufIecwJkqRcD5fqQk69xva/76fNfes41L8
|
||||
doNpFiu0fXbVdcB8UNN61VYsz31D/JD0qA9k5G0CgYEA5gq1egkrC7ZQ1DRqeYSd
|
||||
8b79AnHx5Z9nEQAUD1ABs7wKWrzwkEoqugJHckxg5ULtuP5W80NY/SwWgqArTI8L
|
||||
9IUejeVvOEdCLMhe/peaTzQHnQvDaPc0qtX+RelW9300LnSUYZg2QajiMqGIpF0x
|
||||
mPjKf+TWrBFAl2tzCgYAQekCgYEAukqjaXWlI/To1UZ6R8DdNchr1cr7Ifpx/21U
|
||||
4rH4NsyUJS7GWAlIUnQjOuNQiIla6DOScGd3kF11IAZaRKwUAIYyXZwPfvNeNSlJ
|
||||
+Gu2hnPQLhMB7L8Ew6gbAVH/MfpSdfyhl1izaTuIlmQsacXdgI/OdP3kWVaMNEM1
|
||||
cL755IkCgYAv10G49Mc57WBi6knRHM2cXbYVxjzedJf8zBnAYkQoLdRiYT6uj34U
|
||||
hI1EajSfXYJ2t8PG5nbHMNHAEbYNBikhjDvSrZW+HaTmjsVGV25cqCHPy7giSqVS
|
||||
VftcMlIX/MlTdfcYtNT4wHORZdO2P4wW/y5JSFNol4z3xB4TNXp55A==
|
||||
-----END RSA PRIVATE KEY-----
|
@ -16,6 +16,8 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/talos-systems/crypto/x509"
|
||||
@ -192,8 +194,6 @@ func (c *SystemClock) SetFixedTimestamp(t time.Time) {
|
||||
}
|
||||
|
||||
// NewSecretsBundle creates secrets bundle generating all secrets or reading from the input options if provided.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func NewSecretsBundle(clock Clock, opts ...GenOption) (*SecretsBundle, error) {
|
||||
options := DefaultGenOptions()
|
||||
|
||||
@ -208,115 +208,256 @@ func NewSecretsBundle(clock Clock, opts ...GenOption) (*SecretsBundle, error) {
|
||||
return options.Secrets, nil
|
||||
}
|
||||
|
||||
bundle := SecretsBundle{
|
||||
Clock: clock,
|
||||
}
|
||||
|
||||
err := populateSecretsBundle(options.VersionContract, &bundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bundle, nil
|
||||
}
|
||||
|
||||
// NewSecretsBundleFromKubernetesPKI creates secrets bundle by reading the contents
|
||||
// of a Kubernetes PKI directory (typically `/etc/kubernetes/pki`) and using the provided bootstrapToken as input.
|
||||
//
|
||||
//nolint:gocyclo
|
||||
func NewSecretsBundleFromKubernetesPKI(pkiDir, bootstrapToken string, versionContract *config.VersionContract) (*SecretsBundle, error) {
|
||||
dirStat, err := os.Stat(pkiDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !dirStat.IsDir() {
|
||||
return nil, fmt.Errorf("%q is not a directory", pkiDir)
|
||||
}
|
||||
|
||||
var (
|
||||
etcd *x509.CertificateAuthority
|
||||
kubernetesCA *x509.CertificateAuthority
|
||||
aggregatorCA *x509.CertificateAuthority
|
||||
serviceAccount *x509.ECDSAKey
|
||||
talosCA *x509.CertificateAuthority
|
||||
trustdInfo *TrustdInfo
|
||||
kubeadmTokens *Secrets
|
||||
err error
|
||||
ca *x509.PEMEncodedCertificateAndKey
|
||||
etcdCA *x509.PEMEncodedCertificateAndKey
|
||||
aggregatorCA *x509.PEMEncodedCertificateAndKey
|
||||
sa *x509.PEMEncodedKey
|
||||
)
|
||||
|
||||
etcd, err = NewEtcdCA(clock.Now(), options.VersionContract)
|
||||
ca, err = x509.NewCertificateAndKeyFromFiles(filepath.Join(pkiDir, "ca.crt"), filepath.Join(pkiDir, "ca.key"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kubernetesCA, err = NewKubernetesCA(clock.Now(), options.VersionContract)
|
||||
err = validatePEMEncodedCertificateAndKey(ca)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if options.VersionContract.SupportsAggregatorCA() {
|
||||
aggregatorCA, err = NewAggregatorCA(clock.Now(), options.VersionContract)
|
||||
etcdDir := filepath.Join(pkiDir, "etcd")
|
||||
|
||||
etcdCA, err = x509.NewCertificateAndKeyFromFiles(filepath.Join(etcdDir, "ca.crt"), filepath.Join(etcdDir, "ca.key"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = validatePEMEncodedCertificateAndKey(etcdCA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
aggregatorCACrtPath := filepath.Join(pkiDir, "front-proxy-ca.crt")
|
||||
_, err = os.Stat(aggregatorCACrtPath)
|
||||
|
||||
aggregatorCAFound := err == nil
|
||||
if aggregatorCAFound && !versionContract.SupportsAggregatorCA() {
|
||||
return nil, fmt.Errorf("aggregator CA found in pki dir but is not supported by the requested version")
|
||||
}
|
||||
|
||||
if versionContract.SupportsAggregatorCA() {
|
||||
aggregatorCA, err = x509.NewCertificateAndKeyFromFiles(aggregatorCACrtPath, filepath.Join(pkiDir, "front-proxy-ca.key"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = validatePEMEncodedCertificateAndKey(aggregatorCA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if options.VersionContract.SupportsServiceAccount() {
|
||||
serviceAccount, err = x509.NewECDSAKey()
|
||||
saKeyPath := filepath.Join(pkiDir, "sa.key")
|
||||
_, err = os.Stat(saKeyPath)
|
||||
|
||||
saKeyFound := err == nil
|
||||
if saKeyFound && !versionContract.SupportsServiceAccount() {
|
||||
return nil, fmt.Errorf("service account key found in pki dir but is not supported by the requested version")
|
||||
}
|
||||
|
||||
if versionContract.SupportsServiceAccount() {
|
||||
var saBytes []byte
|
||||
|
||||
saBytes, err = os.ReadFile(filepath.Join(pkiDir, "sa.key"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sa = &x509.PEMEncodedKey{
|
||||
Key: saBytes,
|
||||
}
|
||||
|
||||
_, err = sa.GetKey()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
talosCA, err = NewTalosCA(clock.Now())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kubeadmTokens = &Secrets{}
|
||||
|
||||
// Gen trustd token strings
|
||||
kubeadmTokens.BootstrapToken, err = genToken(6, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kubeadmTokens.AESCBCEncryptionSecret, err = cis.CreateEncryptionToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
trustdInfo = &TrustdInfo{}
|
||||
|
||||
// Gen trustd token strings
|
||||
trustdInfo.Token, err = genToken(6, 16)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clusterID, err := randBytes(constants.DefaultClusterIDSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate cluster ID: %w", err)
|
||||
}
|
||||
|
||||
clusterSecret, err := randBytes(constants.DefaultClusterSecretSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to generate cluster secret: %w", err)
|
||||
}
|
||||
|
||||
result := &SecretsBundle{
|
||||
Cluster: &Cluster{
|
||||
ID: base64.URLEncoding.EncodeToString(clusterID),
|
||||
Secret: base64.StdEncoding.EncodeToString(clusterSecret),
|
||||
bundle := SecretsBundle{
|
||||
Secrets: &Secrets{
|
||||
BootstrapToken: bootstrapToken,
|
||||
},
|
||||
Clock: clock,
|
||||
Secrets: kubeadmTokens,
|
||||
TrustdInfo: trustdInfo,
|
||||
Certs: &Certs{
|
||||
Etcd: &x509.PEMEncodedCertificateAndKey{
|
||||
Crt: etcd.CrtPEM,
|
||||
Key: etcd.KeyPEM,
|
||||
},
|
||||
K8s: &x509.PEMEncodedCertificateAndKey{
|
||||
Crt: kubernetesCA.CrtPEM,
|
||||
Key: kubernetesCA.KeyPEM,
|
||||
},
|
||||
OS: &x509.PEMEncodedCertificateAndKey{
|
||||
Crt: talosCA.CrtPEM,
|
||||
Key: talosCA.KeyPEM,
|
||||
},
|
||||
Etcd: etcdCA,
|
||||
K8s: ca,
|
||||
K8sAggregator: aggregatorCA,
|
||||
K8sServiceAccount: sa,
|
||||
},
|
||||
}
|
||||
|
||||
if aggregatorCA != nil {
|
||||
result.Certs.K8sAggregator = &x509.PEMEncodedCertificateAndKey{
|
||||
err = populateSecretsBundle(versionContract, &bundle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &bundle, nil
|
||||
}
|
||||
|
||||
// populateSecretsBundle fills all the missing fields in the secrets bundle.
|
||||
//
|
||||
//nolint:gocyclo,cyclop
|
||||
func populateSecretsBundle(versionContract *config.VersionContract, bundle *SecretsBundle) error {
|
||||
if bundle.Clock == nil {
|
||||
bundle.Clock = NewClock()
|
||||
}
|
||||
|
||||
if bundle.Certs == nil {
|
||||
bundle.Certs = &Certs{}
|
||||
}
|
||||
|
||||
if bundle.Certs.Etcd == nil {
|
||||
etcd, err := NewEtcdCA(bundle.Clock.Now(), versionContract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.Certs.Etcd = &x509.PEMEncodedCertificateAndKey{
|
||||
Crt: etcd.CrtPEM,
|
||||
Key: etcd.KeyPEM,
|
||||
}
|
||||
}
|
||||
|
||||
if bundle.Certs.K8s == nil {
|
||||
kubernetesCA, err := NewKubernetesCA(bundle.Clock.Now(), versionContract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.Certs.K8s = &x509.PEMEncodedCertificateAndKey{
|
||||
Crt: kubernetesCA.CrtPEM,
|
||||
Key: kubernetesCA.KeyPEM,
|
||||
}
|
||||
}
|
||||
|
||||
if versionContract.SupportsAggregatorCA() && bundle.Certs.K8sAggregator == nil {
|
||||
aggregatorCA, err := NewAggregatorCA(bundle.Clock.Now(), versionContract)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.Certs.K8sAggregator = &x509.PEMEncodedCertificateAndKey{
|
||||
Crt: aggregatorCA.CrtPEM,
|
||||
Key: aggregatorCA.KeyPEM,
|
||||
}
|
||||
}
|
||||
|
||||
if serviceAccount != nil {
|
||||
result.Certs.K8sServiceAccount = &x509.PEMEncodedKey{
|
||||
if versionContract.SupportsServiceAccount() && bundle.Certs.K8sServiceAccount == nil {
|
||||
serviceAccount, err := x509.NewECDSAKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.Certs.K8sServiceAccount = &x509.PEMEncodedKey{
|
||||
Key: serviceAccount.KeyPEM,
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
if bundle.Certs.OS == nil {
|
||||
talosCA, err := NewTalosCA(bundle.Clock.Now())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.Certs.OS = &x509.PEMEncodedCertificateAndKey{
|
||||
Crt: talosCA.CrtPEM,
|
||||
Key: talosCA.KeyPEM,
|
||||
}
|
||||
}
|
||||
|
||||
if bundle.Secrets == nil {
|
||||
bundle.Secrets = &Secrets{}
|
||||
}
|
||||
|
||||
if bundle.Secrets.BootstrapToken == "" {
|
||||
token, err := genToken(6, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.Secrets.BootstrapToken = token
|
||||
}
|
||||
|
||||
if bundle.Secrets.AESCBCEncryptionSecret == "" {
|
||||
aesCBCEncryptionSecret, err := cis.CreateEncryptionToken()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.Secrets.AESCBCEncryptionSecret = aesCBCEncryptionSecret
|
||||
}
|
||||
|
||||
if bundle.TrustdInfo == nil {
|
||||
bundle.TrustdInfo = &TrustdInfo{}
|
||||
}
|
||||
|
||||
if bundle.TrustdInfo.Token == "" {
|
||||
token, err := genToken(6, 16)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
bundle.TrustdInfo.Token = token
|
||||
}
|
||||
|
||||
if bundle.Cluster == nil {
|
||||
bundle.Cluster = &Cluster{}
|
||||
}
|
||||
|
||||
if bundle.Cluster.ID == "" {
|
||||
clusterID, err := randBytes(constants.DefaultClusterIDSize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate cluster ID: %w", err)
|
||||
}
|
||||
|
||||
bundle.Cluster.ID = base64.URLEncoding.EncodeToString(clusterID)
|
||||
}
|
||||
|
||||
if bundle.Cluster.Secret == "" {
|
||||
clusterSecret, err := randBytes(constants.DefaultClusterSecretSize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate cluster secret: %w", err)
|
||||
}
|
||||
|
||||
bundle.Cluster.Secret = base64.StdEncoding.EncodeToString(clusterSecret)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewSecretsBundleFromConfig creates secrets bundle using existing config.
|
||||
@ -608,3 +749,14 @@ func randBytes(size int) ([]byte, error) {
|
||||
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func validatePEMEncodedCertificateAndKey(certs *x509.PEMEncodedCertificateAndKey) error {
|
||||
_, err := certs.GetKey()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = certs.GetCert()
|
||||
|
||||
return err
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
// GenOption controls generate options specific to input generation.
|
||||
type GenOption func(o *GenOptions) error
|
||||
|
||||
// WithEndpointList specifies endpoints to use when acessing Talos cluster.
|
||||
// WithEndpointList specifies endpoints to use when accessing Talos cluster.
|
||||
func WithEndpointList(endpoints []string) GenOption {
|
||||
return func(o *GenOptions) error {
|
||||
o.EndpointList = endpoints
|
||||
|
@ -1253,9 +1253,11 @@ talosctl gen secrets [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for secrets
|
||||
-o, --output-file string path of the output file (default "secrets.yaml")
|
||||
--talos-version string the desired Talos version to generate secrets bundle for (backwards compatibility, e.g. v0.8)
|
||||
-p, --from-kubernetes-pki string use a Kubernetes PKI directory (e.g. /etc/kubernetes/pki) as input
|
||||
-h, --help help for secrets
|
||||
-t, --kubernetes-bootstrap-token string use the provided bootstrap token as input
|
||||
-o, --output-file string path of the output file (default "secrets.yaml")
|
||||
--talos-version string the desired Talos version to generate secrets bundle for (backwards compatibility, e.g. v0.8)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
Loading…
x
Reference in New Issue
Block a user