2018-11-23 16:50:17 -08:00

177 lines
5.4 KiB
Go

package cis
import (
"bytes"
"encoding/base64"
"io/ioutil"
"math/rand"
"text/template"
"time"
"k8s.io/api/core/v1"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
)
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.
// TODO(andrewrynhard): Enable audit-log-maxbackup.
// TODO(andrewrynhard): Enable audit-log-maxsize.
func EnforceAuditingRequirements(cfg *kubeadmapi.InitConfiguration) error {
if err := ioutil.WriteFile("/var/etc/kubernetes/audit-policy.yaml", []byte(auditPolicy), 0400); err != nil {
return err
}
maxAge := int32(30)
cfg.FeatureGates["Auditing"] = true
cfg.ClusterConfiguration.AuditPolicyConfiguration.Path = "/etc/kubernetes/audit-policy.yaml"
cfg.ClusterConfiguration.AuditPolicyConfiguration.LogDir = "/etc/kubernetes/logs"
cfg.ClusterConfiguration.AuditPolicyConfiguration.LogMaxAge = &maxAge
return nil
}
// EnforceSecretRequirements enforces CIS requirements for secrets.
func EnforceSecretRequirements(cfg *kubeadmapi.InitConfiguration) error {
random := func(min, max int) int {
return rand.Intn(max-min) + min
}
var encryptionKeySecret string
seed := time.Now().Unix()
rand.Seed(seed)
for i := 0; i < 32; i++ {
n := random(0, 94)
start := "!"
encryptionKeySecret += string(start[0] + byte(n))
}
data := []byte(encryptionKeySecret)
str := base64.StdEncoding.EncodeToString(data)
aux := struct {
AESCBCEncryptionSecret string
}{
AESCBCEncryptionSecret: str,
}
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("/var/etc/kubernetes/encryptionconfig.yaml", buf.Bytes(), 0400); err != nil {
return err
}
cfg.APIServerExtraArgs["experimental-encryption-provider-config"] = "/etc/kubernetes/encryptionconfig.yaml"
vol := kubeadmapi.HostPathMount{
Name: "encryptionconfig",
HostPath: "/etc/kubernetes/encryptionconfig.yaml",
MountPath: "/etc/kubernetes/encryptionconfig.yaml",
Writable: false,
PathType: v1.HostPathFile,
}
cfg.APIServerExtraVolumes = append(cfg.APIServerExtraVolumes, vol)
return nil
}
// EnforceTLSRequirements enforces CIS requirements for TLS.
func EnforceTLSRequirements(cfg *kubeadmapi.InitConfiguration) error {
// nolint: lll
cfg.APIServerExtraArgs["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.
func EnforceAdmissionPluginsRequirements(cfg *kubeadmapi.InitConfiguration) error {
// nolint: lll
cfg.APIServerExtraArgs["enable-admission-plugins"] = "AlwaysPullImages,PodSecurityPolicy,DenyEscalatingExec,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.InitConfiguration) error {
cfg.APIServerExtraArgs["profiling"] = disabled
cfg.ControllerManagerExtraArgs["profiling"] = disabled
cfg.SchedulerExtraArgs["profiling"] = disabled
cfg.APIServerExtraArgs["service-account-lookup"] = "true"
return nil
}
// EnforceMasterRequirements enforces the CIS requirements for master nodes.
func EnforceMasterRequirements(cfg *kubeadmapi.InitConfiguration) 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
}
// EnforceWorkerRequirements enforces the CIS requirements for master nodes.
func EnforceWorkerRequirements(cfg *kubeadmapi.JoinConfiguration) error {
return nil
}
func ensureFieldsAreNotNil(cfg *kubeadmapi.InitConfiguration) {
if cfg.APIServerExtraArgs == nil {
cfg.APIServerExtraArgs = make(map[string]string)
}
if cfg.ControllerManagerExtraArgs == nil {
cfg.ControllerManagerExtraArgs = make(map[string]string)
}
if cfg.SchedulerExtraArgs == nil {
cfg.SchedulerExtraArgs = make(map[string]string)
}
if cfg.APIServerExtraVolumes == nil {
cfg.APIServerExtraVolumes = make([]kubeadmapi.HostPathMount, 0)
}
if cfg.FeatureGates == nil {
cfg.FeatureGates = make(map[string]bool)
}
}