ラムダコンテナでファイルをスキャンするServerlessを使用する


私は、ラムダ関数を指定したラムダ層で使用しました.レイヤーのバイナリは、アマゾンの amazonlinux:2 イメージ.これらのバイナリはAWS's lambda container images feature ラムダ関数とその層でしたように、展開サイズ制限の心配なしで.

歴史


これを読まなかった人にとって、これはラムダ関数に向かってイベントトリガーを持つS 3バケットを確立する予定です.このラムダ関数は、ハンドラーコードとClamAVバイナリとウイルス定義のコンテナです.それはトリガーのメタデータを通してS 3オブジェクトを得て、それをスキャンして、ClamAV走査の結果につききれいであるか汚いものとしてそれをマークします.
TLDR :ここではGitHub repository .

インフラ


これは明らかに異なっているでしょう-ラムダ層を使用する代わりに、我々はECRに保存されたDockerイメージを使用するでしょう.Serverlessのおかげで、これはほとんど楽です.

無力な


デフォルトでは、サーバーは私たちのためのECRリポジトリを作成し、イメージがそれに住んでいます.私たちがしなければならないすべては、それを Dockerfile .
service: clambda-av

provider:
  name: aws
  runtime: nodejs14.x
  ecr:
    images:
      clambdaAv:
        path: ./
  iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:GetObject
        - s3:PutObjectTagging
      Resource: "arn:aws:s3:::clambda-av-files/*"

functions:
  virusScan:
    image:
      name: clambdaAv
    memorySize: 2048
    events:
      - s3: 
          bucket: clambda-av-files
          event: s3:ObjectCreated:*
    timeout: 120

package:
  exclude:
    - node_modules/**
    - coverage/**

Dockerfile


JavaScriptを使用しているので、我々は nodejs14 image 基地として.残念ながら、私たちは簡単にこのイメージを通して私たちのClamAVバイナリをインストールすることができませんamazonlinux:2 上記の通りイメージ.幸いにも、Dockerは我々が容易にそれを行うことを許しますmulti-stage Docker builds . 私は今までこれをしたことがありませんが、それはかなり迅速かつ興味深いプロセスです.
FROM amazonlinux:2 AS layer-image

WORKDIR /home/build

RUN set -e

RUN echo "Prepping ClamAV"

RUN rm -rf bin
RUN rm -rf lib

RUN yum update -y
RUN amazon-linux-extras install epel -y
RUN yum install -y cpio yum-utils tar.x86_64 gzip zip

RUN yumdownloader -x \*i686 --archlist=x86_64 clamav
RUN rpm2cpio clamav-0*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 clamav-lib
RUN rpm2cpio clamav-lib*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 clamav-update
RUN rpm2cpio clamav-update*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 json-c
RUN rpm2cpio json-c*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 pcre2
RUN rpm2cpio pcre*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 libtool-ltdl
RUN rpm2cpio libtool-ltdl*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 libxml2
RUN rpm2cpio libxml2*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 bzip2-libs
RUN rpm2cpio bzip2-libs*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 xz-libs
RUN rpm2cpio xz-libs*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 libprelude
RUN rpm2cpio libprelude*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 gnutls
RUN rpm2cpio gnutls*.rpm | cpio -vimd

RUN yumdownloader -x \*i686 --archlist=x86_64 nettle
RUN rpm2cpio nettle*.rpm | cpio -vimd

RUN mkdir -p bin
RUN mkdir -p lib
RUN mkdir -p var/lib/clamav
RUN chmod -R 777 var/lib/clamav

COPY ./freshclam.conf .

RUN cp usr/bin/clamscan usr/bin/freshclam bin/.
RUN cp usr/lib64/* lib/.
RUN cp freshclam.conf bin/freshclam.conf

RUN yum install shadow-utils.x86_64 -y

RUN groupadd clamav
RUN useradd -g clamav -s /bin/false -c "Clam Antivirus" clamav
RUN useradd -g clamav -s /bin/false -c "Clam Antivirus" clamupdate

RUN LD_LIBRARY_PATH=./lib ./bin/freshclam --config-file=bin/freshclam.conf

FROM public.ecr.aws/lambda/nodejs:14

COPY --from=layer-image /home/build ./

COPY handler.js ./

CMD ["handler.virusScan"]
このdockfileは二つのことを行います.
  • ClamAVバイナリをステージエイリアスに構築するlayer-image ClamAVウイルス定義とともに
  • ラムダ画像をハンドラー自身でビルドし、layer-image ステージ
  • ハンドラ


    これはハンドラをあまり変更しません.
    const { execSync } = require("child_process");
    const { writeFileSync, unlinkSync } = require("fs");
    const AWS = require("aws-sdk");
    
    const s3 = new AWS.S3();
    
    module.exports.virusScan = async (event, context) => {
      if (!event.Records) {
        console.log("Not an S3 event invocation!");
        return;
      }
    
      for (const record of event.Records) {
        if (!record.s3) {
          console.log("Not an S3 Record!");
          continue;
        }
    
        // get the file
        const s3Object = await s3
          .getObject({
            Bucket: record.s3.bucket.name,
            Key: record.s3.object.key
          })
          .promise();
    
        // write file to disk
        writeFileSync(`/tmp/${record.s3.object.key}`, s3Object.Body);
    
        try { 
          // scan it
          execSync(`./bin/clamscan --database=./var/lib/clamav /tmp/${record.s3.object.key}`);
    
          await s3
            .putObjectTagging({
              Bucket: record.s3.bucket.name,
              Key: record.s3.object.key,
              Tagging: {
                TagSet: [
                  {
                    Key: 'av-status',
                    Value: 'clean'
                  }
                ]
              }
            })
            .promise();
        } catch(err) {
          if (err.status === 1) {
            // tag as dirty, OR you can delete it
            await s3
              .putObjectTagging({
                Bucket: record.s3.bucket.name,
                Key: record.s3.object.key,
                Tagging: {
                  TagSet: [
                    {
                      Key: 'av-status',
                      Value: 'dirty'
                    }
                  ]
                }
              })
              .promise();
          }
        }
    
        // delete the temp file
        unlinkSync(`/tmp/${record.s3.object.key}`);
      }
    };
    

    概要


    我々から(これが私がそれをリンクしている最後の時です)、これはBashスクリプトでバイナリを造る余分のステップを取り除きます.また、ラムダ層の必要性を除去する.
    あなたが再び完全なコードをチェックアウトしたいならば、それはGithubリポジトリにあります.ご質問やご質問、またはあなたがこの記事を持っている可能性がある場合は、リポジトリ上で問題を開くことによって可能性があります問題を投稿することを躊躇しないでください.読書ありがとう!