Skip to content

Commit

Permalink
Add audit policy and log files to rke2 in cis mode (#511)
Browse files Browse the repository at this point in the history
* Add audit policy and log files to rke2 in cis mode

* fix the env variable for audit policy file

* inline the if condition

* unexport constant variable

* add none policy
  • Loading branch information
galal-hussein authored Nov 3, 2020
1 parent 6f91705 commit c535497
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 23 deletions.
6 changes: 6 additions & 0 deletions pkg/cli/cmds/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ var (
EnvVar: "RKE2_CIS_PROFILE",
Destination: &profile,
},
&cli.StringFlag{
Name: "audit-policy-file",
Usage: "Path to the file that defines the audit policy configuration",
EnvVar: "RKE2_AUDIT_POLICY_FILE",
Destination: &config.AuditPolicyFile,
},
}
)

Expand Down
76 changes: 61 additions & 15 deletions pkg/podexecutor/staticpod.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"io/ioutil"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"net/http"
"os"
"os/exec"
Expand All @@ -20,6 +21,7 @@ import (
"github.com/rancher/rke2/pkg/staticpod"
"github.com/sirupsen/logrus"
v1 "k8s.io/api/core/v1"
auditv1 "k8s.io/apiserver/pkg/apis/audit/v1"
"k8s.io/apiserver/pkg/authentication/authenticator"
"sigs.k8s.io/yaml"
)
Expand All @@ -34,12 +36,13 @@ var (
)

type StaticPodConfig struct {
ManifestsDir string
ImagesDir string
Images images.Images
CloudProvider *CloudProviderConfig
CISMode bool
DataDir string
ManifestsDir string
ImagesDir string
Images images.Images
CloudProvider *CloudProviderConfig
CISMode bool
DataDir string
AuditPolicyFile string
}

type CloudProviderConfig struct {
Expand Down Expand Up @@ -78,6 +81,7 @@ func (s *StaticPodConfig) KubeProxy(args []string) error {

// APIServer sets up the apiserver static pod once etcd is available, returning the authenticator and request handler.
func (s *StaticPodConfig) APIServer(ctx context.Context, etcdReady <-chan struct{}, args []string) (authenticator.Request, http.Handler, error) {
auditLogFile := filepath.Join(s.DataDir, "server/logs/audit.log")
if s.CloudProvider != nil {
args = append(args,
"--cloud-provider="+s.CloudProvider.Name,
Expand All @@ -86,12 +90,19 @@ func (s *StaticPodConfig) APIServer(ctx context.Context, etcdReady <-chan struct
if err := images.Pull(s.ImagesDir, "kube-apiserver", s.Images.KubeAPIServer); err != nil {
return nil, nil, err
}
args = append(args,
"--audit-log-path=/var/log/kube-audit/audit-log.json",
"--audit-log-maxage=30",
"--audit-log-maxbackup=10",
"--audit-log-maxsize=100",
)

if s.CISMode {
args = append(args,
"--audit-policy-file="+s.AuditPolicyFile,
"--audit-log-path="+auditLogFile,
"--audit-log-maxage=30",
"--audit-log-maxbackup=10",
"--audit-log-maxsize=100",
)
if err := writeDefaultPolicyFile(s.AuditPolicyFile); err != nil {
return nil, nil, err
}
}
auth, err := auth.FromArgs(args)
for i, arg := range args {
// This is an option k3s adds that does not exist upstream
Expand All @@ -107,9 +118,9 @@ func (s *StaticPodConfig) APIServer(ctx context.Context, etcdReady <-chan struct
Command: "kube-apiserver",
Args: args,
Image: s.Images.KubeAPIServer,
Dirs: ssldirs,
Dirs: append(ssldirs, filepath.Dir(auditLogFile)),
CPUMillis: 250,
Files: []string{etcdNameFile(s.DataDir)},
Files: []string{etcdNameFile(s.DataDir)},
})
})
return auth, http.NotFoundHandler(), err
Expand Down Expand Up @@ -284,4 +295,39 @@ func chownr(path string, uid, gid int) error {

func etcdNameFile(dataDir string) string {
return filepath.Join(dataDir, "server", "db", "etcd", "name")
}
}

func writeDefaultPolicyFile(policyFilePath string) error {
auditPolicy := auditv1.Policy{
TypeMeta: metav1.TypeMeta{
Kind: "Policy",
APIVersion: "audit.k8s.io/v1",
},
ObjectMeta: metav1.ObjectMeta{},
Rules: []auditv1.PolicyRule{
auditv1.PolicyRule{
Level: "None",
},
},
}
bytes, err := yaml.Marshal(auditPolicy)
if err != nil {
return err
}
return writeArgFile(policyFilePath, bytes)
}

func writeArgFile(path string, content []byte) error {
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0700); err != nil {
return err
}
if _, err := os.Stat(path); err == nil {
return nil
} else {
if !os.IsNotExist(err) {
return err
}
}
return ioutil.WriteFile(path, content, 0600)
}
24 changes: 17 additions & 7 deletions pkg/rke2/rke2.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,15 @@ type Config struct {
SystemDefaultRegistry string
CloudProviderName string
CloudProviderConfig string
AuditPolicyFile string
}

var cisMode bool

const CISProfile = "cis-1.5"
const (
CISProfile = "cis-1.5"
defaultAuditPolicyFile = "/etc/rancher/rke2/audit-policy.yaml"
)

func Server(clx *cli.Context, cfg Config) error {
if err := setup(clx, cfg); err != nil {
Expand Down Expand Up @@ -69,6 +73,11 @@ func setup(clx *cli.Context, cfg Config) error {
cisMode = clx.String("profile") == CISProfile
dataDir := clx.String("data-dir")

auditPolicyFile := clx.String("audit-policy-file")
if auditPolicyFile == "" {
auditPolicyFile = defaultAuditPolicyFile
}

images := images.New(cfg.SystemDefaultRegistry)
if err := defaults.Set(clx, images, dataDir); err != nil {
return err
Expand Down Expand Up @@ -106,12 +115,13 @@ func setup(clx *cli.Context, cfg Config) error {
}

sp := podexecutor.StaticPodConfig{
Images: images,
ImagesDir: agentImagesDir,
ManifestsDir: agentManifestsDir,
CISMode: cisMode,
CloudProvider: cpConfig,
DataDir: dataDir,
Images: images,
ImagesDir: agentImagesDir,
ManifestsDir: agentManifestsDir,
CISMode: cisMode,
CloudProvider: cpConfig,
DataDir: dataDir,
AuditPolicyFile: auditPolicyFile,
}
executor.Set(&sp)

Expand Down
2 changes: 1 addition & 1 deletion pkg/staticpod/staticpod.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ func readFiles(args []string) ([]string, error) {
for _, arg := range args {
parts := strings.SplitN(arg, "=", 2)
if len(parts) == 2 && strings.HasPrefix(parts[1], "/") {
if stat, err := os.Stat(parts[1]); err == nil && !stat.IsDir() {
if stat, err := os.Stat(parts[1]); err == nil && !stat.IsDir() && !strings.Contains(parts[1], "audit.log") {
files[parts[1]] = true

if parts[0] == "--kubeconfig" {
Expand Down

0 comments on commit c535497

Please sign in to comment.