Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
36be27a
chore: add integration tests around Serverless ASM
RomainMuller Oct 23, 2023
1bb5c16
record new cases in the build scripts
RomainMuller Oct 23, 2023
daf14fb
update snapshots + some tuning
RomainMuller Oct 23, 2023
9ac55b1
improve normalization procedure
RomainMuller Oct 24, 2023
f3b3406
linter fix
RomainMuller Oct 24, 2023
4118cc7
better isolate integration test suites (improved specificity of pass/…
RomainMuller Oct 24, 2023
1574db9
improved doc in run.sh
RomainMuller Oct 24, 2023
6b31944
print out selected test suite when one has been selected...
RomainMuller Oct 24, 2023
5a35b8e
wait for 2 reports to have been emitted
RomainMuller Oct 24, 2023
74d2418
output raw logs on test failure
RomainMuller Oct 24, 2023
f4aac42
update default node layer version to latest
RomainMuller Oct 24, 2023
dd95ef5
add necessary node configuration, duh
RomainMuller Oct 24, 2023
e6f87e3
scope down except block
RomainMuller Oct 25, 2023
49464fc
reduce breaking changes
RomainMuller Oct 30, 2023
8a43602
Merge remote-tracking branch 'origin/main' into romain.marcadier/apps…
RomainMuller Oct 30, 2023
e453f72
improve prefix check
RomainMuller Oct 30, 2023
fbd5da4
re-normalize existing snapshots
RomainMuller Oct 30, 2023
46a9d1f
remove editor-inserted semicolons
RomainMuller Oct 31, 2023
d8a41c7
sort imports in python file
RomainMuller Oct 31, 2023
e8a2acc
Merge remote-tracking branch 'origin/main' into romain.marcadier/apps…
RomainMuller Oct 31, 2023
1a0df31
flat_map --> flatmap
RomainMuller Oct 31, 2023
273e07d
no raw log output, just print location
RomainMuller Oct 31, 2023
b2b7a5b
pin + update snapshots
RomainMuller Oct 31, 2023
f8d754c
update snapshots
RomainMuller Oct 31, 2023
293034e
remove tracer hostname from traces normalization
RomainMuller Oct 31, 2023
1339f0e
Merge remote-tracking branch 'origin/main' into romain.marcadier/apps…
RomainMuller Nov 3, 2023
151758e
Merge remote-tracking branch 'origin/main' into romain.marcadier/apps…
RomainMuller Nov 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions .github/workflows/serverless-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
architecture: [amd64, arm64]
suite: [metric, log, trace, appsec]
name: ${{ matrix.suite }} on ${{ matrix.architecture }}
steps:
- name: Checkout datadog-agent repository
uses: actions/checkout@v3
Expand All @@ -26,7 +29,7 @@ jobs:
node-version: 14

- name: Install Serverless Framework
run: sudo yarn global add serverless@^3.7.9 --prefix /usr/local
run: sudo yarn global add serverless@^3.36.0 --prefix /usr/local

- name: Checkout the datadog-lambda-extension repository
uses: actions/checkout@v3
Expand All @@ -44,6 +47,12 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Create raw logs directory
id: rawlogs
run: |-
DIR=$(mktemp -d)
echo "dir=${DIR}" >> $GITHUB_OUTPUT

- name: Run tests if AWS credentials are available
id: test
uses: nick-fields/retry@v2
Expand All @@ -54,15 +63,14 @@ jobs:
timeout_minutes: 45
max_attempts: 2
command: |
export RAWLOGS_DIR=$(mktemp -d)
echo "rawlogs=$RAWLOGS_DIR" >> $GITHUB_OUTPUT
RAWLOGS_DIR="${{ steps.rawlogs.outputs.dir }}/${{ matrix.architecture }}}"
cd go/src/github.com/DataDog/datadog-agent
ARCHITECTURE=${{ matrix.architecture }} RAWLOGS_DIR=$RAWLOGS_DIR \
./test/integration/serverless/run.sh
./test/integration/serverless/run.sh ${{ matrix.suite }}

- name: Archive raw logs
if: always()
uses: actions/upload-artifact@v3
with:
name: rawlogs
path: ${{ steps.test.outputs.rawlogs }}
path: ${{ steps.rawlogs.outputs.dir }}
70 changes: 70 additions & 0 deletions test/integration/serverless/appsec-payload.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"version": "1.0",
"resource": "/my/path",
"path": "/my/path",
"httpMethod": "GET",
"headers": {
"User-Agent": "Arachni/v1"
},
"multiValueHeaders": {
"User-Agent": [
"Arachni/v1"
]
},
"queryStringParameters": {
"sql": "UNION SELECT password FROM users"
},
"multiValueQueryStringParameters": {
"sql": [
"UNION SELECT password FROM users"
]
},
"requestContext": {
"accountId": "123456789012",
"apiId": "id",
"authorizer": {
"claims": null,
"scopes": null
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"extendedRequestId": "request-id",
"httpMethod": "GET",
"identity": {
"accessKey": null,
"accountId": null,
"caller": null,
"cognitoAuthenticationProvider": null,
"cognitoAuthenticationType": null,
"cognitoIdentityId": null,
"cognitoIdentityPoolId": null,
"principalOrgId": null,
"sourceIp": "192.0.2.1",
"user": null,
"userAgent": "user-agent",
"userArn": null,
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"path": "/my/path",
"protocol": "HTTP/1.1",
"requestId": "id=",
"requestTime": "04/Mar/2020:19:15:17 +0000",
"requestTimeEpoch": 1583349317135,
"resourceId": null,
"resourcePath": "/my/path",
"stage": "$default"
},
"pathParameters": null,
"stageVariables": null,
"body": "Hello from Lambda!",
"isBase64Encoded": false
}
2 changes: 1 addition & 1 deletion test/integration/serverless/build_csharp_functions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ else
CONVERTED_ARCH="x86_64"
fi

dotnet lambda package --configuration Release --framework net6.0 --verbosity quiet --output-package bin/Release/net6.0/handler.zip --function-architecture $CONVERTED_ARCH
PATH="${PATH}:${HOME}/.dotnet/tools" dotnet lambda package --configuration Release --framework net6.0 --verbosity quiet --output-package bin/Release/net6.0/handler.zip --function-architecture $CONVERTED_ARCH
2 changes: 1 addition & 1 deletion test/integration/serverless/build_go_functions.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

echo "Building Go functions for $ARCHITECTURE architecture"
go_test_dirs=("metric" "log" "timeout" "trace")
go_test_dirs=("metric" "log" "timeout" "trace" "appsec")
cd src
for go_dir in "${go_test_dirs[@]}"; do
env GOOS=linux CGO_ENABLED=0 GOARCH=$ARCHITECTURE go build -ldflags="-s -w" -o bin/"$go_dir" go-tests/"$go_dir"/main.go
Expand Down
4 changes: 2 additions & 2 deletions test/integration/serverless/build_java_functions.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/bin/bash

echo "Building Java Lambda Functions"
java_test_dirs=("metric" "trace" "log" "timeout" "error")
java_test_dirs=("metric" "trace" "log" "timeout" "error" "appsec")
cd src
for java_dir in "${java_test_dirs[@]}"; do
mvn package -q -f java-tests/"${java_dir}"/pom.xml
done
done
77 changes: 73 additions & 4 deletions test/integration/serverless/log_normalize.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import argparse
import json
import os
import re
import traceback
from typing import Union


def normalize_metrics(stage):
Expand Down Expand Up @@ -85,6 +88,7 @@ def sort__dd_tags_container(log):
tags = tags.split(',')
tags.sort()
log["tags"]["_dd.tags.container"] = ','.join(tags)
return log

return [
require(r'BEGINTRACE.*ENDTRACE'),
Expand All @@ -104,13 +108,44 @@ def sort__dd_tags_container(log):
replace(r'("otel.trace_id":")[a-zA-Z0-9]+"', r'\1null"'),
replace(r'("faas.execution":")[a-zA-Z0-9-]+"', r'\1null"'),
replace(r'("faas.instance":")[a-zA-Z0-9-/]+\[\$LATEST\][a-zA-Z0-9]+"', r'\1null"'),
replace(r'("_dd.tracer_hostname":)"\d{1,3}(?:.\d{1,3}){3}"+', r'\1"<redacted>"'),
replace(stage, 'XXXXXX'),
exclude(r'[ ]$'),
foreach(sort__dd_tags_container),
sort_by(trace_sort_key),
]


def normalize_appsec(stage):
def select__dd_appsec_json(log):
"""Selects the content of spans.*.meta.[_dd.appsec.json] which is
unfortunately an embedded JSON string value, so it's parsed out.
"""

entries = []

for chunk in log["chunks"]:
for span in chunk.get("spans") or []:
meta = span.get("meta") or {}
data = meta.get("_dd.appsec.json")
if data is None:
continue
parsed = json.loads(data, strict=False)
# The triggers may appear in any order, so we sort them by rule ID
parsed["triggers"] = sorted(parsed["triggers"], key=lambda x: x["rule"]["id"])
entries.append(parsed)

return entries

return [
require(r'BEGINTRACE.*ENDTRACE'),
exclude(r'BEGINTRACE'),
exclude(r'ENDTRACE'),
flatmap(select__dd_appsec_json),
replace(stage, 'XXXXXX'),
]


#####################
# BEGIN NORMALIZERS #
#####################
Expand Down Expand Up @@ -159,11 +194,28 @@ def _foreach(log):
logs = json.loads(log, strict=False)
for log_item in logs:
fn(log_item)
return json.dumps(logs)
return json.dumps(logs, sort_keys=True)

return _foreach


def flatmap(fn):
"""
Execute fn with each element of the list in order, flatten the results.
"""

def _flat_map(log):
logs = json.loads(log, strict=False)

mapped = []
for log_item in logs:
mapped.extend(fn(log_item))

return json.dumps(mapped, sort_keys=True)

return _flat_map


def sort_by(key):
"""
Sort the json entries using the given key function, requires the log string
Expand Down Expand Up @@ -211,12 +263,17 @@ def get_normalizers(typ, stage):
return normalize_logs(stage)
elif typ == 'traces':
return normalize_traces(stage)
elif typ == 'appsec':
return normalize_appsec(stage)
else:
raise ValueError(f'invalid type "{typ}"')


def format_json(log):
return json.dumps(json.loads(log, strict=False), indent=2)
try:
return json.dumps(json.loads(log, strict=False), indent=2)
except json.JSONDecodeError:
return log


def parse_args():
Expand All @@ -230,9 +287,21 @@ def parse_args():
if __name__ == '__main__':
try:
args = parse_args()

if args.logs.startswith('file:'):
with open(args.logs[5:], 'r') as f:
args.logs = f.read()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great addition!


print(normalize(args.logs, args.type, args.stage))
except Exception:
err = {"error": "normalization raised exception"}
except Exception as e:
err: dict[str, Union[str, list[str]]] = {
"error": "normalization raised exception",
}
# Unless explicitly specified, perform as it did historically
if os.environ.get("TRACEBACK") == "true":
err["message"] = str(e)
err["backtrace"] = traceback.format_exception(type(e), e, e.__traceback__)

err_json = json.dumps(err, indent=2)
print(err_json)
exit(1)
Loading