Skip to content

Commit

Permalink
feat(init): enforce CIS requirements (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewrynhard authored Nov 11, 2018
1 parent fc84b62 commit 0c41de9
Show file tree
Hide file tree
Showing 4 changed files with 244 additions and 0 deletions.
206 changes: 206 additions & 0 deletions src/initramfs/cmd/init/pkg/security/cis/cis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
package cis

import (
"bytes"
"encoding/base64"
"html/template"
"io/ioutil"
"math/rand"
"time"

"github.com/autonomy/dianemo/src/initramfs/cmd/init/pkg/constants"

"k8s.io/api/core/v1"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/scheme"
kubeadmapiv1beta1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta1"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
configutil "k8s.io/kubernetes/cmd/kubeadm/app/util/config"
)

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 *kubeadm.InitConfiguration) error {
if err := ioutil.WriteFile("/var/etc/kubernetes/audit-policy.yaml", []byte(auditPolicy), 0400); err != nil {
return err
}
maxAge := int32(30)
if cfg.FeatureGates == nil {
cfg.FeatureGates = make(map[string]bool)
}
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 *kubeadm.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 := kubeadm.HostPathMount{
Name: "encryptionconfig",
HostPath: "/etc/kubernetes/encryptionconfig.yaml",
MountPath: "/etc/kubernetes/encryptionconfig.yaml",
Writable: false,
PathType: v1.HostPathFile,
}
if cfg.APIServerExtraVolumes == nil {
cfg.APIServerExtraVolumes = make([]kubeadm.HostPathMount, 0)
}
cfg.APIServerExtraVolumes = append(cfg.APIServerExtraVolumes, vol)

return nil
}

// EnforceTLSRequirements enforces CIS requirements for TLS.
func EnforceTLSRequirements(cfg *kubeadm.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 PodSecurityPolicy.
// TODO(andrewrynhard): Enable EventRateLimit.
func EnforceAdmissionPluginsRequirements(cfg *kubeadm.InitConfiguration) error {
// nolint: lll
cfg.APIServerExtraArgs["enable-admission-plugins"] = "AlwaysPullImages,SecurityContextDeny,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 *kubeadm.InitConfiguration) error {
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)
}
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() error {
cfg := &kubeadmapiv1beta1.InitConfiguration{}
internalCfg, err := configutil.ConfigFileAndDefaultsToInternalConfig(constants.KubeadmConfig, cfg)
if err != nil {
return err
}

if err := EnforceAuditingRequirements(internalCfg); err != nil {
return err
}
if err := EnforceSecretRequirements(internalCfg); err != nil {
return err
}
if err := EnforceTLSRequirements(internalCfg); err != nil {
return err
}
if err := EnforceAdmissionPluginsRequirements(internalCfg); err != nil {
return err
}
if err := EnforceExtraRequirements(internalCfg); err != nil {
return err
}

b, err := configutil.MarshalInitConfigurationToBytes(internalCfg, kubeadmapiv1beta1.SchemeGroupVersion)
if err != nil {
return err
}

if err := ioutil.WriteFile(constants.KubeadmConfig, b, 0600); err != nil {
return err
}

return nil
}

// EnforceWorkerRequirements enforces the CIS requirements for master nodes.
func EnforceWorkerRequirements() error {
cfg := &kubeadmapiv1beta1.JoinConfiguration{}
internalCfg, err := configutil.JoinConfigFileAndDefaultsToInternalConfig(constants.KubeadmConfig, cfg)
if err != nil {
return err
}

b, err := kubeadmutil.MarshalToYamlForCodecs(internalCfg, kubeadm.SchemeGroupVersion, scheme.Codecs)
if err != nil {
return err
}

if err := ioutil.WriteFile(constants.KubeadmConfig, b, 0600); err != nil {
return err
}

return nil
}
11 changes: 11 additions & 0 deletions src/initramfs/cmd/init/pkg/system/services/kubeadm.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/autonomy/dianemo/src/initramfs/cmd/init/pkg/constants"
"github.com/autonomy/dianemo/src/initramfs/cmd/init/pkg/security/cis"
"github.com/autonomy/dianemo/src/initramfs/cmd/init/pkg/system/conditions"
"github.com/autonomy/dianemo/src/initramfs/cmd/init/pkg/system/runner"
"github.com/autonomy/dianemo/src/initramfs/cmd/init/pkg/system/runner/containerd"
Expand Down Expand Up @@ -80,6 +81,16 @@ func (k *Kubeadm) PreFunc(data *userdata.UserData) (err error) {
return
}

if data.Services.Kubeadm.Init != nil && data.Services.Kubeadm.Init.Bootstrap {
if err := cis.EnforceMasterRequirements(); err != nil {
return err
}
} else {
if err := cis.EnforceWorkerRequirements(); err != nil {
return err
}
}

return nil
}

Expand Down
9 changes: 9 additions & 0 deletions src/initramfs/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ require (
github.com/pkg/errors v0.8.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/sirupsen/logrus v1.0.6 // indirect
github.com/spf13/afero v1.1.2 // indirect
github.com/spf13/cobra v0.0.3
github.com/spf13/pflag v1.0.1 // indirect
github.com/stretchr/testify v1.2.2 // indirect
Expand All @@ -74,6 +75,14 @@ require (
gopkg.in/yaml.v2 v2.1.1
gotest.tools v2.1.0+incompatible // indirect
k8s.io/api v0.0.0-20181031211151-1455c336c32a
k8s.io/apiextensions-apiserver v0.0.0-20181110112449-a6e0648e729a // indirect
k8s.io/apimachinery v0.0.0-20181031012033-2e0dc82819fd
k8s.io/apiserver v0.0.0-20181110111630-c45349c92333 // indirect
k8s.io/client-go v9.0.0+incompatible
k8s.io/cluster-bootstrap v0.0.0-20181108060158-bf9d13f1fbeb // indirect
k8s.io/kube-openapi v0.0.0-20181109181836-c59034cc13d5 // indirect
k8s.io/kube-proxy v0.0.0-20181108055616-8eeec43ca7b5 // indirect
k8s.io/kubelet v0.0.0-20181108055742-1ff588f76017 // indirect
k8s.io/kubernetes v1.13.0-alpha.3
k8s.io/utils v0.0.0-20181102055113-1bd4f387aa67 // indirect
)
18 changes: 18 additions & 0 deletions src/initramfs/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.0.6 h1:hcP1GmhGigz/O7h1WVUM5KklBp1JoNS9FggWKdj/j3s=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
Expand Down Expand Up @@ -146,7 +148,23 @@ gotest.tools v2.1.0+incompatible h1:5USw7CrJBYKqjg9R7QlA6jzqZKEAtvW82aNmsxxGPxw=
gotest.tools v2.1.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
k8s.io/api v0.0.0-20181031211151-1455c336c32a h1:FpAv2ADbN/Hf0lCdblM6VhOE1a2JYUzv44kENG1aCdI=
k8s.io/api v0.0.0-20181031211151-1455c336c32a/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
k8s.io/apiextensions-apiserver v0.0.0-20181110112449-a6e0648e729a h1:enG3CUxMMMQEiPEyuxhX0DLMUjMGgm5AV4hPXaRJoR8=
k8s.io/apiextensions-apiserver v0.0.0-20181110112449-a6e0648e729a/go.mod h1:IxkesAMoaCRoLrPJdZNZUQp9NfZnzqaVzLhb2VEQzXE=
k8s.io/apimachinery v0.0.0-20181031012033-2e0dc82819fd h1:rzRDbWmTXaWr6SDV9caWzwAUPSfvgwX6j89LBnq/ycw=
k8s.io/apimachinery v0.0.0-20181031012033-2e0dc82819fd/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/apiserver v0.0.0-20181110111630-c45349c92333 h1:vJS6O3laUr6RjawTCj6mGtWAtSZIj8UJHHdJkVoq8iY=
k8s.io/apiserver v0.0.0-20181110111630-c45349c92333/go.mod h1:6bqaTSOSJavUIXUtfaR9Os9JtTCm8ZqH2SUl2S60C4w=
k8s.io/client-go v9.0.0+incompatible h1:/PdJjifJTjMFe0G4ESclZDcwF1+bFePTJ2xf+MXjcvs=
k8s.io/client-go v9.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/cluster-bootstrap v0.0.0-20181108060158-bf9d13f1fbeb h1:z/dxZqygnYDAliIMBasYmAl2rprSkZG7m63O/HRYnas=
k8s.io/cluster-bootstrap v0.0.0-20181108060158-bf9d13f1fbeb/go.mod h1:iBSm2nwo3OaiuW8VDvc3ySDXK5SKfUrxwPvBloKG7zg=
k8s.io/kube-openapi v0.0.0-20181109181836-c59034cc13d5 h1:MH8SvyTlIiLt8b1oHy4Dtp1zPpLGp6lTOjvfzPTkoQE=
k8s.io/kube-openapi v0.0.0-20181109181836-c59034cc13d5/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/kube-proxy v0.0.0-20181108055616-8eeec43ca7b5 h1:tM7Kt5AXss8IHvgPHoff1hyJHxLk3DEI8zotPbGcS6g=
k8s.io/kube-proxy v0.0.0-20181108055616-8eeec43ca7b5/go.mod h1:wYVhqAVLhGBLbGzgb9GsBakzIddI81JxSUHANQvzZZs=
k8s.io/kubelet v0.0.0-20181108055742-1ff588f76017 h1:Df4PBcfWHh/oi4pHC+G7mbJEKtbukYl34RDo12caUxA=
k8s.io/kubelet v0.0.0-20181108055742-1ff588f76017/go.mod h1:m6JOtVhjgs4GGnzhPpXuNF9VG+IjARwo/dHCNw4+QDA=
k8s.io/kubernetes v1.13.0-alpha.3 h1:vk043/s8SX9P545f65zH/uMJoXqGQq5WVpVzDqx80W8=
k8s.io/kubernetes v1.13.0-alpha.3/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20181102055113-1bd4f387aa67 h1:+kBMW7D4cSYIhPz0fVs6NRp5QILMz6+65ec4kWJOoXs=
k8s.io/utils v0.0.0-20181102055113-1bd4f387aa67/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=

0 comments on commit 0c41de9

Please sign in to comment.