Skip to content

airflow cdk code error

0

#!/usr/bin/env python3 from aws_cdk import ( Stack, RemovalPolicy, aws_ec2 as ec2, aws_iam as iam, aws_s3 as s3, aws_s3_deployment as s3deploy, aws_mwaa as mwaa, ) from constructs import Construct import os

class AirflowStack(Stack): """ MWAA Airflow Stack — FIXED (only invalid IAM policy removed) """

def __init__(
    self,
    scope: Construct,
    construct_id: str,
    *,
    store_vpc: ec2.Vpc,
    **kwargs,
) -> None:
    super().__init__(scope, construct_id, **kwargs)

    airflow_env_name = construct_id.lower()
    dags_bucket_name = f"{construct_id.lower()}-dags"

    # ---------------------------------------------------------------------
    # 1️⃣ S3 Bucket (UNCHANGED)
    # ---------------------------------------------------------------------
    dags_bucket = s3.Bucket(
        self,
        "AirflowDagsBucket",
        bucket_name=dags_bucket_name,
        versioned=True,
        encryption=s3.BucketEncryption.S3_MANAGED,
        block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
        enforce_ssl=True,
        removal_policy=RemovalPolicy.RETAIN,
    )

    dags_folder = os.path.join(os.getcwd(), "dags")
    if os.path.isdir(dags_folder):
        s3deploy.BucketDeployment(
            self,
            "DeployDags",
            sources=[s3deploy.Source.asset(dags_folder)],
            destination_bucket=dags_bucket,
            destination_key_prefix="dags",
            prune=False,
        )

    # ---------------------------------------------------------------------
    # 2️⃣ MWAA EXECUTION ROLE (ONLY FIX IS HERE)
    # ---------------------------------------------------------------------
    mwaa_role = iam.Role(
        self,
        "MwaaExecutionRole",
        role_name=f"{airflow_env_name}-exec-role",
        assumed_by=iam.CompositePrincipal(
            iam.ServicePrincipal("airflow.amazonaws.com"),
            iam.ServicePrincipal("airflow-env.amazonaws.com"),
        ),
        path="/service-role/",
    )

    # ❌ REMOVED:
    # AmazonMWAASvcRolePolicy DOES NOT EXIST / NOT ATTACHABLE
    # mwaa_role.add_managed_policy(
    #     iam.ManagedPolicy.from_aws_managed_policy_name("AmazonMWAASvcRolePolicy")
    # )

    # Existing S3 access (UNCHANGED)
    mwaa_role.add_managed_policy(
        iam.ManagedPolicy.from_aws_managed_policy_name("AmazonS3ReadOnlyAccess")
    )

    dags_bucket.grant_read_write(mwaa_role)

    # Logs (UNCHANGED)
    mwaa_role.add_to_policy(
        iam.PolicyStatement(
            actions=[
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
            ],
            resources=["*"],
        )
    )

    # MWAA internal queues (UNCHANGED)
    mwaa_role.add_to_policy(
        iam.PolicyStatement(
            actions=[
                "sqs:SendMessage",
                "sqs:ReceiveMessage",
                "sqs:DeleteMessage",
                "sqs:GetQueueAttributes",
                "sqs:GetQueueUrl",
            ],
            resources=["*"],
        )
    )

    # Private VPC auth calls (UNCHANGED)
    mwaa_role.add_to_policy(
        iam.PolicyStatement(
            actions=[
                "secretsmanager:GetSecretValue",
                "kms:Decrypt",
                "sts:GetCallerIdentity",
            ],
            resources=["*"],
        )
    )

    # ---------------------------------------------------------------------
    # 3️⃣ SECURITY GROUP (UNCHANGED)
    # ---------------------------------------------------------------------
    mwaa_sg = ec2.SecurityGroup(
        self,
        "MwaaSecurityGroup",
        vpc=store_vpc,
        description="MWAA Security Group",
        allow_all_outbound=True,
    )

    mwaa_sg.add_ingress_rule(
        peer=mwaa_sg,
        connection=ec2.Port.all_traffic(),
        description="MWAA self traffic",
    )

    mwaa_sg.add_egress_rule(
        peer=ec2.Peer.any_ipv4(),
        connection=ec2.Port.tcp(443),
        description="HTTPS outbound",
    )

    # ---------------------------------------------------------------------
    # 4️⃣ NETWORK CONFIG (UNCHANGED)
    # ---------------------------------------------------------------------
    private_subnets = store_vpc.select_subnets(
        subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS
    ).subnet_ids[:2]

    if len(private_subnets) < 2:
        raise ValueError("MWAA requires at least 2 private subnets")

    network_config = mwaa.CfnEnvironment.NetworkConfigurationProperty(
        security_group_ids=[mwaa_sg.security_group_id],
        subnet_ids=private_subnets,
    )

    # ---------------------------------------------------------------------
    # 5️⃣ LOGGING (UNCHANGED)
    # ---------------------------------------------------------------------
    logging_config = mwaa.CfnEnvironment.LoggingConfigurationProperty(
        dag_processing_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
            enabled=True, log_level="INFO"
        ),
        scheduler_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
            enabled=True, log_level="INFO"
        ),
        task_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
            enabled=True, log_level="INFO"
        ),
        webserver_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
            enabled=True, log_level="INFO"
        ),
        worker_logs=mwaa.CfnEnvironment.ModuleLoggingConfigurationProperty(
            enabled=True, log_level="INFO"
        ),
    )

    # ---------------------------------------------------------------------
    # 6️⃣ MWAA ENVIRONMENT (UNCHANGED)
    # ---------------------------------------------------------------------
    mwaa_env = mwaa.CfnEnvironment(
        self,
        "AirflowEnvironment",
        name=airflow_env_name,
        airflow_version="3.0.6",
        environment_class="mw1.micro",
        execution_role_arn=mwaa_role.role_arn,
        source_bucket_arn=dags_bucket.bucket_arn,
        dag_s3_path="dags",
        network_configuration=network_config,
        logging_configuration=logging_config,
        webserver_access_mode="PRIVATE_ONLY",
        min_workers=1,
        max_workers=1,
    )

    # ---------------------------------------------------------------------
    # 7️⃣ AIRFLOW CONFIG (UNCHANGED)
    # ---------------------------------------------------------------------
    mwaa_env.add_override(
        "Properties.AirflowConfigurationOptions",
        {
            "core.load_default_connections": "False",
            "core.load_examples": "False",
            "core.default_timezone": "utc",
        },
    )

    mwaa_env.node.add_dependency(dags_bucket)
    mwaa_env.node.add_dependency(mwaa_role)
    mwaa_env.node.add_dependency(mwaa_sg)

when used

    # AmazonMWAASvcRolePolicy DOES NOT EXIST / NOT ATTACHABLE
    # mwaa_role.add_managed_policy(
    #     iam.ManagedPolicy.from_aws_managed_policy_name("AmazonMWAASvcRolePolicy")
    # )

got error airflow failed: ToolkitError: The stack named store-airflow failed creation, it may need to be manually deleted from the AWS console: ROLLBACK_COMPLETE: Resource handler returned message: "Policy arn:aws:iam::aws:policy/AmazonMWAASvcRolePolicy does not exist or is not attachable. (Service: Iam, Status Code: 404, Request ID: 0810ff43-1415-46ce-9186-2e314dbea306) (SDK Attempt Count: 1)" (RequestToken: 0e1d97be-151e-1d53-7602-a02c25634b48, HandlerErrorCode: NotFound)

please do suggest cdk code for this error as well for non-stabilizied error with vpc cdk

1 Answer
0
Accepted Answer

The error you're encountering is because the managed policy "AmazonMWAASvcRolePolicy" doesn't exist or isn't attachable. You've already correctly commented out this policy in your code, which is the right approach.

For Amazon MWAA (Managed Workflows for Apache Airflow), you need to ensure your execution role has the appropriate permissions. Instead of using a non-existent managed policy, you should create the necessary permissions directly in your IAM role.

Here's a suggested fix for your MWAA execution role section:

# MWAA EXECUTION ROLE
mwaa_role = iam.Role(
self,
"MwaaExecutionRole",
role_name=f"{airflow_env_name}-exec-role",
assumed_by=iam.CompositePrincipal(
iam.ServicePrincipal("airflow.amazonaws.com"),
iam.ServicePrincipal("airflow-env.amazonaws.com"),
),
path="/service-role/",
)

# Add MWAA service-specific permissions
mwaa_role.add_to_policy(
iam.PolicyStatement(
actions=[
"airflow:PublishMetrics",
"airflow:CreateWebLoginToken",
"airflow:GetEnvironment",
],
resources=[f"arn:aws:airflow:{self.region}:{self.account}:environment/{airflow_env_name}"]
)
)

# Existing S3 access
mwaa_role.add_managed_policy(
iam.ManagedPolicy.from_aws_managed_policy_name("AmazonS3ReadOnlyAccess")
)

dags_bucket.grant_read_write(mwaa_role)

Regarding the non-stabilized error with VPC CDK, this is likely related to the VPC creation process not completing before MWAA tries to use it. To address this, you can add explicit dependencies:

# Add explicit dependency on VPC
mwaa_env.node.add_dependency(store_vpc)

Additionally, to ensure your VPC is properly configured for MWAA, make sure:

  1. Your VPC has at least two private subnets in different Availability Zones
  2. Your private subnets have NAT Gateways for outbound internet access
  3. Your security groups allow the necessary traffic

If you're creating the VPC in the same stack, you might want to consider using a more explicit VPC configuration:

vpc = ec2.Vpc(
self,
"MwaaVpc",
max_azs=2,
nat_gateways=1,
subnet_configuration=[
ec2.SubnetConfiguration(
name="Public",
subnet_type=ec2.SubnetType.PUBLIC,
cidr_mask=24
),
ec2.SubnetConfiguration(
name="Private",
subnet_type=ec2.SubnetType.PRIVATE_WITH_EGRESS,
cidr_mask=24
)
]
)

This ensures that your VPC has the proper configuration for MWAA to function correctly. The key is to make sure you have at least two private subnets with outbound internet access through NAT gateways.
Sources
cloud quest - cloud infrastructure with generative AI code errors | AWS re:Post
aws-openapigateway-lambda - AWS Solutions Constructs

answered 9 months ago

AWS
EXPERT

reviewed 9 months ago

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.