diff --git a/pkg/cli/cmds/root.go b/pkg/cli/cmds/root.go index 466050313a..b1c98626ac 100644 --- a/pkg/cli/cmds/root.go +++ b/pkg/cli/cmds/root.go @@ -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, + }, } ) diff --git a/pkg/podexecutor/staticpod.go b/pkg/podexecutor/staticpod.go index 78fdb358fa..a0188971da 100644 --- a/pkg/podexecutor/staticpod.go +++ b/pkg/podexecutor/staticpod.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "io/ioutil" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "net/http" "os" "os/exec" @@ -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" ) @@ -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 { @@ -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, @@ -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 @@ -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 @@ -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") -} \ No newline at end of file +} + +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) +} diff --git a/pkg/rke2/rke2.go b/pkg/rke2/rke2.go index 20e8fa2dab..f73a731df4 100644 --- a/pkg/rke2/rke2.go +++ b/pkg/rke2/rke2.go @@ -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 { @@ -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 @@ -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) diff --git a/pkg/staticpod/staticpod.go b/pkg/staticpod/staticpod.go index 5de9076f46..11598816d3 100644 --- a/pkg/staticpod/staticpod.go +++ b/pkg/staticpod/staticpod.go @@ -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" {