Skip to content

Commit 12ed260

Browse files
authored
Move to smaller base image (#20)
Use alpine as a base image, and install clamav properly so that it's just available on PATH. This led to a few changes to how we call `clamscan` and `freshclam`. Without lambci, we now need `aws-lambda-rie` to provide the Lambda runtime environment (i.e. the HTTP API). Because this is just needed for local dev, mount it rather than installing on the image directly. `aws-lambda-rie` causes two restrictions: - The function name must be "function". There's [a PR to make this configurable](aws/aws-lambda-runtime-interface-emulator#46), but AWS don't seem keen - It can only handle one invokation at a time, so we can't upload the second test file (and therefore invoke the Lamdba) until the first is finished #minor
1 parent f760245 commit 12ed260

File tree

10 files changed

+35
-61
lines changed

10 files changed

+35
-61
lines changed

.aws-lambda-rie/aws-lambda-rie

5.3 MB
Binary file not shown.

cmd/opg-s3-antivirus-update/freshclam.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
type Freshclam struct{}
99

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

1313
cmd.Stdout = os.Stdout
1414
cmd.Stderr = os.Stdout

cmd/opg-s3-antivirus-update/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,10 @@ func (l *Lambda) uploadDefinitions() error {
7777
}
7878

7979
input := &s3manager.UploadInput{
80-
Bucket: aws.String(l.bucket),
81-
Key: aws.String(key),
82-
Body: file,
80+
Bucket: aws.String(l.bucket),
81+
Key: aws.String(key),
82+
Body: file,
83+
ServerSideEncryption: aws.String("AES256"),
8384
}
8485

8586
if _, err := l.uploader.Upload(input); err != nil {

cmd/opg-s3-antivirus-update/main_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type mockUploader struct {
3030
}
3131

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

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

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

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

149149
uploader.
150-
On("Upload", "a-bucket", "a", mock.Anything).
150+
On("Upload", "a-bucket", "a", mock.Anything, "AES256").
151151
Return(nil)
152152

153153
uploader.
154-
On("Upload", "a-bucket", "b", mock.Anything).
154+
On("Upload", "a-bucket", "b", mock.Anything, "AES256").
155155
Return(nil)
156156

157157
response, err := l.HandleEvent(Event{})

cmd/opg-s3-antivirus/scanner.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type ClamAvScanner struct {
1010
}
1111

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

1515
cmd.Stdout = os.Stdout
1616
cmd.Stderr = os.Stdout

docker/docker-compose.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ services:
1616
ANTIVIRUS_TAG_VALUE_PASS: ok
1717
ANTIVIRUS_TAG_VALUE_FAIL: infected
1818
ANTIVIRUS_DEFINITIONS_BUCKET: virus-definitions
19+
volumes:
20+
- "../.aws-lambda-rie:/aws-lambda"
21+
entrypoint: /aws-lambda/aws-lambda-rie /var/task/main
1922

2023
antivirus-update-function:
2124
image: antivirus-update-function:latest
@@ -28,6 +31,9 @@ services:
2831
AWS_ACCESS_KEY_ID: localstack
2932
AWS_SECRET_ACCESS_KEY: localstack
3033
ANTIVIRUS_DEFINITIONS_BUCKET: virus-definitions
34+
volumes:
35+
- "../.aws-lambda-rie:/aws-lambda"
36+
entrypoint: /aws-lambda/aws-lambda-rie /var/task/main
3137

3238
localstack:
3339
image: localstack/localstack:0.13
@@ -42,7 +48,7 @@ services:
4248
SERVICES: s3,lambda
4349
LAMBDA_EXECUTOR: docker
4450
LAMBDA_REMOVE_CONTAINERS: "true"
45-
LAMBDA_FORWARD_URL: http://antivirus-function:9001
51+
LAMBDA_FORWARD_URL: http://antivirus-function:8080
4652
DOCKER_HOST: unix:///var/run/docker.sock
4753
healthcheck:
4854
test: ["CMD-SHELL", "curl http://localhost:4566 || exit 1"]
Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
FROM amazonlinux:2 AS build-clamav
2-
3-
RUN yum update -y &&\
4-
amazon-linux-extras install epel -y &&\
5-
yum install clamav clamd -y
6-
7-
FROM golang:1.17.6 AS build-env
1+
FROM golang:1.17.7 AS build-env
82

93
WORKDIR /app
104

@@ -17,24 +11,13 @@ COPY . .
1711

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

20-
FROM lambci/lambda:go1.x
14+
FROM alpine:3.15
2115

22-
ENV DOCKER_LAMBDA_WATCH=1
23-
ENV DOCKER_LAMBDA_STAY_OPEN=1
24-
ENV AWS_LAMBDA_FUNCTION_HANDLER=main
25-
ENV LD_LIBRARY_PATH=/var/task/lib
16+
RUN apk update && apk add --no-cache clamav
2617

27-
COPY ./freshclam.conf /etc
28-
COPY --from=build-clamav /usr/bin/freshclam /var/task/bin/freshclam
29-
COPY --from=build-clamav /usr/lib64/libclam* /var/task/lib/
30-
COPY --from=build-clamav /usr/lib64/libfreshclam* /var/task/lib/
31-
COPY --from=build-clamav /usr/lib64/libgnutls* /var/task/lib/
32-
COPY --from=build-clamav /usr/lib64/libhogweed* /var/task/lib/
33-
COPY --from=build-clamav /usr/lib64/libjson* /var/task/lib/
34-
COPY --from=build-clamav /usr/lib64/libltdl* /var/task/lib/
35-
COPY --from=build-clamav /usr/lib64/libnettle* /var/task/lib/
36-
COPY --from=build-clamav /usr/lib64/libpcre* /var/task/lib/
37-
COPY --from=build-clamav /usr/lib64/libprelude* /var/task/lib/
38-
COPY --from=build-clamav /usr/lib64/libtasn1* /var/task/lib/
18+
RUN mkdir -p /tmp/clamav && chown -R clamav:clamav /tmp/clamav
3919

20+
COPY ./freshclam.conf /etc
4021
COPY --from=build-env /go/bin/main /var/task/main
22+
23+
ENTRYPOINT [ "/var/task/main" ]

docker/opg-s3-antivirus/Dockerfile

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
FROM amazonlinux:2 AS build-clamav
2-
3-
RUN yum update -y &&\
4-
amazon-linux-extras install epel -y &&\
5-
yum install clamav clamd -y
6-
7-
FROM golang:1.17.6 AS build-env
1+
FROM golang:1.17.7 AS build-env
82

93
WORKDIR /app
104

@@ -17,21 +11,10 @@ COPY . .
1711

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

20-
FROM lambci/lambda:go1.x
14+
FROM alpine:3.15
2115

22-
ENV DOCKER_LAMBDA_WATCH=1
23-
ENV DOCKER_LAMBDA_STAY_OPEN=1
24-
ENV AWS_LAMBDA_FUNCTION_HANDLER=main
25-
ENV LD_LIBRARY_PATH=/var/task/lib
26-
27-
COPY --from=build-clamav /usr/bin/clamscan /var/task/bin/clamscan
28-
COPY --from=build-clamav /usr/lib64/libclam* /var/task/lib/
29-
COPY --from=build-clamav /usr/lib64/libgnutls* /var/task/lib/
30-
COPY --from=build-clamav /usr/lib64/libhogweed* /var/task/lib/
31-
COPY --from=build-clamav /usr/lib64/libjson* /var/task/lib/
32-
COPY --from=build-clamav /usr/lib64/libnettle* /var/task/lib/
33-
COPY --from=build-clamav /usr/lib64/libpcre* /var/task/lib/
34-
COPY --from=build-clamav /usr/lib64/libprelude* /var/task/lib/
35-
COPY --from=build-clamav /usr/lib64/libtasn1* /var/task/lib/
16+
RUN apk update && apk add --no-cache clamav
3617

3718
COPY --from=build-env /go/bin/main /var/task/main
19+
20+
ENTRYPOINT [ "/var/task/main" ]

scripts/localstack/init/localstack_init.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ awslocal s3api put-bucket-policy \
3434
--bucket "uploads-bucket"
3535

3636
awslocal lambda create-function \
37-
--function-name antivirus \
37+
--function-name function \
3838
--code ImageUri=antivirus-function:latest \
3939
--role arn:aws:iam::000000000:role/lambda-ex
4040

4141
echo '{
4242
"LambdaFunctionConfigurations": [
4343
{
4444
"Id": "bucket-av-scan",
45-
"LambdaFunctionArn": "arn:aws:lambda:eu-west-1:000000000000:function:antivirus",
45+
"LambdaFunctionArn": "arn:aws:lambda:eu-west-1:000000000000:function:function",
4646
"Events": [
4747
"s3:ObjectCreated:Put"
4848
]

test.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,17 @@ catch() {
1010
docker compose -f docker/docker-compose.yml up --wait localstack
1111
docker compose -f docker/docker-compose.yml exec -T localstack bash -c '. /scripts/wait/wait-until-s3-ready.sh'
1212

13-
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
13+
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
1414
docker compose -f docker/docker-compose.yml exec -T localstack awslocal s3api list-objects --bucket virus-definitions
1515
docker compose -f docker/docker-compose.yml restart antivirus-function
1616

1717
sleep 10
1818
docker compose -f docker/docker-compose.yml exec -T localstack bash -c 'echo "Test file" | awslocal s3 cp - s3://uploads-bucket/valid.txt'
19-
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'
2019

2120
docker compose -f docker/docker-compose.yml exec -T localstack bash -c '. /scripts/wait/wait-until-tagged.sh valid.txt'
2221
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"'
2322

23+
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'
24+
2425
docker compose -f docker/docker-compose.yml exec -T localstack bash -c '. /scripts/wait/wait-until-tagged.sh invalid.txt'
2526
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"'

0 commit comments

Comments
 (0)