diff --git a/packages/graphql-mesh-server/lib/fargate.ts b/packages/graphql-mesh-server/lib/fargate.ts index 17dc9e89..54805cf3 100644 --- a/packages/graphql-mesh-server/lib/fargate.ts +++ b/packages/graphql-mesh-server/lib/fargate.ts @@ -78,6 +78,11 @@ export interface MeshServiceProps { * Defaults to 3 */ blockedIpv6Priority?: number; + /** + * If true, block all access to the endpoint. Use in conjunction with allowedIps to block public access + * @default false + */ + blockAll?: boolean; /** * List of AWS Managed rules to add to the WAF */ @@ -97,9 +102,14 @@ export interface MeshServiceProps { */ rateLimitPriority?: number; /** - * List of IPv4 addresses that can bypass rate limiting. + * The waf allowed ip rule priority. + * Defaults to 2 + */ + allowedIpPriority?: number; + /** + * List of IPv4 addresses that can bypass all WAF block lists. */ - rateLimitBypassList?: string[]; + allowedIps?: string[]; /** * Pass custom cpu scaling steps * Default value: @@ -253,8 +263,8 @@ export class MeshService extends Construct { this.service = fargateService.service; this.loadBalancer = fargateService.loadBalancer; - const rateLimitBypassList = new CfnIPSet(this, "RateLimitBypassList", { - addresses: props.rateLimitBypassList || [], + const allowedIpList = new CfnIPSet(this, "allowList", { + addresses: props.allowedIps || [], ipAddressVersion: "IPV4", scope: "REGIONAL", description: "List of IPs that are whitelisted from rate limiting", @@ -274,47 +284,108 @@ export class MeshService extends Construct { description: "List of IPv6s blocked by WAF", }); - const defaultRules: CfnWebACL.RuleProperty[] = [ - { - name: "IPBlockList", - priority: 2 || props.blockedIpPriority, - statement: { - ipSetReferenceStatement: { - arn: blockedIpList.attrArn, + const defaultRules: CfnWebACL.RuleProperty[] = props.blockAll + ? [ + { + name: "BlockNonAllowedIps", + priority: props.allowedIpPriority || 2, + statement: { + notStatement: { + statement: { + ipSetReferenceStatement: { + arn: allowedIpList.attrArn, + ipSetForwardedIpConfig: { + fallbackBehavior: "MATCH", + headerName: "X-Forwarded-For", + position: "FIRST", + }, + }, + }, + }, + }, + visibilityConfig: { + cloudWatchMetricsEnabled: true, + metricName: "IPAllowList", + sampledRequestsEnabled: true, + }, + action: { + block: {}, + }, }, - }, - visibilityConfig: { - cloudWatchMetricsEnabled: true, - metricName: "IPBlockList", - sampledRequestsEnabled: true, - }, - action: { - block: {}, - }, - }, - { - name: "IPv6BlockList", - priority: 3 || props.blockedIpPriority, - statement: { - ipSetReferenceStatement: { - arn: blockedIpv6List.attrArn, + ] + : [ + { + name: "IPAllowList", + priority: props.allowedIpPriority || 2, + statement: { + ipSetReferenceStatement: { + arn: allowedIpList.attrArn, + ipSetForwardedIpConfig: { + fallbackBehavior: "MATCH", + headerName: "X-Forwarded-For", + position: "FIRST", + }, + }, + }, + visibilityConfig: { + cloudWatchMetricsEnabled: true, + metricName: "IPAllowList", + sampledRequestsEnabled: true, + }, + action: { + allow: {}, + }, }, - }, - visibilityConfig: { - cloudWatchMetricsEnabled: true, - metricName: "IPv6BlockList", - sampledRequestsEnabled: true, - }, - action: { - block: {}, - }, - }, - ]; + { + name: "IPBlockList", + priority: props.blockedIpPriority || 3, + statement: { + ipSetReferenceStatement: { + arn: blockedIpList.attrArn, + ipSetForwardedIpConfig: { + fallbackBehavior: "MATCH", + headerName: "X-Forwarded-For", + position: "FIRST", + }, + }, + }, + visibilityConfig: { + cloudWatchMetricsEnabled: true, + metricName: "IPBlockList", + sampledRequestsEnabled: true, + }, + action: { + block: {}, + }, + }, + { + name: "IPv6BlockList", + priority: (props.blockedIpPriority || 3) + 1, + statement: { + ipSetReferenceStatement: { + arn: blockedIpv6List.attrArn, + ipSetForwardedIpConfig: { + fallbackBehavior: "MATCH", + headerName: "X-Forwarded-For", + position: "FIRST", + }, + }, + }, + visibilityConfig: { + cloudWatchMetricsEnabled: true, + metricName: "IPv6BlockList", + sampledRequestsEnabled: true, + }, + action: { + block: {}, + }, + }, + ]; - if (props.rateLimit) { + if (props.rateLimit && !props.blockAll) { defaultRules.push({ name: "RateLimit", - priority: 10 || props.rateLimitPriority, + priority: props.rateLimitPriority || 10, statement: { rateBasedStatement: { aggregateKeyType: "FORWARDED_IP", @@ -323,20 +394,6 @@ export class MeshService extends Construct { fallbackBehavior: "MATCH", headerName: "X-Forwarded-For", }, - scopeDownStatement: { - notStatement: { - statement: { - ipSetReferenceStatement: { - arn: rateLimitBypassList.attrArn, - ipSetForwardedIpConfig: { - fallbackBehavior: "MATCH", - headerName: "X-Forwarded-For", - position: "FIRST", - }, - }, - }, - }, - }, }, }, visibilityConfig: { diff --git a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts index d49f9fbe..5803d0c3 100644 --- a/packages/graphql-mesh-server/lib/graphql-mesh-server.ts +++ b/packages/graphql-mesh-server/lib/graphql-mesh-server.ts @@ -103,6 +103,11 @@ export type MeshHostingProps = { * Defaults to 3 */ blockedIpv6Priority?: number; + /** + * If true, block all access to the endpoint. Use in conjunction with allowedIps to block public access + * @default false + */ + blockAll?: boolean; /** * List of AWS Managed rules to add to the WAF */ @@ -122,9 +127,9 @@ export type MeshHostingProps = { */ rateLimitPriority?: number; /** - * List of IPv4 addresses that can bypass rate limiting. + * List of IPv4 addresses that can bypass all WAF block lists. */ - rateLimitBypassList?: string[]; + allowedIps?: string[]; /** * Enable / disable container insights * Defaults to true