Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sort EndpointIds by AZ to enable resource composability #15

Open
x6j8x opened this issue Jan 18, 2021 · 17 comments
Open

Sort EndpointIds by AZ to enable resource composability #15

x6j8x opened this issue Jan 18, 2021 · 17 comments

Comments

@x6j8x
Copy link

x6j8x commented Jan 18, 2021

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
Copy link

Dunmail commented Jul 26, 2021

+1

@adamspicer
Copy link

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

@Wittionary
Copy link

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

@kallu
Copy link

kallu commented Apr 15, 2022

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
Copy link

rshayman commented Aug 8, 2022

+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
Copy link

This is a real oversight, +1 to separate list

@edc1934
Copy link

edc1934 commented Dec 23, 2022

+1

@rene84
Copy link

rene84 commented Mar 6, 2023

yes please!

rene84 added a commit to rene84/aws-cloudformation-resource-providers-networkfirewall that referenced this issue Mar 6, 2023
Return EndpointIds sorted by AZ in the !GetAtt response for AWS::NetworkFirewall::Firewall see aws-cloudformation#15
@youssouphSagna
Copy link

+1

1 similar comment
@hugo-galindo
Copy link

+1

@andrewjroth
Copy link

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." 😮‍💨

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
Copy link

prli commented Dec 11, 2023

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
Copy link

+1

@cactusglitch
Copy link

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
Copy link

+1

@IpsumAudite
Copy link

IpsumAudite commented May 2, 2024

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
Copy link

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests