mirror of https://github.com/kubernetes/kops.git
Serve secrets from kops-controller for nodes without state store access
This commit is contained in:
parent
18b5dcd297
commit
61eaeddb9b
|
|
@ -245,6 +245,9 @@ func addNodeController(mgr manager.Manager, opt *config.Options) error {
|
|||
if opt.ConfigBase == "" {
|
||||
return fmt.Errorf("must specify configBase")
|
||||
}
|
||||
if opt.SecretStore == "" {
|
||||
return fmt.Errorf("must specify secretStore")
|
||||
}
|
||||
|
||||
nodeController, err := controllers.NewLegacyNodeReconciler(mgr, opt.ConfigBase, legacyIdentifier)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
type Options struct {
|
||||
Cloud string `json:"cloud,omitempty"`
|
||||
ConfigBase string `json:"configBase,omitempty"`
|
||||
SecretStore string `json:"secretStore,omitempty"`
|
||||
Server *ServerOptions `json:"server,omitempty"`
|
||||
CacheNodeidentityInfo bool `json:"cacheNodeidentityInfo,omitempty"`
|
||||
|
||||
|
|
|
|||
|
|
@ -61,5 +61,21 @@ func (s *Server) getNodeConfig(ctx context.Context, req *nodeup.BootstrapRequest
|
|||
nodeConfig.NodeupConfig = string(b)
|
||||
}
|
||||
|
||||
{
|
||||
secretIDs := []string{
|
||||
"dockerconfig",
|
||||
}
|
||||
nodeConfig.NodeSecrets = make(map[string][]byte)
|
||||
for _, id := range secretIDs {
|
||||
secret, err := s.secretStore.FindSecret(id)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error loading secret %q: %w", id, err)
|
||||
}
|
||||
if secret != nil && secret.Data != nil {
|
||||
nodeConfig.NodeSecrets[id] = secret.Data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodeConfig, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import (
|
|||
"k8s.io/kops/pkg/pki"
|
||||
"k8s.io/kops/pkg/rbac"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/upup/pkg/fi/secrets"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
)
|
||||
|
||||
|
|
@ -48,6 +49,7 @@ type Server struct {
|
|||
server *http.Server
|
||||
verifier bootstrap.Verifier
|
||||
keystore pki.Keystore
|
||||
secretStore fi.SecretStore
|
||||
|
||||
// configBase is the base of the configuration storage.
|
||||
configBase vfs.Path
|
||||
|
|
@ -71,10 +73,16 @@ func NewServer(opt *config.Options, verifier bootstrap.Verifier) (*Server, error
|
|||
|
||||
configBase, err := vfs.Context.BuildVfsPath(opt.ConfigBase)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse ConfigBase %q: %v", opt.ConfigBase, err)
|
||||
return nil, fmt.Errorf("cannot parse ConfigBase %q: %w", opt.ConfigBase, err)
|
||||
}
|
||||
s.configBase = configBase
|
||||
|
||||
p, err := vfs.Context.BuildVfsPath(opt.SecretStore)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse SecretStore %q: %w", opt.SecretStore, err)
|
||||
}
|
||||
s.secretStore = secrets.NewVFSSecretStore(nil, p)
|
||||
|
||||
r := http.NewServeMux()
|
||||
r.Handle("/bootstrap", http.HandlerFunc(s.bootstrap))
|
||||
server.Handler = recovery(r)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ type BootstrapRequest struct {
|
|||
// BootstrapResponse is a response to a BootstrapRequest.
|
||||
type BootstrapResponse struct {
|
||||
// Certs are the issued certificates.
|
||||
Certs map[string]string
|
||||
Certs map[string]string `json:"Certs,omitempty"`
|
||||
|
||||
// NodeConfig contains the node configuration, if IncludeNodeConfig is set.
|
||||
NodeConfig *NodeConfig `json:"nodeConfig,omitempty"`
|
||||
|
|
@ -48,6 +48,9 @@ type NodeConfig struct {
|
|||
|
||||
// NodeupConfig holds the nodeup.Config for the node's instance group.
|
||||
NodeupConfig string `json:"nodeupConfig,omitempty"`
|
||||
|
||||
// NodeSecrets holds the secrets for the node (like `dockerconfig`).
|
||||
NodeSecrets map[string][]byte `json:"nodeSecrets,omitempty"`
|
||||
}
|
||||
|
||||
// NodeConfigCertificate holds a certificate that the node needs to boot.
|
||||
|
|
|
|||
|
|
@ -19,25 +19,31 @@ package configserver
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/kops/pkg/apis/nodeup"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
"k8s.io/kops/util/pkg/vfs"
|
||||
)
|
||||
|
||||
// configserverSecretStore is a SecretStore backed by the config server.
|
||||
type configserverSecretStore struct {
|
||||
nodeConfig *nodeup.NodeConfig
|
||||
nodeSecrets map[string][]byte
|
||||
}
|
||||
|
||||
func NewSecretStore(nodeConfig *nodeup.NodeConfig) fi.SecretStore {
|
||||
func NewSecretStore(nodeSecrets map[string][]byte) fi.SecretStore {
|
||||
return &configserverSecretStore{
|
||||
nodeConfig: nodeConfig,
|
||||
nodeSecrets: nodeSecrets,
|
||||
}
|
||||
}
|
||||
|
||||
// Secret implements fi.SecretStore
|
||||
func (s *configserverSecretStore) Secret(id string) (*fi.Secret, error) {
|
||||
return nil, fmt.Errorf("Secret not supported by configserverSecretStore")
|
||||
secret, err := s.FindSecret(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if secret == nil {
|
||||
return nil, fmt.Errorf("secret %q not found", id)
|
||||
}
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
// DeleteSecret implements fi.SecretStore
|
||||
|
|
@ -47,7 +53,14 @@ func (s *configserverSecretStore) DeleteSecret(id string) error {
|
|||
|
||||
// FindSecret implements fi.SecretStore
|
||||
func (s *configserverSecretStore) FindSecret(id string) (*fi.Secret, error) {
|
||||
return nil, fmt.Errorf("FindSecret not supported by configserverSecretStore")
|
||||
secretBytes, ok := s.nodeSecrets[id]
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
secret := &fi.Secret{
|
||||
Data: secretBytes,
|
||||
}
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
// GetOrCreateSecret implements fi.SecretStore
|
||||
|
|
|
|||
|
|
@ -584,6 +584,7 @@ func (tf *TemplateFunctions) KopsControllerConfig() (string, error) {
|
|||
config := &kopscontrollerconfig.Options{
|
||||
Cloud: string(cluster.Spec.GetCloudProvider()),
|
||||
ConfigBase: cluster.Spec.ConfigBase,
|
||||
SecretStore: cluster.Spec.SecretStore,
|
||||
}
|
||||
|
||||
if featureflag.CacheNodeidentityInfo.Enabled() {
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@ func (c *NodeUpCommand) Run(out io.Writer) error {
|
|||
var secretStore fi.SecretStore
|
||||
var keyStore fi.Keystore
|
||||
if nodeConfig != nil {
|
||||
modelContext.SecretStore = configserver.NewSecretStore(nodeConfig)
|
||||
modelContext.SecretStore = configserver.NewSecretStore(nodeConfig.NodeSecrets)
|
||||
} else if c.cluster.Spec.SecretStore != "" {
|
||||
klog.Infof("Building SecretStore at %q", c.cluster.Spec.SecretStore)
|
||||
p, err := vfs.Context.BuildVfsPath(c.cluster.Spec.SecretStore)
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ func (c *VFSSecretStore) Secret(id string) (*fi.Secret, error) {
|
|||
return nil, err
|
||||
}
|
||||
if s == nil {
|
||||
return nil, fmt.Errorf("Secret not found: %q", id)
|
||||
return nil, fmt.Errorf("secret %q not found", id)
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue