Skip to content

Commit

Permalink
Syscalls enforcement a la seccomp (#29583)
Browse files Browse the repository at this point in the history
  • Loading branch information
mftoure authored Sep 27, 2024
1 parent 2588d20 commit 6d5f968
Show file tree
Hide file tree
Showing 5 changed files with 880 additions and 0 deletions.
88 changes: 88 additions & 0 deletions cmd/security-agent/subcommands/runtime/activity_dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package runtime

import (
"encoding/json"
"fmt"
"os"

Expand Down Expand Up @@ -60,6 +61,7 @@ func activityDumpCommands(globalParams *command.GlobalParams) []*cobra.Command {
activityDumpCmd.AddCommand(stopCommands(globalParams)...)
activityDumpCmd.AddCommand(diffCommands(globalParams)...)
activityDumpCmd.AddCommand(activityDumpToWorkloadPolicyCommands(globalParams)...)
activityDumpCmd.AddCommand(activityDumpToSeccompProfileCommands(globalParams)...)
return []*cobra.Command{activityDumpCmd}
}

Expand Down Expand Up @@ -775,3 +777,89 @@ func activityDumpToWorkloadPolicy(_ log.Component, _ config.Component, _ secrets

return nil
}

type activityDumpToSeccompProfileCliParams struct {
*command.GlobalParams

input string
output string
format string
}

func activityDumpToSeccompProfileCommands(globalParams *command.GlobalParams) []*cobra.Command {
cliParams := &activityDumpToSeccompProfileCliParams{
GlobalParams: globalParams,
}

ActivityDumpToSeccompProfileCmd := &cobra.Command{
Use: "workload-seccomp",
Hidden: true,
Short: "convert an activity dump to a seccomp profile",
RunE: func(_ *cobra.Command, _ []string) error {
return fxutil.OneShot(activityDumpToSeccompProfile,
fx.Supply(cliParams),
fx.Supply(core.BundleParams{
ConfigParams: config.NewSecurityAgentParams(globalParams.ConfigFilePaths),
SecretParams: secrets.NewEnabledParams(),
LogParams: log.ForOneShot(command.LoggerName, "info", true)}),
core.Bundle(),
)
},
}

ActivityDumpToSeccompProfileCmd.Flags().StringVar(
&cliParams.input,
"input",
"",
"path to the activity-dump file",
)

ActivityDumpToSeccompProfileCmd.Flags().StringVar(
&cliParams.output,
"output",
"",
"path to the generated seccomp profile file",
)

ActivityDumpToSeccompProfileCmd.Flags().StringVar(
&cliParams.format,
"format",
"json",
"format of the generated seccomp profile file",
)

return []*cobra.Command{ActivityDumpToSeccompProfileCmd}
}
func activityDumpToSeccompProfile(_ log.Component, _ config.Component, _ secrets.Component, args *activityDumpToSeccompProfileCliParams) error {

ads, err := dump.LoadActivityDumpsFromFiles(args.input)
if err != nil {
return err
}

seccompProfile := dump.GenerateSeccompProfile(ads)

var b []byte
if args.format == "yaml" {
b, err = yaml.Marshal(seccompProfile)
} else {
b, err = json.Marshal(seccompProfile)
}

if err != nil {
return err
}

output := os.Stdout
if args.output != "" && args.output != "-" {
output, err = os.Create(args.output)
if err != nil {
return err
}
defer output.Close()
}

fmt.Fprint(output, string(b))

return nil
}
8 changes: 8 additions & 0 deletions cmd/security-agent/subcommands/runtime/activity_dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,11 @@ func TestActivityDumpToWorkloadPolicyCommand(t *testing.T) {
activityDumpToWorkloadPolicy,
func() {})
}

func TestActivityDumpToSeccompProfileCommand(t *testing.T) {
fxutil.TestOneShotSubcommand(t,
Commands(&command.GlobalParams{}),
[]string{"runtime", "activity-dump", "workload-seccomp", "--input", "file", "--output", "file"},
activityDumpToSeccompProfile,
func() {})
}
16 changes: 16 additions & 0 deletions pkg/security/security_profile/activity_tree/activity_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -917,3 +917,19 @@ func (at *ActivityTree) ExtractPaths() (map[string][]string, map[string][]string

return fimPathsperExecPath, execAndParent
}

// ExtractSyscalls return the syscalls present in an activity tree
func (at *ActivityTree) ExtractSyscalls(arch string) []string {
var syscalls []string

at.visit(func(processNode *ProcessNode) {
for _, s := range processNode.Syscalls {
sycallKey := utils.SyscallKey{Arch: arch, ID: s}
syscall, ok := utils.Syscalls[sycallKey]
if ok {
syscalls = append(syscalls, syscall)
}
}
})
return syscalls
}
35 changes: 35 additions & 0 deletions pkg/security/security_profile/dump/activity_dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,18 @@ type SECLRuleOpts struct {
FIM bool
}

// SeccompProfile represents a Seccomp profile
type SeccompProfile struct {
DefaultAction string `yaml:"defaultAction" json:"defaultAction"`
Syscalls []SyscallPolicy `yaml:"syscalls" json:"syscalls"`
}

// SyscallPolicy represents the policy in a seccomp profile
type SyscallPolicy struct {
Names []string `yaml:"names" json:"names"`
Action string `yaml:"action" json:"action"`
}

// NewActivityDumpLoadConfig returns a new instance of ActivityDumpLoadConfig
func NewActivityDumpLoadConfig(evt []model.EventType, timeout time.Duration, waitListTimeout time.Duration, rate int, start time.Time, resolver *stime.Resolver) *model.ActivityDumpLoadConfig {
adlc := &model.ActivityDumpLoadConfig{
Expand Down Expand Up @@ -1023,3 +1035,26 @@ func GenerateRules(ads []*ActivityDump, opts SECLRuleOpts) []*rules.RuleDefiniti
}
return ruleDefs
}

// GenerateSeccompProfile returns a seccomp a profile
func GenerateSeccompProfile(ads []*ActivityDump) *SeccompProfile {

sp := &SeccompProfile{
DefaultAction: "SCMP_ACT_KILL",
Syscalls: []SyscallPolicy{
{
Action: "SCMP_ACT_ALLOW",
Names: []string{},
},
},
}

for _, ad := range ads {
syscalls := ad.ActivityTree.ExtractSyscalls(ad.Metadata.Arch)
sp.Syscalls[0].Names = append(sp.Syscalls[0].Names, syscalls...)

}
slices.Sort(sp.Syscalls[0].Names)
sp.Syscalls[0].Names = slices.Compact(sp.Syscalls[0].Names)
return sp
}
Loading

0 comments on commit 6d5f968

Please sign in to comment.