Multi-account setup

This feature is only available for bucketAV for Amazon S3!

If you have a multi-account setup, you might want to scan buckets created in additional AWS accounts b and c while bucketAV runs in AWS account a.

We recommend running bucketAV in the same account as your S3 buckets to minimize the configuration overhead and keep the isolation boundaries in effect.

Step 1: Prepare bucketAV

Allowlist additional AWS accounts by modifying the AWSAccountRestriction configuration parameter or AWSOrganizationRestriction configuration parameter in your bucketAV stack.

Step 2: Connect additional AWS accounts

There are two supported approaches:

  1. IAM role-based access (recommended)
  2. S3 bucket-policy-based access

The following table compares the two approaches:

IAM role-based accessS3 bucket-policy-based access
Permission scopefine granular, per AWS account/region and optionally per S3 bucketvery fine granular, per S3 bucket
Configuration effortlow, once per AWS account/regionhigh, once per S3 bucket

IAM role-based access (recommended)

Requires bucketAV for Amazon S3 powered by ClamAV® version >= 2.19.0, or bucketAV for Amazon S3 powered by Sophos® version >= 2.11.0.
To update to the latest version, follow the Update Guide.

To use IAM role-based access, you must connect your AWS accounts b and c with bucketAV in AWS account a.

  1. Visit the AWS CloudWatch Management Console.
  2. Navigate to Dashboards.
  3. Select the dashboard starting with the name bucketav followed by the name of the AWS region—for example, bucketav-eu-west-1. Step 1
  4. Find the AWS accounts tile. Click the Connect AWS account button and follow the instructions. Step 2

CloudFormation StackSets

If you plan to connect many AWS accounts, we recommend using AWS CloudFormation StackSets in combination with AWS Organizations.

  1. Add your AWS organization id to the AWSOrganizationRestriction configuration parameter.
  2. Log in to your organization’s root account (or the delegated administrator for AWS CloudFormation) in a fresh browser session.
  3. Visit the AWS CloudFormation Console
  4. Ensure that you are in the correct region.
  5. Navigate to StackSets.
  6. Click on Create StackSet.
  7. Set Permissions to Service-managed permissions.
  8. Set Prepare template to Template is ready.
  9. Set the Template source to Amazon S3 URL.
  10. Set the Amazon S3 URL to https://bucketav-add-ons.s3.eu-west-1.amazonaws.com/account-connection/v2.2.0/bucketav-add-on-account-connection.yaml Copy.
  11. Click on Next.
  12. Set the StackSet name to bucketav-account-connection.
  13. Set the BucketAVStackName parameter to the stack name of bucketAV (if you followed the docs, the name is bucketav).
  14. Set the BucketAVAccountId parameter to the AWS account ID of bucketAV (this is also where you create the StackSet).
  15. Click on Next.
  16. Keep the defaults, scroll to the bottom of the page, and click on Next.
  17. Set Add stacks to stack set to Deploy new stacks.
  18. Set Deployment targets either to your organization or specific organizational units (OUs).
  19. Set Automatic deployment to Activated.
  20. Set Account removal behaviour to Delete stacks.
  21. Add the region where bucketAV runs.
  22. Click on Next.
  23. Select I acknowledge that AWS CloudFormation might create IAM resources.
  24. Click on the Submit button to save.

Add-Ons

The following Add-Ons support IAM role-based access out of the box but are still created in the AWS account running bucketAV (account a):

  • move-clean
  • move-no
  • quarantine
  • scheduled-bucket-scan

All other Add-Ons access resources only within the AWS account running bucketAV (account a).

Add-Ons that move files (move-clean, move-no, quarantine) from a source bucket in account b to a target/quarantine bucket in account c must consider one specialty..

Scenario: bucketAV runs in AWS account a, your source bucket is created in AWS Account b, and your target/quarantine bucket is created in AWS account c. AWS account b is connected to bucketAV and runs in AWS account a.

Add the following bucket policy statements to your target S3 bucket/quarantine in account c to grant bucketAV’s IAM role created in account b access.

  • Replace BUCKETAV_STACK_NAME with the stack name of bucketAV (account a; if you followed the docs, the name is bucketav).
  • Replace ACCOUNT_B_ID with the AWS account id (account b; e.g., 222222222222).
  • Replace BUCKET_NAME with the name of the target/quarantine S3 bucket (account c).
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "bucketAVRequired1",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::ACCOUNT_B_ID:role/BUCKETAV_STACK_NAME-AccountConnection"
    },
    "Action": "s3:ListBucket*",
    "Resource": "arn:aws:s3:::BUCKET_NAME"
  }, {
    "Sid": "bucketAVRequired2",
    "Effect": "Allow",
    "Principal": {
      "AWS": "arn:aws:iam::ACCOUNT_B_ID:role/BUCKETAV_STACK_NAME-AccountConnection"
    },
    "Action": "s3:PutObject*",
    "Resource": "arn:aws:s3:::BUCKET_NAME/*"
  }]
}

When using KMS to encrypt the S3 bucket or objects, please note that a customer-managed KMS key is necessary for cross-account access. Use a KMS key policy and the Add-On parameter KMSKeyRestriction to control access.

S3 bucket-policy-based access

Add the following bucket policy statements to each S3 bucket in additional AWS accounts to grant bucketAV access.

  • Replace ROLE_ARN with the ScanRoleArn output of the CloudFormation bucketav stack.
  • Replace BUCKET_NAME with the name of the S3 bucket.
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "bucketAVRequired1",
    "Effect": "Allow",
    "Principal": {
      "AWS": "ROLE_ARN"
    },
    "Action": "s3:ListBucket*",
    "Resource": "arn:aws:s3:::BUCKET_NAME"
  }, {
    "Sid": "bucketAVRequired2",
    "Effect": "Allow",
    "Principal": {
      "AWS": "ROLE_ARN"
    },
    "Action": "s3:GetObject*",
    "Resource": "arn:aws:s3:::BUCKET_NAME/*"
  }, {
    "Sid": "bucketAVOnlyIfYouDeleteInfectedFiles",
    "Effect": "Allow",
    "Principal": {
      "AWS": "ROLE_ARN"
    },
    "Action": "s3:DeleteObject*",
    "Resource": "arn:aws:s3:::BUCKET_NAME/*"
  }, {
    "Sid": "bucketAVOnlyIfYouTagFilesWithScanResult",
    "Effect": "Allow",
    "Principal": {
      "AWS": "ROLE_ARN"
    },
    "Action": [
      "s3:GetObjectTagging",
      "s3:GetObjectVersionTagging",
      "s3:PutObjectTagging",
      "s3:PutObjectVersionTagging"
    ],
    "Resource": "arn:aws:s3:::BUCKET_NAME/*"
  }]
}

If you use SSE-KMS to encrypt your buckets, you must ensure that the KMS Key Policy allows access from the ScanRoleArn. If you use AWS-managed KMS CMKs, you can not edit the key policy. Therefore, only customer-managed CMKs are supported.

Add-Ons

The following Add-Ons require access to your S3 buckets and require additional statements in your bucket policy:

move-clean, move-no, quarantine
Target/quarantine bucket in different AWS account than bucketAV

Scenario: bucketAV runs in AWS account a while your target/quarantine bucket is created in AWS account b.

Add the following bucket policy statements to your target S3 bucket/quarantine in account b to grant bucketAV running in AWS account a access.

  • Replace ROLE_ARN with the MoveRoleArn / QuarantineRoleArn output of the CloudFormation bucketav-move-clean / bucketav-move-no / bucketav-quarantine stack (account a).
  • Replace BUCKET_NAME with the name of the target/quarantine S3 bucket (account ).
{
  "Version": "2012-10-17",
  "Statement": [{
    "Sid": "bucketAVRequired1",
    "Effect": "Allow",
    "Principal": {
      "AWS": "ROLE_ARN"
    },
    "Action": "s3:ListBucket*",
    "Resource": "arn:aws:s3:::BUCKET_NAME"
  }, {
    "Sid": "bucketAVRequired2",
    "Effect": "Allow",
    "Principal": {
      "AWS": "ROLE_ARN"
    },
    "Action": "s3:PutObject*",
    "Resource": "arn:aws:s3:::BUCKET_NAME/*"
  }]
}

When using KMS to encrypt the S3 bucket or objects, please note that a customer-managed KMS key is necessary for cross-account access. Use a KMS key policy and the Add-On parameter KMSKeyRestriction to control access.

Source bucket in different AWS account than bucketAV

Scenario: bucketAV runs in AWS account a while the source bucket is created in AWS account b.

Add the following bucket policy statements to your source S3 bucket in account b to grant bucketAV running in AWS account a access.

  • Replace ROLE_ARN with the MoveRoleArn / QuarantineRoleArn output of the CloudFormation bucketav-move-clean / bucketav-move-no / bucketav-quarantine stack (account a).
  • Replace BUCKET_NAME with the name of the source S3 bucket (account b).
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "ROLE_ARN"
      },
      "Action": "s3:ListBucket*",
      "Resource": "arn:aws:s3:::BUCKET_NAME"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "ROLE_ARN"
      },
      "Action": [
        "s3:GetObject*",
        "s3:DeleteObject*"
      ],
      "Resource": "arn:aws:s3:::BUCKET_NAME/*"
    }
  ]
}

When using KMS to encrypt the S3 bucket or objects, please note that a customer-managed KMS key is necessary for cross-account access. Use a KMS key policy and the Add-On parameter KMSKeyRestriction to control access.

scheduled-bucket-scan

Scenario: bucketAV runs in AWS account a while the bucket is created in AWS account b.

Add the following bucket policy statements to your source S3 bucket in account b to grant bucketAV running in AWS account a access.

  • Replace ROLE_ARN with the RoleArn output of the CloudFormation bucketav-scheduled-bucket-scan stack (account a).
  • Replace BUCKET_NAME with the name of the source S3 bucket (account b).
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "ROLE_ARN"
      },
      "Action": "s3:ListBucketVersions",
      "Resource": "arn:aws:s3:::BUCKET_NAME"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "ROLE_ARN"
      },
      "Action": [
        "s3:GetObjectTagging",
        "s3:GetObjectVersionTagging"
      ],
      "Resource": "arn:aws:s3:::BUCKET_NAME/*"
    }
  ]
}

When using KMS to encrypt the S3 bucket or objects, please note that a customer-managed KMS key is necessary for cross-account access. Use a KMS key policy and the Add-On parameter KMSKeyRestriction to control access.

Access Findings Topic from additional AWS accounts

  1. In your bucketAV AWS account, get the SNS Findings Topic ARN.
  2. In your additional AWS account, create an SQS standard queue with a queue policy like this (replace ACCOUNT_ID, SQS_QUEUE_ARN, SNS_FINDINGS_TOPIC_ARN):
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "AWS": "ACCOUNT_ID"
    },
    "Action": "sqs:*",
    "Resource": "SQS_QUEUE_ARN"
  }, {
    "Effect": "Allow",
    "Principal": "*",
    "Action": "sqs:SendMessage",
    "Resource": "ACCOUNT_B_SQS_QUEUE_ARN",
    "Condition": {
      "ArnEquals": {
        "aws:SourceArn": "SNS_FINDINGS_TOPIC_ARN"
      }
    }
  }]
}
  1. Copy the SQS queue ARN.
  2. In your bucketAV AWS account, open the SNS Findings Topic and create a subscription:
    1. Set Protocol to SQS.
    2. Set to Endpoint to SQS_QUEUE_ARN.
  3. In account b, open the newly created SQS queue, click the Send and receive messages button, and Poll for messages. One SubscriptionConfirmation message is waiting for you in the queue. Extract the SubscribeURL attribute and open the URL in your browser. You will see an XML document with a root element named ConfirmSubscriptionResponse.
  4. In account a, double-check the SNS subscription status to match Confirmed.

Configure EventBridge

First, in your AWS account running bucketAV (account a), configure the EventBridge bus default to accept messages from the AWS account owning the bucket that you want to scan (account b). To do so, configure the permissions of the EventBus with the following resource-based policy:

  • Replace ACCOUNT_A_ID with the AWS account id running bucketAV (account a; e.g., 111111111111).
  • Replace ACCOUNT_B_ID with the AWS account id owning the bucket (account b; e.g., 222222222222).
  • Replace REGION with the AWS region (e.g., eu-west-1).
{
  "Version": "2012-10-17",
  "Statement":
  [
    {
      "Sid": "AllowAccountToPutEvents",
      "Effect": "Allow",
      "Principal":
      {
        "AWS": "ACCOUNT_B_ID"
      },
      "Action": "events:PutEvents",
      "Resource": "arn:aws:events:REGION:ACCOUNT_A_ID:event-bus/default"
    }
  ]
}

Second, in your AWS account running bucketAV (account a), create an EventBridge rule as described at https://bucketav.com/help/scan-modes/real-time-file-scan.html#eventbridge.

Third, in your AWS account owning the bucket (account b), create an EventBridge rule with the same event pattern as in the previous step. Set the Event bus as target to:

  • Replace ACCOUNT_A_ID with the AWS account id running bucketAV (account a; e.g., 111111111111).
  • Replace REGION with the AWS region (e.g., eu-west-1).
arn:aws:events:REGION:ACCOUNT_A_ID:event-bus/default

Configure EventBridge

Fourth, in your AWS account owning the bucket (account b), enable Amazon EventBridge on the bucket. Make sure the bucket’s region matches the bucketAV region.

Need more help?

Write us, and we'll get back to you as soon as we can.

Send us an email