mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-19 05:31:14 +02:00
This adds RPCs for basic etcd management tasks. Signed-off-by: Andrew Rynhard <andrew@rynhard.io>
112 lines
2.7 KiB
Go
112 lines
2.7 KiB
Go
// 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 main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/aes"
|
|
"encoding/base64"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/kubernetes-sigs/bootkube/pkg/recovery"
|
|
k8saes "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
|
|
|
|
"github.com/talos-systems/talos/internal/pkg/etcd"
|
|
machineapi "github.com/talos-systems/talos/pkg/machinery/api/machine"
|
|
"github.com/talos-systems/talos/pkg/machinery/config"
|
|
"github.com/talos-systems/talos/pkg/machinery/constants"
|
|
)
|
|
|
|
//nolint: gocyclo
|
|
func recoverAssets(config config.Provider) error {
|
|
// Ensure assets directory does not exist / is left over from a failed install
|
|
if err := os.RemoveAll(constants.AssetsDirectory); err != nil {
|
|
// Ignore if the directory does not exist
|
|
if !errors.Is(err, os.ErrNotExist) {
|
|
return err
|
|
}
|
|
}
|
|
|
|
var (
|
|
backend recovery.Backend
|
|
err error
|
|
)
|
|
|
|
switch *recoverSource {
|
|
case machineapi.RecoverRequest_ETCD.String():
|
|
var client *etcd.Client
|
|
|
|
client, err = etcd.NewClient([]string{"127.0.0.1:2379"})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var transform recovery.TransformerFromStorage
|
|
|
|
transform, err = aesTransformer(config.Cluster())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
backend = recovery.NewEtcdBackendWithTransformer(client.Client, "/registry", transform)
|
|
case machineapi.RecoverRequest_APISERVER.String():
|
|
backend, err = recovery.NewAPIServerBackend(constants.RecoveryKubeconfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
as, err := recovery.Recover(context.Background(), backend, constants.RecoveryKubeconfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = os.MkdirAll(constants.AssetsDirectory, 0o600); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err = as.WriteFiles(constants.AssetsDirectory); err != nil {
|
|
return fmt.Errorf("failed to write recovered assets: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func aesTransformer(clusterConfig config.ClusterConfig) (recovery.TransformerFromStorage, error) {
|
|
key, err := base64.StdEncoding.DecodeString(clusterConfig.AESCBCEncryptionSecret())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cipher, err := aes.NewCipher(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
transformer := k8saes.NewCBCTransformer(cipher)
|
|
|
|
return func(value []byte) ([]byte, error) {
|
|
const (
|
|
aesCBCTransformerPrefixV1 = "k8s:enc:aescbc:v1:"
|
|
aesCBCKeyName = "key1:"
|
|
|
|
aesCBCPrefix = aesCBCTransformerPrefixV1 + aesCBCKeyName
|
|
)
|
|
|
|
if !bytes.HasPrefix(value, []byte(aesCBCPrefix)) {
|
|
return value, nil
|
|
}
|
|
|
|
value = value[len(aesCBCPrefix):]
|
|
|
|
value, _, e := transformer.TransformFromStorage(value, nil)
|
|
|
|
return value, e
|
|
}, nil
|
|
}
|