Andrew Rynhard 4ff8824182 feat: add aescbcEncryptionSecret field to machine config
This change allows us to generate the EncryptionConfig on each
controlplane node. The benefit is that we no longer need to distibute
the EncryptionConfig via trustd.

Signed-off-by: Andrew Rynhard <andrew@andrewrynhard.com>
2019-09-25 09:41:20 -07:00

199 lines
6.1 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 cis
import (
"bytes"
"crypto/rand"
"encoding/base64"
"io/ioutil"
"os"
"text/template"
"github.com/talos-systems/talos/pkg/constants"
v1 "k8s.io/api/core/v1"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2"
)
const disabled = "false"
const auditPolicy string = `apiVersion: audit.k8s.io/v1beta1
kind: Policy
rules:
- level: Metadata
`
const encryptionConfig string = `kind: EncryptionConfig
apiVersion: v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: {{ .AESCBCEncryptionSecret }}
- identity: {}
`
// EnforceAuditingRequirements enforces CIS requirements for auditing.
func EnforceAuditingRequirements(cfg *kubeadmapi.ClusterConfiguration) error {
if err := ioutil.WriteFile("/etc/kubernetes/audit-policy.yaml", []byte(auditPolicy), 0400); err != nil {
return err
}
// TODO(andrewrynhard): We should log to a file, and the option to retrieve
// the log files.
cfg.APIServer.ExtraArgs["audit-log-path"] = "-"
cfg.APIServer.ExtraArgs["audit-log-maxage"] = "30"
cfg.APIServer.ExtraArgs["audit-log-maxbackup"] = "3"
cfg.APIServer.ExtraArgs["audit-log-maxsize"] = "50"
return nil
}
// CreateEncryptionToken generates an encryption token to be used for secrets.
func CreateEncryptionToken() (string, error) {
encryptionKey := make([]byte, 32)
if _, err := rand.Read(encryptionKey); err != nil {
return "", err
}
str := base64.StdEncoding.EncodeToString(encryptionKey)
return str, nil
}
// WriteEncryptionConfigToDisk writes an EncryptionConfig to disk.
func WriteEncryptionConfigToDisk(aescbcEncryptionSecret string) error {
if _, err := os.Stat(constants.EncryptionConfigInitramfsPath); os.IsNotExist(err) {
aux := struct {
AESCBCEncryptionSecret string
}{
AESCBCEncryptionSecret: aescbcEncryptionSecret,
}
t, err := template.New("encryptionconfig").Parse(encryptionConfig)
if err != nil {
return err
}
encBytes := []byte{}
buf := bytes.NewBuffer(encBytes)
if err := t.Execute(buf, aux); err != nil {
return err
}
if err := ioutil.WriteFile(constants.EncryptionConfigInitramfsPath, buf.Bytes(), 0400); err != nil {
return err
}
}
return nil
}
// EnforceSecretRequirements enforces CIS requirements for secrets.
func EnforceSecretRequirements(cfg *kubeadmapi.ClusterConfiguration) error {
cfg.APIServer.ExtraArgs["experimental-encryption-provider-config"] = constants.EncryptionConfigRootfsPath
vol := kubeadmapi.HostPathMount{
Name: "encryptionconfig",
HostPath: constants.EncryptionConfigRootfsPath,
MountPath: constants.EncryptionConfigRootfsPath,
ReadOnly: true,
PathType: v1.HostPathFile,
}
cfg.APIServer.ExtraVolumes = append(cfg.APIServer.ExtraVolumes, vol)
return nil
}
// EnforceTLSRequirements enforces CIS requirements for TLS.
func EnforceTLSRequirements(cfg *kubeadmapi.ClusterConfiguration) error {
// nolint: lll
cfg.APIServer.ExtraArgs["tls-cipher-suites"] = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256"
return nil
}
// EnforceAdmissionPluginsRequirements enforces CIS requirements for admission plugins.
// TODO(andrewrynhard): Include any extra user specified plugins.
// TODO(andrewrynhard): Enable EventRateLimit.
// TODO(andrewrynhard): Enable AlwaysPullImages (See https://github.com/kubernetes/kubernetes/issues/64333).
func EnforceAdmissionPluginsRequirements(cfg *kubeadmapi.ClusterConfiguration) error {
// nolint: lll
cfg.APIServer.ExtraArgs["enable-admission-plugins"] = "PodSecurityPolicy,NamespaceLifecycle,ServiceAccount,NodeRestriction,LimitRanger,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota"
return nil
}
// EnforceExtraRequirements enforces miscellaneous CIS requirements.
// TODO(andrewrynhard): Enable anonymous-auth, see https://github.com/kubernetes/kubeadm/issues/798.
// TODO(andrewrynhard): Enable kubelet-certificate-authority, see https://github.com/kubernetes/kubeadm/issues/118#issuecomment-407202481.
func EnforceExtraRequirements(cfg *kubeadmapi.ClusterConfiguration) error {
cfg.APIServer.ExtraArgs["profiling"] = disabled
cfg.ControllerManager.ExtraArgs["profiling"] = disabled
cfg.Scheduler.ExtraArgs["profiling"] = disabled
cfg.APIServer.ExtraArgs["service-account-lookup"] = "true"
return nil
}
// EnforceBootstrapMasterRequirements enforces the CIS requirements for master nodes.
func EnforceBootstrapMasterRequirements(cfg *kubeadmapi.ClusterConfiguration) error {
ensureFieldsAreNotNil(cfg)
if err := EnforceAuditingRequirements(cfg); err != nil {
return err
}
if err := EnforceSecretRequirements(cfg); err != nil {
return err
}
if err := EnforceTLSRequirements(cfg); err != nil {
return err
}
if err := EnforceAdmissionPluginsRequirements(cfg); err != nil {
return err
}
if err := EnforceExtraRequirements(cfg); err != nil {
return err
}
return nil
}
// EnforceCommonMasterRequirements enforces the CIS requirements for master nodes.
func EnforceCommonMasterRequirements(aescbcEncryptionSecret string) error {
return WriteEncryptionConfigToDisk(aescbcEncryptionSecret)
}
// EnforceWorkerRequirements enforces the CIS requirements for master nodes.
func EnforceWorkerRequirements(cfg *kubeadmapi.JoinConfiguration) error {
return nil
}
func ensureFieldsAreNotNil(cfg *kubeadmapi.ClusterConfiguration) {
if cfg.APIServer.ExtraArgs == nil {
cfg.APIServer.ExtraArgs = make(map[string]string)
}
if cfg.ControllerManager.ExtraArgs == nil {
cfg.ControllerManager.ExtraArgs = make(map[string]string)
}
if cfg.Scheduler.ExtraArgs == nil {
cfg.Scheduler.ExtraArgs = make(map[string]string)
}
if cfg.APIServer.ExtraVolumes == nil {
cfg.APIServer.ExtraVolumes = make([]kubeadmapi.HostPathMount, 0)
}
if cfg.FeatureGates == nil {
cfg.FeatureGates = make(map[string]bool)
}
}