diff --git a/nodeup/pkg/model/kube_apiserver.go b/nodeup/pkg/model/kube_apiserver.go index 820fada9c8..710138d102 100644 --- a/nodeup/pkg/model/kube_apiserver.go +++ b/nodeup/pkg/model/kube_apiserver.go @@ -64,26 +64,24 @@ func (b *KubeAPIServerBuilder) Build(c *fi.ModelBuilderContext) error { return err } - if b.Cluster.Spec.EncryptionConfig != nil { - if *b.Cluster.Spec.EncryptionConfig { - encryptionConfigPath := fi.String(filepath.Join(b.PathSrvKubernetes(), "encryptionconfig.yaml")) + if b.NodeupConfig.APIServerConfig.EncryptionConfigSecretHash != "" { + encryptionConfigPath := fi.String(filepath.Join(b.PathSrvKubernetes(), "kube-apiserver", "encryptionconfig.yaml")) - kubeAPIServer.EncryptionProviderConfig = encryptionConfigPath + kubeAPIServer.EncryptionProviderConfig = encryptionConfigPath - key := "encryptionconfig" - encryptioncfg, err := b.SecretStore.Secret(key) - if err == nil { - contents := string(encryptioncfg.Data) - t := &nodetasks.File{ - Path: *encryptionConfigPath, - Contents: fi.NewStringResource(contents), - Mode: fi.String("600"), - Type: nodetasks.FileType_File, - } - c.AddTask(t) - } else { - return fmt.Errorf("encryptionConfig enabled, but could not load encryptionconfig secret: %v", err) + key := "encryptionconfig" + encryptioncfg, err := b.SecretStore.Secret(key) + if err == nil { + contents := string(encryptioncfg.Data) + t := &nodetasks.File{ + Path: *encryptionConfigPath, + Contents: fi.NewStringResource(contents), + Mode: fi.String("600"), + Type: nodetasks.FileType_File, } + c.AddTask(t) + } else { + return fmt.Errorf("encryptionConfig enabled, but could not load encryptionconfig secret: %v", err) } } { diff --git a/pkg/apis/nodeup/config.go b/pkg/apis/nodeup/config.go index 7c81c6b123..a1ce893049 100644 --- a/pkg/apis/nodeup/config.go +++ b/pkg/apis/nodeup/config.go @@ -123,6 +123,10 @@ type StaticManifest struct { type APIServerConfig struct { // KubeAPIServer is a copy of the KubeAPIServerConfig from the cluster spec. KubeAPIServer *kops.KubeAPIServerConfig + // EncryptionConfigSecretHash is a hash of the encryptionconfig secret. + // It is empty if EncryptionConfig is not enabled. + // TODO: give secrets IDs and look them up like we do keypairs. + EncryptionConfigSecretHash string `json:",omitempty"` } func NewConfig(cluster *kops.Cluster, instanceGroup *kops.InstanceGroup) (*Config, *BootConfig) { diff --git a/upup/pkg/fi/cloudup/apply_cluster.go b/upup/pkg/fi/cloudup/apply_cluster.go index 0b50b88f31..a87ce7e29e 100644 --- a/upup/pkg/fi/cloudup/apply_cluster.go +++ b/upup/pkg/fi/cloudup/apply_cluster.go @@ -19,6 +19,8 @@ package cloudup import ( "bytes" "context" + "crypto/sha256" + "encoding/base64" "fmt" "io" "net" @@ -333,6 +335,7 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error { } } + encryptionConfigSecretHash := "" if fi.BoolValue(c.Cluster.Spec.EncryptionConfig) { secret, err := secretStore.FindSecret("encryptionconfig") if err != nil { @@ -344,6 +347,8 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error { fmt.Println("See `kops create secret encryptionconfig -h` and https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/") return fmt.Errorf("could not find encryptionconfig secret") } + hashBytes := sha256.Sum256(secret.Data) + encryptionConfigSecretHash = base64.URLEncoding.EncodeToString(hashBytes[:]) } ciliumSpec := c.Cluster.Spec.Networking.Cilium @@ -487,7 +492,7 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error { cloud: cloud, } - configBuilder, err := newNodeUpConfigBuilder(cluster, assetBuilder, c.Assets) + configBuilder, err := newNodeUpConfigBuilder(cluster, assetBuilder, c.Assets, encryptionConfigSecretHash) if err != nil { return err } @@ -1139,17 +1144,18 @@ type nodeUpConfigBuilder struct { // url with hash: @http://... or @https://... assets map[architectures.Architecture][]*mirrors.MirroredAsset - assetBuilder *assets.AssetBuilder - channels []string - configBase vfs.Path - cluster *kops.Cluster - etcdManifests map[kops.InstanceGroupRole][]string - images map[kops.InstanceGroupRole]map[architectures.Architecture][]*nodeup.Image - protokubeAsset map[architectures.Architecture][]*mirrors.MirroredAsset - channelsAsset map[architectures.Architecture][]*mirrors.MirroredAsset + assetBuilder *assets.AssetBuilder + channels []string + configBase vfs.Path + cluster *kops.Cluster + etcdManifests map[kops.InstanceGroupRole][]string + images map[kops.InstanceGroupRole]map[architectures.Architecture][]*nodeup.Image + protokubeAsset map[architectures.Architecture][]*mirrors.MirroredAsset + channelsAsset map[architectures.Architecture][]*mirrors.MirroredAsset + encryptionConfigSecretHash string } -func newNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBuilder, assets map[architectures.Architecture][]*mirrors.MirroredAsset) (model.NodeUpConfigBuilder, error) { +func newNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBuilder, assets map[architectures.Architecture][]*mirrors.MirroredAsset, encryptionConfigSecretHash string) (model.NodeUpConfigBuilder, error) { configBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigBase) if err != nil { return nil, fmt.Errorf("error parsing config base %q: %v", cluster.Spec.ConfigBase, err) @@ -1282,15 +1288,16 @@ func newNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBui } configBuilder := nodeUpConfigBuilder{ - assetBuilder: assetBuilder, - assets: assets, - channels: channels, - configBase: configBase, - cluster: cluster, - etcdManifests: etcdManifests, - images: images, - protokubeAsset: protokubeAsset, - channelsAsset: channelsAsset, + assetBuilder: assetBuilder, + assets: assets, + channels: channels, + configBase: configBase, + cluster: cluster, + etcdManifests: etcdManifests, + images: images, + protokubeAsset: protokubeAsset, + channelsAsset: channelsAsset, + encryptionConfigSecretHash: encryptionConfigSecretHash, } return &configBuilder, nil @@ -1344,6 +1351,10 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit } } + if isMaster || role == kops.InstanceGroupRoleAPIServer { + config.APIServerConfig.EncryptionConfigSecretHash = n.encryptionConfigSecretHash + } + if isMaster || useGossip { for _, arch := range architectures.GetSupported() { for _, a := range n.protokubeAsset[arch] {