Skip to content

Commit 24cbc8a

Browse files
authored
feat: configure Fargate instrumentation log group (#188)
1 parent 0289217 commit 24cbc8a

File tree

5 files changed

+190
-4
lines changed

5 files changed

+190
-4
lines changed

sysdig/data_source_sysdig_fargate_ECS_test.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ func TestECStransformation(t *testing.T) {
8282
RecipeConfig: string(jsonConf),
8383
}
8484

85-
patchedOutput, err := patchFargateTaskDefinition(context.Background(), string(inputfile), kiltConfig)
85+
patchedOutput, err := patchFargateTaskDefinition(context.Background(), string(inputfile), kiltConfig, nil)
8686
if err != nil {
8787
t.Fatalf("Cannot execute PatchFargateTaskDefinition : %v", err.Error())
8888
}
@@ -144,10 +144,33 @@ func TestTransform(t *testing.T) {
144144
}
145145

146146
inputContainerDefinition, _ := ioutil.ReadFile("testfiles/" + testName + ".json")
147-
patched, _ := patchFargateTaskDefinition(context.Background(), string(inputContainerDefinition), kiltConfig)
147+
patched, _ := patchFargateTaskDefinition(context.Background(), string(inputContainerDefinition), kiltConfig, nil)
148148
expectedContainerDefinition, _ := ioutil.ReadFile("testfiles/" + testName + "_expected.json")
149149

150150
sortAndCompare(t, expectedContainerDefinition, []byte(*patched))
151151
})
152152
}
153153
}
154+
155+
func TestLogGroup(t *testing.T) {
156+
jsonConfig, _ := json.Marshal(testKiltDefinition)
157+
kiltConfig := &cfnpatcher.Configuration{
158+
Kilt: agentinoKiltDefinition,
159+
ImageAuthSecret: "image_auth_secret",
160+
OptIn: false,
161+
UseRepositoryHints: true,
162+
RecipeConfig: string(jsonConfig),
163+
}
164+
165+
logConfig := map[string]interface{}{
166+
"group": "test_log_group",
167+
"stream_prefix": "test_prefix",
168+
"region": "test_region",
169+
}
170+
171+
inputContainerDefinition, _ := ioutil.ReadFile("testfiles/fargate_log_group.json")
172+
patched, _ := patchFargateTaskDefinition(context.Background(), string(inputContainerDefinition), kiltConfig, logConfig)
173+
expectedContainerDefinition, _ := ioutil.ReadFile("testfiles/fargate_log_group_expected.json")
174+
175+
sortAndCompare(t, expectedContainerDefinition, []byte(*patched))
176+
}

sysdig/data_source_sysdig_fargate_workload_agent.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ import (
77
"errors"
88
"fmt"
99

10+
"github.com/Jeffail/gabs/v2"
11+
"github.com/aws/aws-sdk-go/aws"
12+
"github.com/aws/aws-sdk-go/service/ecs"
1013
"github.com/falcosecurity/kilt/runtimes/cloudformation/cfnpatcher"
1114
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1215
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
@@ -78,6 +81,31 @@ func dataSourceSysdigFargateWorkloadAgent() *schema.Resource {
7881
Description: "the collector port to connect to",
7982
Optional: true,
8083
},
84+
"log_configuration": {
85+
Type: schema.TypeSet,
86+
MaxItems: 1,
87+
Description: "configuration for instrumentation logs using the awslogs driver",
88+
Optional: true,
89+
Elem: &schema.Resource{
90+
Schema: map[string]*schema.Schema{
91+
"group": {
92+
Type: schema.TypeString,
93+
Description: "The log group where the awslogs driver will send log streams",
94+
Required: true,
95+
},
96+
"stream_prefix": {
97+
Type: schema.TypeString,
98+
Description: "Prefix for the instrumentation log stream",
99+
Required: true,
100+
},
101+
"region": {
102+
Type: schema.TypeString,
103+
Description: "Region for the log group",
104+
Required: true,
105+
},
106+
},
107+
},
108+
},
81109
"output_container_definitions": {
82110
Type: schema.TypeString,
83111
Computed: true,
@@ -100,8 +128,45 @@ type cfnStack struct {
100128
Resources map[string]cfnResource `json:"Resources"`
101129
}
102130

131+
// fargatePostKiltModifications performs any additional changes needed after
132+
// Kilt has applied it's transformations
133+
func fargatePostKiltModifications(patchedBytes []byte, logConfig map[string]interface{}) ([]byte, error) {
134+
if len(logConfig) == 0 {
135+
// no log configuration provided, nothing to do
136+
return patchedBytes, nil
137+
}
138+
139+
containers, err := gabs.ParseJSON(patchedBytes)
140+
if err != nil {
141+
return nil, fmt.Errorf("failed to parse containers for post-processing: %s", err)
142+
}
143+
144+
for _, container := range containers.Children() {
145+
containerName, ok := container.Search("Name").Data().(string)
146+
if !ok || containerName != "SysdigInstrumentation" {
147+
// not the instrumentation container, skip it
148+
continue
149+
}
150+
151+
awsLogConfig := &ecs.LogConfiguration{
152+
LogDriver: aws.String("awslogs"),
153+
Options: map[string]*string{
154+
"awslogs-group": aws.String(logConfig["group"].(string)),
155+
"awslogs-stream-prefix": aws.String(logConfig["stream_prefix"].(string)),
156+
"awslogs-region": aws.String(logConfig["region"].(string)),
157+
},
158+
}
159+
_, err = container.Set(awsLogConfig, "LogConfiguration")
160+
if err != nil {
161+
return nil, fmt.Errorf("failed to set log configuration: %s", err)
162+
}
163+
}
164+
165+
return containers.Bytes(), nil
166+
}
167+
103168
// PatchFargateTaskDefinition modifies the container definitions
104-
func patchFargateTaskDefinition(ctx context.Context, containerDefinitions string, kiltConfig *cfnpatcher.Configuration) (patched *string, err error) {
169+
func patchFargateTaskDefinition(ctx context.Context, containerDefinitions string, kiltConfig *cfnpatcher.Configuration, logConfig map[string]interface{}) (patched *string, err error) {
105170
var cdefs []map[string]interface{}
106171
err = json.Unmarshal([]byte(containerDefinitions), &cdefs)
107172
if err != nil {
@@ -158,6 +223,8 @@ func patchFargateTaskDefinition(ctx context.Context, containerDefinitions string
158223
return nil, err
159224
}
160225

226+
patchedBytes, err = fargatePostKiltModifications(patchedBytes, logConfig)
227+
161228
patchedString := string(patchedBytes)
162229
return &patchedString, nil
163230
}
@@ -196,7 +263,12 @@ func dataSourceSysdigFargateWorkloadAgentRead(ctx context.Context, d *schema.Res
196263

197264
containerDefinitions := d.Get("container_definitions").(string)
198265

199-
outputContainerDefinitions, err := patchFargateTaskDefinition(ctx, containerDefinitions, kiltConfig)
266+
logConfig := map[string]interface{}{}
267+
if logConfiguration := d.Get("log_configuration").(*schema.Set).List(); len(logConfiguration) > 0 {
268+
logConfig = logConfiguration[0].(map[string]interface{})
269+
}
270+
271+
outputContainerDefinitions, err := patchFargateTaskDefinition(ctx, containerDefinitions, kiltConfig, logConfig)
200272
if err != nil {
201273
return diag.Errorf("Error applying configuration patch: %v", err.Error())
202274
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[
2+
{
3+
"name": "test",
4+
"image": "test_image:latest",
5+
"entryPoint": [
6+
"/bin/test"
7+
],
8+
"command": [
9+
"test",
10+
"--test-arg",
11+
"test-arg-value"
12+
]
13+
}
14+
]
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[
2+
{
3+
"name": "test",
4+
"Image": "test_image:latest",
5+
"EntryPoint": [
6+
"/opt/draios/bin/instrument"
7+
],
8+
"Command": [
9+
"/bin/test",
10+
"test",
11+
"--test-arg",
12+
"test-arg-value"
13+
],
14+
"Environment": [
15+
{
16+
"Name": "SYSDIG_ORCHESTRATOR_PORT",
17+
"Value": "orchestrator_port"
18+
},
19+
{
20+
"Name": "SYSDIG_COLLECTOR",
21+
"Value": "collector_host"
22+
},
23+
{
24+
"Name": "SYSDIG_COLLECTOR_PORT",
25+
"Value": "collector_port"
26+
},
27+
{
28+
"Name": "SYSDIG_ACCESS_KEY",
29+
"Value": "sysdig_access_key"
30+
},
31+
{
32+
"Name": "SYSDIG_LOGGING",
33+
"Value": ""
34+
},
35+
{
36+
"Name": "SYSDIG_ORCHESTRATOR",
37+
"Value": "orchestrator_host"
38+
}
39+
],
40+
"LinuxParameters": {
41+
"Capabilities": {
42+
"Add": [
43+
"SYS_PTRACE"
44+
]
45+
}
46+
},
47+
"VolumesFrom": [
48+
{
49+
"ReadOnly": true,
50+
"SourceContainer": "SysdigInstrumentation"
51+
}
52+
]
53+
},
54+
{
55+
"EntryPoint": [
56+
"/opt/draios/bin/logwriter"
57+
],
58+
"Image": "workload_agent_image",
59+
"Name": "SysdigInstrumentation",
60+
"RepositoryCredentials": {
61+
"CredentialsParameter": "image_auth_secret"
62+
},
63+
"LogConfiguration": {
64+
"LogDriver": "awslogs",
65+
"Options": {
66+
"awslogs-group": "test_log_group",
67+
"awslogs-stream-prefix": "test_prefix",
68+
"awslogs-region": "test_region"
69+
},
70+
"SecretOptions": null
71+
}
72+
}
73+
]

website/docs/d/fargate_workload_agent.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ data "sysdig_fargate_workload_agent" "instrumented_containers" {
3939
* `orchestrator_port` - (Optional) The orchestrator port to connect to.
4040
* `collector_host` - (Optional) The collector host to connect to.
4141
* `collector_port` - (Optional) The collector port to connect to.
42+
* `log_configuration` - (Optional) Configuration for the awslogs driver on the instrumentation container. All three values must be specified if instrumentation logging is desired:
43+
* `group` - The name of the existing log group for instrumentation logs
44+
* `stream_prefix` - Prefix for the instrumentation log stream
45+
* `region` - The AWS region where the target log group resides
4246

4347

4448
## Attributes Reference

0 commit comments

Comments
 (0)