Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Binary file added .aws-lambda-rie/aws-lambda-rie
Binary file not shown.
2 changes: 1 addition & 1 deletion cmd/opg-s3-antivirus-update/freshclam.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
type Freshclam struct{}

func (c *Freshclam) Update() error {
cmd := exec.Command("./bin/freshclam")
cmd := exec.Command("freshclam", "--config-file=/etc/freshclam.conf")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

For some reason the config file needs to be specified now, even though it's the default location. No harm in being specific though I guess 🤷🏽


cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
Expand Down
7 changes: 4 additions & 3 deletions cmd/opg-s3-antivirus-update/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,10 @@ func (l *Lambda) uploadDefinitions() error {
}

input := &s3manager.UploadInput{
Bucket: aws.String(l.bucket),
Key: aws.String(key),
Body: file,
Bucket: aws.String(l.bucket),
Key: aws.String(key),
Body: file,
ServerSideEncryption: aws.String("AES256"),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is required by our S3 policy

}

if _, err := l.uploader.Upload(input); err != nil {
Expand Down
10 changes: 5 additions & 5 deletions cmd/opg-s3-antivirus-update/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type mockUploader struct {
}

func (m *mockUploader) Upload(input *s3manager.UploadInput, options ...func(*s3manager.Uploader)) (*s3manager.UploadOutput, error) {
args := m.Called(*input.Bucket, *input.Key, input.Body)
args := m.Called(*input.Bucket, *input.Key, input.Body, *input.ServerSideEncryption)
return nil, args.Error(0)
}

Expand Down Expand Up @@ -85,7 +85,7 @@ func TestHandleEvent(t *testing.T) {
On("Update").Return(nil)

uploader.
On("Upload", "a-bucket", "a", mock.Anything).
On("Upload", "a-bucket", "a", mock.Anything, "AES256").
Run(func(args mock.Arguments) {
r := args[2].(io.Reader)
data, _ := io.ReadAll(r)
Expand All @@ -94,7 +94,7 @@ func TestHandleEvent(t *testing.T) {
Return(nil)

uploader.
On("Upload", "a-bucket", "b", mock.Anything).
On("Upload", "a-bucket", "b", mock.Anything, "AES256").
Run(func(args mock.Arguments) {
r := args[2].(io.Reader)
data, _ := io.ReadAll(r)
Expand Down Expand Up @@ -147,11 +147,11 @@ func TestHandleEventFirstRun(t *testing.T) {
On("Update").Return(nil)

uploader.
On("Upload", "a-bucket", "a", mock.Anything).
On("Upload", "a-bucket", "a", mock.Anything, "AES256").
Return(nil)

uploader.
On("Upload", "a-bucket", "b", mock.Anything).
On("Upload", "a-bucket", "b", mock.Anything, "AES256").
Return(nil)

response, err := l.HandleEvent(Event{})
Expand Down
2 changes: 1 addition & 1 deletion cmd/opg-s3-antivirus/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type ClamAvScanner struct {
}

func (s *ClamAvScanner) ScanFile(path string) (bool, error) {
cmd := exec.Command("./bin/clamscan", "--stdout", "-d", "/tmp/clamav", path)
cmd := exec.Command("clamscan", "--stdout", "-d", "/tmp/clamav", path)

cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
Expand Down
8 changes: 7 additions & 1 deletion docker/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ services:
ANTIVIRUS_TAG_VALUE_PASS: ok
ANTIVIRUS_TAG_VALUE_FAIL: infected
ANTIVIRUS_DEFINITIONS_BUCKET: virus-definitions
volumes:
- "../.aws-lambda-rie:/aws-lambda"
entrypoint: /aws-lambda/aws-lambda-rie /var/task/main

antivirus-update-function:
image: antivirus-update-function:latest
Expand All @@ -28,6 +31,9 @@ services:
AWS_ACCESS_KEY_ID: localstack
AWS_SECRET_ACCESS_KEY: localstack
ANTIVIRUS_DEFINITIONS_BUCKET: virus-definitions
volumes:
- "../.aws-lambda-rie:/aws-lambda"
entrypoint: /aws-lambda/aws-lambda-rie /var/task/main

localstack:
image: localstack/localstack:0.13
Expand All @@ -42,7 +48,7 @@ services:
SERVICES: s3,lambda
LAMBDA_EXECUTOR: docker
LAMBDA_REMOVE_CONTAINERS: "true"
LAMBDA_FORWARD_URL: http://antivirus-function:9001
LAMBDA_FORWARD_URL: http://antivirus-function:8080
DOCKER_HOST: unix:///var/run/docker.sock
healthcheck:
test: ["CMD-SHELL", "curl http://localhost:4566 || exit 1"]
Expand Down
31 changes: 7 additions & 24 deletions docker/opg-s3-antivirus-update/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
FROM amazonlinux:2 AS build-clamav

RUN yum update -y &&\
amazon-linux-extras install epel -y &&\
yum install clamav clamd -y

FROM golang:1.17.6 AS build-env
FROM golang:1.17.7 AS build-env

WORKDIR /app

Expand All @@ -17,24 +11,13 @@ COPY . .

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -o /go/bin/main ./cmd/opg-s3-antivirus-update

FROM lambci/lambda:go1.x
FROM alpine:3.15

ENV DOCKER_LAMBDA_WATCH=1
ENV DOCKER_LAMBDA_STAY_OPEN=1
ENV AWS_LAMBDA_FUNCTION_HANDLER=main
ENV LD_LIBRARY_PATH=/var/task/lib
RUN apk update && apk add --no-cache clamav

COPY ./freshclam.conf /etc
COPY --from=build-clamav /usr/bin/freshclam /var/task/bin/freshclam
COPY --from=build-clamav /usr/lib64/libclam* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libfreshclam* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libgnutls* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libhogweed* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libjson* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libltdl* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libnettle* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libpcre* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libprelude* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libtasn1* /var/task/lib/
RUN mkdir -p /tmp/clamav && chown -R clamav:clamav /tmp/clamav

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

/tmp is overwritten by Lambda in production but this is necessary locally, effectively emulating that behaviour


COPY ./freshclam.conf /etc
COPY --from=build-env /go/bin/main /var/task/main

ENTRYPOINT [ "/var/task/main" ]
27 changes: 5 additions & 22 deletions docker/opg-s3-antivirus/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
FROM amazonlinux:2 AS build-clamav

RUN yum update -y &&\
amazon-linux-extras install epel -y &&\
yum install clamav clamd -y

FROM golang:1.17.6 AS build-env
FROM golang:1.17.7 AS build-env

WORKDIR /app

Expand All @@ -17,21 +11,10 @@ COPY . .

RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -installsuffix cgo -o /go/bin/main ./cmd/opg-s3-antivirus

FROM lambci/lambda:go1.x
FROM alpine:3.15

ENV DOCKER_LAMBDA_WATCH=1
ENV DOCKER_LAMBDA_STAY_OPEN=1
ENV AWS_LAMBDA_FUNCTION_HANDLER=main
ENV LD_LIBRARY_PATH=/var/task/lib

COPY --from=build-clamav /usr/bin/clamscan /var/task/bin/clamscan
COPY --from=build-clamav /usr/lib64/libclam* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libgnutls* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libhogweed* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libjson* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libnettle* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libpcre* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libprelude* /var/task/lib/
COPY --from=build-clamav /usr/lib64/libtasn1* /var/task/lib/
RUN apk update && apk add --no-cache clamav

COPY --from=build-env /go/bin/main /var/task/main

ENTRYPOINT [ "/var/task/main" ]
4 changes: 2 additions & 2 deletions scripts/localstack/init/localstack_init.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ awslocal s3api put-bucket-policy \
--bucket "uploads-bucket"

awslocal lambda create-function \
--function-name antivirus \
--function-name function \
--code ImageUri=antivirus-function:latest \
--role arn:aws:iam::000000000:role/lambda-ex

echo '{
"LambdaFunctionConfigurations": [
{
"Id": "bucket-av-scan",
"LambdaFunctionArn": "arn:aws:lambda:eu-west-1:000000000000:function:antivirus",
"LambdaFunctionArn": "arn:aws:lambda:eu-west-1:000000000000:function:function",
"Events": [
"s3:ObjectCreated:Put"
]
Expand Down
5 changes: 3 additions & 2 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ catch() {
docker compose -f docker/docker-compose.yml up --wait localstack
docker compose -f docker/docker-compose.yml exec -T localstack bash -c '. /scripts/wait/wait-until-s3-ready.sh'

docker compose -f docker/docker-compose.yml exec -T localstack awslocal lambda invoke --endpoint http://antivirus-update-function:9001 --no-sign-request --function-name antivirus-update --payload '{}' /dev/stdout
docker compose -f docker/docker-compose.yml exec -T localstack awslocal lambda invoke --endpoint http://antivirus-update-function:8080 --no-sign-request --function-name function --payload '{}' /dev/stdout
docker compose -f docker/docker-compose.yml exec -T localstack awslocal s3api list-objects --bucket virus-definitions
docker compose -f docker/docker-compose.yml restart antivirus-function

sleep 10
docker compose -f docker/docker-compose.yml exec -T localstack bash -c 'echo "Test file" | awslocal s3 cp - s3://uploads-bucket/valid.txt'
docker compose -f docker/docker-compose.yml exec -T localstack bash -c 'echo "X5O!P%@AP[4\PZX54(P^)7CC)7}\$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!\$H+H*" | awslocal s3 cp - s3://uploads-bucket/invalid.txt'

docker compose -f docker/docker-compose.yml exec -T localstack bash -c '. /scripts/wait/wait-until-tagged.sh valid.txt'
docker compose -f docker/docker-compose.yml exec -T localstack awslocal s3api get-object-tagging --bucket uploads-bucket --key valid.txt | jq -e '(.TagSet[] | select(.Key == "virus-scan-status")).Value == "ok"'

docker compose -f docker/docker-compose.yml exec -T localstack bash -c 'echo "X5O!P%@AP[4\PZX54(P^)7CC)7}\$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!\$H+H*" | awslocal s3 cp - s3://uploads-bucket/invalid.txt'

docker compose -f docker/docker-compose.yml exec -T localstack bash -c '. /scripts/wait/wait-until-tagged.sh invalid.txt'
docker compose -f docker/docker-compose.yml exec -T localstack awslocal s3api get-object-tagging --bucket uploads-bucket --key invalid.txt | jq -e '(.TagSet[] | select(.Key == "virus-scan-status")).Value == "infected"'