diff --git a/pkg/hocon/hocon.go b/pkg/hocon/hocon.go index 17fe082..c88696c 100644 --- a/pkg/hocon/hocon.go +++ b/pkg/hocon/hocon.go @@ -73,3 +73,8 @@ func (k *KiltHocon) Runtime(info *kilt.TargetInfo) (*kilt.Runtime, error) { } return extractRuntime(config) } + +func (k *KiltHocon) Task() (*kilt.Task, error) { + config := configuration.ParseString(k.definition) + return extractTask(config) +} diff --git a/pkg/hocon/task.go b/pkg/hocon/task.go new file mode 100644 index 0000000..8e04459 --- /dev/null +++ b/pkg/hocon/task.go @@ -0,0 +1,16 @@ +package hocon + +import ( + "github.com/falcosecurity/kilt/pkg/kilt" + "github.com/go-akka/configuration" +) + +func extractTask(config *configuration.Config) (*kilt.Task, error) { + var task = new(kilt.Task) + + if config.HasPath("task.pid_mode") { + task.PidMode = config.GetString("task.pid_mode") + } + + return task, nil +} diff --git a/pkg/kilt/kilt.go b/pkg/kilt/kilt.go index 7fc9917..7b902ed 100644 --- a/pkg/kilt/kilt.go +++ b/pkg/kilt/kilt.go @@ -17,3 +17,7 @@ func (k *Kilt) Build(info *TargetInfo) (*Build, error) { func (k *Kilt) Runtime(info *TargetInfo) (*Runtime, error) { return k.definition.Runtime(info) } + +func (k *Kilt) Task() (*Task, error) { + return k.definition.Task() +} diff --git a/pkg/kilt/types.go b/pkg/kilt/types.go index 93f60a8..d8aa7b8 100644 --- a/pkg/kilt/types.go +++ b/pkg/kilt/types.go @@ -34,6 +34,10 @@ type Build struct { Resources []BuildResource } +type Task struct { + PidMode string // the only value is `task` right now +} + type RuntimeUpload struct { Payload *Payload Destination string @@ -70,4 +74,5 @@ type Payload struct { type LanguageInterface interface { Build(info *TargetInfo) (*Build, error) Runtime(info *TargetInfo) (*Runtime, error) + Task() (*Task, error) } diff --git a/runtimes/cloudformation/cfnpatcher/cfn_test.go b/runtimes/cloudformation/cfnpatcher/cfn_test.go index ebae41e..ac89b2f 100644 --- a/runtimes/cloudformation/cfnpatcher/cfn_test.go +++ b/runtimes/cloudformation/cfnpatcher/cfn_test.go @@ -58,6 +58,10 @@ var sidecarEnvTests = [...]string{ "sidecar_env/volumes_from", } +var taskPidModeTests = [...]string{ + "task_pid_mode/command", +} + const defaultConfig = ` build { entry_point: ["/kilt/run", "--", ${?original.metadata.captured_tag}] @@ -112,6 +116,25 @@ build { } ` +const taskPidModeConfig = ` +build { + entry_point: ["/kilt/run", "--", ${?original.metadata.captured_tag}] + command: [] ${?original.entry_point} ${?original.command} + mount: [ + { + name: "KiltImage" + image: "KILT:latest" + volumes: ["/kilt"] + entry_point: ["/kilt/wait"] + } + ] + capabilities: ["SYS_PTRACE"] +} +task { + pid_mode: "task" +} +` + func runTest(t *testing.T, name string, context context.Context, config Configuration) { fragment, err := ioutil.ReadFile("fixtures/" + name + ".json") if err != nil { @@ -197,6 +220,22 @@ func TestPatchingSidecarEnv(t *testing.T) { } } +func TestPatchingTask(t *testing.T) { + l := log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger() + + for _, testName := range taskPidModeTests { + t.Run(testName, func(t *testing.T) { + runTest(t, testName, l.WithContext(context.Background()), + Configuration{ + Kilt: taskPidModeConfig, + OptIn: false, + RecipeConfig: "{}", + UseRepositoryHints: false, + }) + }) + } +} + func TestPatchingForParameterizingEnvars(t *testing.T) { l := log.Output(zerolog.ConsoleWriter{Out: os.Stderr}).With().Caller().Logger() diff --git a/runtimes/cloudformation/cfnpatcher/fixtures/task_pid_mode/command.json b/runtimes/cloudformation/cfnpatcher/fixtures/task_pid_mode/command.json new file mode 100644 index 0000000..c2b20c7 --- /dev/null +++ b/runtimes/cloudformation/cfnpatcher/fixtures/task_pid_mode/command.json @@ -0,0 +1,29 @@ +{ + "Resources": { + "taskdef": { + "Type": "AWS::ECS::TaskDefinition", + "Properties": { + "RequiresCompatibilities": [ + "FARGATE" + ], + "Tags": [ + { + "Key": "antani", + "Value": "sbiribuda" + }, + { + "Key": "kiltinclude", + "Value": "itisignored" + } + ], + "ContainerDefinitions": [ + { + "Name": "app", + "Image": "busybox", + "Command": ["/bin/sh"] + } + ] + } + } + } +} \ No newline at end of file diff --git a/runtimes/cloudformation/cfnpatcher/fixtures/task_pid_mode/command.patched.json b/runtimes/cloudformation/cfnpatcher/fixtures/task_pid_mode/command.patched.json new file mode 100644 index 0000000..b3e2f94 --- /dev/null +++ b/runtimes/cloudformation/cfnpatcher/fixtures/task_pid_mode/command.patched.json @@ -0,0 +1,57 @@ +{ + "Resources": { + "taskdef": { + "Properties": { + "ContainerDefinitions": [ + { + "Command": [ + "/bin/sh" + ], + "EntryPoint": [ + "/kilt/run", + "--", + "" + ], + "Image": "busybox", + "LinuxParameters": { + "Capabilities": { + "Add": [ + "SYS_PTRACE" + ] + } + }, + "Name": "app", + "VolumesFrom": [ + { + "ReadOnly": true, + "SourceContainer": "KiltImage" + } + ] + }, + { + "EntryPoint": [ + "/kilt/wait" + ], + "Image": "KILT:latest", + "Name": "KiltImage" + } + ], + "RequiresCompatibilities": [ + "FARGATE" + ], + "Tags": [ + { + "Key": "antani", + "Value": "sbiribuda" + }, + { + "Key": "kiltinclude", + "Value": "itisignored" + } + ], + "PidMode": "task" + }, + "Type": "AWS::ECS::TaskDefinition" + } + } +} \ No newline at end of file diff --git a/runtimes/cloudformation/cfnpatcher/patcher.go b/runtimes/cloudformation/cfnpatcher/patcher.go index 6747691..9939081 100644 --- a/runtimes/cloudformation/cfnpatcher/patcher.go +++ b/runtimes/cloudformation/cfnpatcher/patcher.go @@ -44,6 +44,26 @@ func applyTaskDefinitionPatch(ctx context.Context, name string, resource *gabs.C successes := 0 containers := make(map[string]kilt.BuildResource) k := kiltapi.NewKiltFromHoconWithConfig(configuration.Kilt, configuration.RecipeConfig) + + taskPatch, err := k.Task() + if err != nil { + return nil, fmt.Errorf("could not get task definition patch: %w", err) + } + + if taskPatch.PidMode != "" { + if !resource.Exists("Properties") { + _, err := resource.Set(map[string]interface{}{}, "Properties") + if err != nil { + return nil, fmt.Errorf("could not add properties to task definition: %w", err) + } + } + + _, err = resource.Set(taskPatch.PidMode, "Properties", "PidMode") + if err != nil { + return nil, fmt.Errorf("could not set PidMode: %w", err) + } + } + if resource.Exists("Properties", "ContainerDefinitions") { for _, container := range resource.S("Properties", "ContainerDefinitions").Children() { info := extractContainerInfo(ctx, resource, name, container, configuration)