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:
- IAM role-based access (recommended)
- S3 bucket-policy-based access
The following table compares the two approaches:
IAM role-based access | S3 bucket-policy-based access | |
---|---|---|
Permission scope | fine granular, per AWS account/region and optionally per S3 bucket | very fine granular, per S3 bucket |
Configuration effort | low, once per AWS account/region | high, 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.
- Visit the AWS CloudWatch Management Console.
- Navigate to Dashboards.
- Select the dashboard starting with the name
bucketav
followed by the name of the AWS region—for example,bucketav-eu-west-1
. - Find the AWS accounts tile. Click the Connect AWS account button and follow the instructions.
CloudFormation StackSets
If you plan to connect many AWS accounts, we recommend using AWS CloudFormation StackSets in combination with AWS Organizations.
- Add your AWS organization id to the AWSOrganizationRestriction configuration parameter.
- Log in to your organization’s root account (or the delegated administrator for AWS CloudFormation) in a fresh browser session.
- Visit the AWS CloudFormation Console
- Ensure that you are in the correct region.
- Navigate to StackSets.
- Click on Create StackSet.
- Set Permissions to
Service-managed permissions
. - Set Prepare template to
Template is ready
. - Set the Template source to
Amazon S3 URL
. - 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. - Click on Next.
- Set the StackSet name to
bucketav-account-connection
. - Set the BucketAVStackName parameter to the stack name of bucketAV (if you followed the docs, the name is
bucketav
). - Set the BucketAVAccountId parameter to the AWS account ID of bucketAV (this is also where you create the StackSet).
- Click on Next.
- Keep the defaults, scroll to the bottom of the page, and click on Next.
- Set Add stacks to stack set to
Deploy new stacks
. - Set Deployment targets either to your organization or specific organizational units (OUs).
- Set Automatic deployment to
Activated
. - Set Account removal behaviour to
Delete stacks
. - Add the region where bucketAV runs.
- Click on Next.
- Select I acknowledge that AWS CloudFormation might create IAM resources.
- 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 isbucketav
). - 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 CloudFormationbucketav
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 CloudFormationbucketav-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 CloudFormationbucketav-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 CloudFormationbucketav-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
- In your bucketAV AWS account, get the SNS Findings Topic ARN.
- 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"
}
}
}]
}
- Copy the SQS queue ARN.
- In your bucketAV AWS account, open the SNS Findings Topic and create a subscription:
- Set Protocol to SQS.
- Set to Endpoint to
SQS_QUEUE_ARN
.
- 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.
- 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
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.