aws-cloudformation / aws-cloudformation-resource-providers-networkfirewall

https://aws.amazon.com/network-firewall/
Apache License 2.0
4 stars 10 forks source link

Sort EndpointIds by AZ to enable resource composability #15

Open x6j8x opened 3 years ago

x6j8x commented 3 years ago

Hi,

currently it is not possible to instantiate a working, self-contained, multi-AZ CloudFormation stack containing a AWS::NetworkFirewall::Firewall resource.

The main reason is the current behaviour that the EndpointIds attribute does not guarantee any particular order. This makes it impossible to create the AWS::EC2::Route resources necessary to ensure that traffic from (or to) the workload subnets actually traverses the Firewall (without resorting to "shell-script" CustomResource Lambdas as workaround).

It would be a great improvement if the EndpointIds would return its entries at least in "natural" AZ order (a-z).

This way the user would be enabled to actually pick the necessary entries from the list with standard CloudFormation intrinsic functions (Fn::Split, Fn::Select). The format of AZ:EndpointId can stay the same as it can be easily deconstructed using the same functions.

As a result users would be able to create self-contained CloudFormation stacks with working routing and without using CustomResource Lambdas.

Best,

Sascha

Dunmail commented 3 years ago

+1

adamspicer commented 3 years ago

+1 See workaround lambda here: https://github.com/aws-samples/aws-networkfirewall-cfn-templates/blob/main/distributed_architecture/anfw-distributed-2az-template.yaml

Wittionary commented 2 years ago

@yiweiy-aws How can we make headway on this issue?

kallu commented 2 years ago

I would very much like to see either ordered list or even option to use attribute to select the endpoint for given AZ. While waiting that, you actually can pick endpoint from the list for given AZ using combination of Splits and Joins. It doesn't look pretty but works. Below is an example how to pick FW endpoint for AZ-A to setup default route though FW.

 InspectionTGWRouteA:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref InspectionTGWRouteTableA
      DestinationCidrBlock: '0.0.0.0/0'
      VpcEndpointId: !Select [ 0, !Split [ ',', !Select [ 1 , !Split [ 'a:', !Join [ ',', !GetAtt NetworkFW.EndpointIds ] ] ] ] ]
rshayman commented 2 years ago

+1 for a separate return value per AZ

I cannot understand why this is taking so long to fix. It is an obvious oversights.

karl-barbour commented 1 year ago

This is a real oversight, +1 to separate list

edc1934 commented 1 year ago

+1

rene84 commented 1 year ago

yes please!

youssouphSagna commented 1 year ago

+1

hugo-galindo commented 1 year ago

+1

andrewjroth commented 10 months ago

This right here is why people get so frustrated with CloudFormation. It is so limited in processing that you need to do silly things to get it to work properly for basic things. Like "how do I deploy a network firewall in two zones?" "oh, you need to do some outside processing for that." :face_exhaling:

The fact that the "accepted answer" for AWS CloudFormation deployment of AWS Network Firewall is "oh, there's an issue being tracked for that" ... over three years old ... is just real frustrating.

prli commented 9 months ago

It would be great if AWS supports this out-of-the-box.

for anyone looking to sort endpointIds by AZ, and not involve a CustomResource lambda, check out this stackoverflow for details. the idea is to use Fn.join and Fn.split to do some sorting.

posting the sorting function below as well.

/** this is actually some voodoo magic here...
 * we select firewall subnet from vpc, assuming (hoping...) vpc.availabilityZones are in order of AZs
 * this means we require `firewall.attrEndpointIds` to be in order.
 * however, `firewall.attrEndpointIds` is not in order for some inexplicable reasons.
 * https://github.com/aws-cloudformation/aws-cloudformation-resource-providers-networkfirewall/issues/15
 * `firewall.attrEndpointIds` is a List-encoded tokens - https://docs.aws.amazon.com/cdk/v2/guide/tokens.html#tokens_list
 * in order to sort `firewall.attrEndpointIds` in order of AZs, we need to use a combination of splits and joins.
 * AWS AZs are ordered lexicographically starting at `a`, and "assuming" vpc.availabilityZones are returned in order of AZs
 * to sort `firewall.attrEndpointIds` as a List-encoded tokens, the following steps are taken:
 * 1. join `firewall.attrEndpointIds` as a string token with `,` as delimiter.
 *   -> "us-west-2c:vpce-111122223333,us-west-2a:vpce-987654321098,us-west-2b:vpce-012345678901"
 * 2. split the resulting string token `azWithFirewallVpcEndpointIds` with `a:` for the first AZ (`b:` and `c:` subsequently).
 *   -> [ "us-west-2c:vpce-111122223333,us-west-2", "vpce-987654321098,us-west-2b:vpce-012345678901" ]
 * 3. select 2nd element as it contains the endpoint ID, along with some extra garbage and store it into var `temp`
 *   -> "vpce-987654321098,us-west-2b:vpce-012345678901"
 * 4. split `temp` by `,` as that was the joined list delimiter
 *   -> [ "vpce-987654321098", "us-west-2b:vpce-012345678901" ]
 * 5. select 1st element as it contains the endpoint ID without any extra garbage now
 *   -> "vpce-987654321098"
 * https://carriagereturn.nl/aws/cloudformation/firewall/endpoint/routing/2022/05/22/firewall-endpoints.html
 */
getFirewallEndpointsInOrder(firewall: fw.CfnFirewall): string[] {
    const firewallVpcEndpointIds: string[] = [];
    const azWithFirewallVpcEndpointIds = cdk.Fn.join(',', firewall.attrEndpointIds);
    const aZs = ['a', 'b', 'c', 'd', 'e', 'f']; // max amount of AZs in AWS (us-east-1)
    for (let i = 0; i < this.vpc.availabilityZones.length; i++) {
        const temp = cdk.Fn.split(`${aZs[i]}:`, azWithFirewallVpcEndpointIds, 2)[1];
        const firewallVpcEndpointId = cdk.Fn.split(',', temp, 2)[0];
        firewallVpcEndpointIds.push(firewallVpcEndpointId);
    }
    return firewallVpcEndpointIds;
}
robbie-hst commented 9 months ago

+1

cactusglitch commented 8 months ago

very sad to say; We're in 2024, still haven't found better answer. 👏 thanks to https://carriagereturn.nl/aws/cloudformation/firewall/endpoint/routing/2022/05/22/firewall-endpoints.html

federicodallafontana commented 5 months ago

+1

IpsumAudite commented 5 months ago

Insane that they have yet to fix this! One of the links recommended above has a simple (if clunky) solution that worked for me with no changes to it at all, thanks @kallu!!

VpcEndpointId: !Select [ 0, !Split [ ',', !Select [ 1 , !Split [ 'a:', !Join [ ',', !GetAtt {NETWORK_FIREWALL}.EndpointIds ] ] ] ] ]

sciarrilli commented 4 months ago

+1