GuardDuty Malware Protection for S3, role policy issue

0

Hi team,

i'm trying to create a CDK stack for gaurdy malware protection for S3, following the git hub repo that was provided by this blog (cdk)

 const protectedBucket = new s3.Bucket(this, "ProtectedUploadBucket", {
      removalPolicy: cdk.RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      encryption: s3.BucketEncryption.S3_MANAGED,
    });

    const guardDutyMalwareRole = new iam.Role(
      this,
      "GuardDutyS3MalwareScanRole",
      {
        assumedBy: new iam.ServicePrincipal(
          "malware-protection-plan.guardduty.amazonaws.com",
          {
            conditions: {
              StringEquals: {
                "aws:SourceAccount": this.account,
              },
              ArnLike: {
                "aws:SourceArn": `arn:aws:guardduty:${this.region}:${this.account}:malware-protection-plan/*`,
              },
            },
          }
        ),
        description: "Role for GuardDuty Malware Protection to scan S3 buckets",
      }
    );

    // 2. Create the IAM role with the trust policy
    const malwareProtectionPolicy = new iam.Policy(
      this,
      "GuardDutyMalwareProtectionPolicy",
      {
        statements: [
          new iam.PolicyStatement({
            sid: "AllowManagedRuleToSendS3EventsToGuardDuty",
            effect: iam.Effect.ALLOW,
            actions: ["events:PutRule"],
            resources: [
              `arn:aws:events:${this.region}:${this.account}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`,
            ],
            conditions: {
              StringEquals: {
                "events:ManagedBy":
                  "malware-protection-plan.guardduty.amazonaws.com",
              },
              ForAllValues: {
                StringEquals: {
                  "events:source": "aws.s3",
                  "events:detail-type": [
                    "Object Created",
                    "AWS API Call via CloudTrail",
                  ],
                },
              },
              Null: {
                "events:source": "false",
                "events:detail-type": "false",
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowUpdateTargetAndDeleteManagedRule",
            effect: iam.Effect.ALLOW,
            actions: [
              "events:DeleteRule",
              "events:PutTargets",
              "events:RemoveTargets",
            ],
            resources: [
              `arn:aws:events:${this.region}:${this.account}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`,
            ],
            conditions: {
              StringEquals: {
                "events:ManagedBy":
                  "malware-protection-plan.guardduty.amazonaws.com",
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowGuardDutyToMonitorEventBridgeManagedRule",
            effect: iam.Effect.ALLOW,
            actions: ["events:DescribeRule", "events:ListTargetsByRule"],
            resources: [
              `arn:aws:events:${this.region}:${this.account}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`,
            ],
          }),
          new iam.PolicyStatement({
            sid: "AllowEnableS3EventBridgeEvents",
            effect: iam.Effect.ALLOW,
            actions: ["s3:PutBucketNotification", "s3:GetBucketNotification"],
            resources: [`${protectedBucket.bucketArn}`],
            conditions: {
              StringEquals: {
                "aws:ResourceAccount": this.account,
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowPostScanTag",
            effect: iam.Effect.ALLOW,
            actions: [
              "s3:GetObjectTagging",
              "s3:GetObjectVersionTagging",
              "s3:PutObjectTagging",
              "s3:PutObjectVersionTagging",
            ],
            resources: [`${protectedBucket.bucketArn}/*`],
            conditions: {
              StringEquals: {
                "aws:ResourceAccount": this.account,
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowPutValidationObject",
            effect: iam.Effect.ALLOW,
            actions: ["s3:PutObject"],
            resources: [
              `${protectedBucket.bucketArn}/malware-protection-resource-validation-object`,
            ],
            conditions: {
              StringEquals: {
                "aws:ResourceAccount": this.account,
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowCheckBucketOwnership",
            effect: iam.Effect.ALLOW,
            actions: ["s3:ListBucket"],
            resources: [`${protectedBucket.bucketArn}`],
            conditions: {
              StringEquals: {
                "aws:ResourceAccount": this.account,
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowMalwareScan",
            effect: iam.Effect.ALLOW,
            actions: ["s3:GetObject", "s3:GetObjectVersion"],
            resources: [`${protectedBucket.bucketArn}/*`],
            conditions: {
              StringEquals: {
                "aws:ResourceAccount": this.account,
              },
            },
          }),
        ],
      }
    );
    malwareProtectionPolicy.attachToRole(guardDutyMalwareRole);

    // Create the GuardDuty malware protection plan
    new guardduty.CfnMalwareProtectionPlan(
      this,
      "GuardDutyS3MalwareProtectionPlan",
      {
        protectedResource: {
          s3Bucket: {
            bucketName: protectedBucket.bucketName,
          },
        },
        role: guardDutyMalwareRole.roleArn,
        actions: {
          tagging: {
            status: "ENABLED",
          },
        },
      }
    );

I've added a policy for AllowCheckBucketOwnership like in this documentation

During the cdk deploy the stack fail with this error:

WS::GuardDuty::MalwareProtectionPlan | GuardDutyS3MalwareProtectionPlan Resource handler returned message: "The request was rejected because provided IAM role does not have the required permissions to validate S3 bucket ownership. (Service: GuardDuty, Status Code: 400,

Is there anything wrong on the way I added the policy?

Thank you!

1 Answer
0

Hello.

If you want to use the same IAM policy as the document, I think you will need to do the following.
In the following document, the IAM policy does not specify an account in "conditions", so please delete it and try again.
https://docs.aws.amazon.com/guardduty/latest/ug/malware-protection-s3-iam-policy-prerequisite.html

    const malwareProtectionPolicy = new iam.Policy(
      this,
      "GuardDutyMalwareProtectionPolicy",
      {
        statements: [
          new iam.PolicyStatement({
            sid: "AllowManagedRuleToSendS3EventsToGuardDuty",
            effect: iam.Effect.ALLOW,
            actions: ["events:PutRule"],
            resources: [
              `arn:aws:events:${this.region}:${this.account}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`,
            ],
            conditions: {
              StringEquals: {
                "events:ManagedBy":
                  "malware-protection-plan.guardduty.amazonaws.com",
              },
              ForAllValues: {
                StringEquals: {
                  "events:source": "aws.s3",
                  "events:detail-type": [
                    "Object Created",
                    "AWS API Call via CloudTrail",
                  ],
                },
              },
              Null: {
                "events:source": "false",
                "events:detail-type": "false",
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowUpdateTargetAndDeleteManagedRule",
            effect: iam.Effect.ALLOW,
            actions: [
              "events:DeleteRule",
              "events:PutTargets",
              "events:RemoveTargets",
            ],
            resources: [
              `arn:aws:events:${this.region}:${this.account}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`,
            ],
            conditions: {
              StringEquals: {
                "events:ManagedBy":
                  "malware-protection-plan.guardduty.amazonaws.com",
              },
            },
          }),
          new iam.PolicyStatement({
            sid: "AllowGuardDutyToMonitorEventBridgeManagedRule",
            effect: iam.Effect.ALLOW,
            actions: ["events:DescribeRule", "events:ListTargetsByRule"],
            resources: [
              `arn:aws:events:${this.region}:${this.account}:rule/DO-NOT-DELETE-AmazonGuardDutyMalwareProtectionS3*`,
            ],
          }),
          new iam.PolicyStatement({
            sid: "AllowEnableS3EventBridgeEvents",
            effect: iam.Effect.ALLOW,
            actions: ["s3:PutBucketNotification", "s3:GetBucketNotification"],
            resources: [`${protectedBucket.bucketArn}`],
//            conditions: {
//              StringEquals: {
//                "aws:ResourceAccount": this.account,
//              },
//            },
          }),
          new iam.PolicyStatement({
            sid: "AllowPostScanTag",
            effect: iam.Effect.ALLOW,
            actions: [
              "s3:GetObjectTagging",
              "s3:GetObjectVersionTagging",
              "s3:PutObjectTagging",
              "s3:PutObjectVersionTagging",
            ],
            resources: [`${protectedBucket.bucketArn}/*`],
//            conditions: {
//              StringEquals: {
//                "aws:ResourceAccount": this.account,
//              },
//            },
          }),
          new iam.PolicyStatement({
            sid: "AllowPutValidationObject",
            effect: iam.Effect.ALLOW,
            actions: ["s3:PutObject"],
            resources: [
              `${protectedBucket.bucketArn}/malware-protection-resource-validation-object`,
            ],
//            conditions: {
//              StringEquals: {
//                "aws:ResourceAccount": this.account,
//              },
//            },
          }),
          new iam.PolicyStatement({
            sid: "AllowCheckBucketOwnership",
            effect: iam.Effect.ALLOW,
            actions: ["s3:ListBucket"],
            resources: [`${protectedBucket.bucketArn}`],
//            conditions: {
//              StringEquals: {
//                "aws:ResourceAccount": this.account,
//              },
//            },
          }),
          new iam.PolicyStatement({
            sid: "AllowMalwareScan",
            effect: iam.Effect.ALLOW,
            actions: ["s3:GetObject", "s3:GetObjectVersion"],
            resources: [`${protectedBucket.bucketArn}/*`],
//            conditions: {
//              StringEquals: {
//                "aws:ResourceAccount": this.account,
//              },
//            },
          }),
        ],
      }
    );
    malwareProtectionPolicy.attachToRole(guardDutyMalwareRole);
profile picture
EXPERT
answered a month ago
  • Thank you for answering my question,

    is there any other way to do it via CDK? or we should anyway create the policy for Guarduty service role ?

    if we don't specify the role, will AWS creates it behind the scene? like it does when we crate the s3 protection via the console

    Thank you!

  • Since this IAM role is different from the GuardDuty service-linked role, I think it would not be created automatically when enabling Malware Protection for S3.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions