This guide outlines the process of consolidating multiple AWS Application Load Balancers (ALBs) managed by Kubernetes Ingress resources into a single shared Ingress ALB. It also covers integrating AWS WAF for enhanced security on your subdomains and services, specifically focusing on how to translate Ingress-level CIDR restrictions into WAF rules.
Table of Contents
1. Introduction
Managing numerous ALBs can lead to increased operational overhead and costs. This guide will walk you through fetching existing Ingress configurations, modifying them to use a shared ALB, configuring access logs, and attaching WAF to protect your applications, specifically handling domain-based IP restrictions.
2. Prerequisites
Before you begin, ensure you have the following:
- Kubernetes Cluster: An EKS cluster or a Kubernetes cluster with the AWS Load Balancer Controller installed and configured.
kubectl: Configured to connect to your Kubernetes cluster.jq: A lightweight and flexible command-line JSON processor.- AWS CLI: Configured with appropriate permissions to manage ALBs, S3, and WAF.
- IAM Permissions: Sufficient IAM permissions to create/modify Ingress resources, S3 buckets/policies, and WAF Web ACLs.
- S3 Bucket: An S3 bucket for storing ALB access logs.
3. Identifying Existing Ingress Resources and CIDRs
First, let's gather information about your current Ingress configurations and any specific inbound CIDR restrictions. This helps in understanding your current setup and planning the migration.
Fetch All Ingress Files
kubectl get ingress --all-namespaces -o yaml > all-ingress.yamlFetch All Inbound CIDRs Used by ALBs
kubectl get ingress --all-namespaces -o json | \
jq -r '.items[] | select(.metadata.annotations."alb.ingress.kubernetes.io/inbound-cidrs") |
"\(.metadata.namespace)/\(.metadata.name): \(.metadata.annotations."alb.ingress.kubernetes.io/inbound-cidrs")"' \
> inbound-cidrs.txtReview inbound-cidrs.txt to understand which services currently have IP restrictions. You'll use this information to create WAF IP sets and rules.
4. Planning Your Migration
Before making changes:
- Shared ALB Name: e.g.,
shared-application-alb - Consolidation Strategy: Decide which ingress resources migrate.
- DNS Updates: Prepare to repoint DNS to the new shared ALB CNAME.
- WAF Rules: Derived from
inbound-cidrs.txt.
5. Modifying Ingress Resources for a Shared ALB
Example Ingress Modification
Existing ingress file (SANITIZED)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: portal-service
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/subnets: {{SUBNET_ID_1}},{{SUBNET_ID_2}}
alb.ingress.kubernetes.io/certificate-arn: {{ACM_CERT_ARN}}
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
spec:
rules:
- host: "{{DOMAIN_1}}"
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: portal-service-backend
port:
number: 443New ingress file (SANITIZED)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: new-portal-service
namespace: default
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
alb.ingress.kubernetes.io/group.name: shared-application-alb
alb.ingress.kubernetes.io/backend-protocol: HTTP
alb.ingress.kubernetes.io/certificate-arn: "{{ACM_CERT_ARN}}"
alb.ingress.kubernetes.io/healthcheck-protocol: HTTP
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'
alb.ingress.kubernetes.io/ssl-redirect: '443'
alb.ingress.kubernetes.io/subnets: {{SUBNET_ID_1}},{{SUBNET_ID_2}}
alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=3000
alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS13-1-2-2021-06
alb.ingress.kubernetes.io/wafv2-acl-arn: {{WAF_ACL_ARN}}
spec:
rules:
- host: {{DOMAIN_1}}
http:
paths:
- backend:
service:
name: portal-service-backend
port:
number: 443
path: /
pathType: PrefixExplanation of Changes: (No confidential data → unchanged)
5. S3 Bucket Policy for Access Logs
(Sanitized: ELB account ID + AWS account ID)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::{{ELB_ACCOUNT_ID}}:root"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::your-access-log-bucket-name/AWSLogs/{{ACCOUNT_ID}}/*",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
}
}
]
}CFN and json builder
AWSTemplateFormatVersion: '2010-09-09'
Description: 'WAF WebACL for EKS ALBs with managed rule groups and IP set references'
Parameters:
EnvironmentName:
Type: String
Default: UAT
Description: Deployment environment (e.g. UAT, PROD)
OfficeNetworkIPSetARN:
Type: String
Default: '{{WAF_IPSET_OFFICE_ARN}}'
Description: ARN of the allowed office network IP Set
PartnerNetworkIPSetARN:
Type: String
Default: '{{WAF_IPSET_PARTNER_ARN}}'
Description: ARN of the partner network IP Set
Resources:
OfficeNetworkIPSet:
Type: AWS::WAFv2::IPSet
Properties:
Name: "office-network-ip-set"
Description: "Allowed office network CIDRs for UAT ALBs"
Scope: REGIONAL
IPAddressVersion: IPV4
Addresses:
- "{{CIDR_OFFICE_1}}" # Example CIDR
- "{{CIDR_OFFICE_2}}" # Example CIDR
EKSWAFWebACL:
Type: AWS::WAFv2::WebACL
Properties:
Name: !Sub 'EKS-WAF-ALB-${EnvironmentName}'
Scope: REGIONAL
Description: WAF for EKS ALBs
DefaultAction:
Block: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: !Sub 'EKS-WAF-ALB-${EnvironmentName}'
Rules:
- Name: DomainSpecificAccessRules
Priority: 0
Statement:
OrStatement:
Statements:
- AndStatement:
Statements:
- ByteMatchStatement:
SearchString: "{{DOMAIN_DASHBOARD}}"
FieldToMatch:
SingleHeader:
Name: "host"
TextTransformations:
- Priority: 0
Type: "LOWERCASE"
PositionalConstraint: "EXACTLY"
- IPSetReferenceStatement:
Arn: !GetAtt OfficeNetworkIPSet.Arn
IPSetForwardedIPConfig:
HeaderName: "X-Forwarded-For"
FallbackBehavior: "MATCH"
Position: "FIRST"
- AndStatement:
Statements:
- ByteMatchStatement:
SearchString: "{{DOMAIN_CUSTOMER_PORTAL}}"
FieldToMatch:
SingleHeader:
Name: "host"
TextTransformations:
- Priority: 0
Type: "LOWERCASE"
PositionalConstraint: "EXACTLY"
- IPSetReferenceStatement:
Arn: !Ref PartnerNetworkIPSetARN
IPSetForwardedIPConfig:
HeaderName: "X-Forwarded-For"
FallbackBehavior: "MATCH"
Position: "FIRST"
- ByteMatchStatement:
SearchString: "{{DOMAIN_API}}"
FieldToMatch:
SingleHeader:
Name: "host"
TextTransformations:
- Priority: 0
Type: "LOWERCASE"
PositionalConstraint: "EXACTLY"
Action:
Allow: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: DomainSpecificAccessRule
- Name: AWS-AWSManagedRulesAnonymousIpList
Priority: 1
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesAnonymousIpList
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesAnonymousIpList
- Name: AWS-AWSManagedRulesAmazonIpReputationList
Priority: 2
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesAmazonIpReputationList
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesAmazonIpReputationList
- Name: AWS-AWSManagedRulesKnownBadInputsRuleSet
Priority: 3
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesKnownBadInputsRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesKnownBadInputsRuleSet
- Name: AWS-AWSManagedRulesLinuxRuleSet
Priority: 4
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesLinuxRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesLinuxRuleSet
- Name: AWS-AWSManagedRulesPHPRuleSet
Priority: 5
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesPHPRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesPHPRuleSet
- Name: AWS-AWSManagedRulesUnixRuleSet
Priority: 6
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesUnixRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesUnixRuleSet
- Name: AWS-AWSManagedRulesSQLiRuleSet
Priority: 7
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesSQLiRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesSQLiRuleSet
- Name: AWS-AWSManagedRulesWindowsRuleSet
Priority: 8
Statement:
ManagedRuleGroupStatement:
VendorName: AWS
Name: AWSManagedRulesWindowsRuleSet
OverrideAction:
None: {}
VisibilityConfig:
SampledRequestsEnabled: true
CloudWatchMetricsEnabled: true
MetricName: AWS-AWSManagedRulesWindowsRuleSet
Outputs:
WebACLId:
Description: The ID of the WAF WebACL
Value: !GetAtt EKSWAFWebACL.Id
Export:
Name: !Sub '${AWS::StackName}-WebACLId'✅ JSON Rule Builder for all allowed
{
"Name": "AllowPubliclyAccessibleServices",
"Priority": 2,
"Statement": {
"OrStatement": {
"Statements": [
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_PUBLIC_CKYC}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_PUBLIC_LANDING}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_GUEST_VIEW_DOCS}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_PUBLIC_API_GATEWAY}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_VENDOR_INFO}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_EXTERNAL_VENDOR_PORTAL}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_CIBIL}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_CONFIG_PORTAL_API}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_DATA_ANALYTICS}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_NEW_APP_RELEASE}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_UTIL_SERVICES}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_HR_VERIFICATION}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_CRON}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_PAYMENT_CLIENT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SECURE_FORMS}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } }
]
}
},
"Action": { "Allow": {} },
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "AllowPubliclyAccessibleServices"
}
}✅ ** DomainAndIPSetRoutingRule for restricted service domains**
{
"Name": "DomainAndIPSetRoutingRule",
"Priority": 0,
"Action": { "Allow": {} },
"Statement": {
"OrStatement": {
"Statements": [
{
"AndStatement": {
"Statements": [
{
"OrStatement": {
"Statements": [
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_CHATBOT_SERVER_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_CHATBOT_PORTAL_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_PAY_SERVER_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_AGENT_PAYMENT_COLLECTION_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SYNORIQ_LMS_MW_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SYNC_YUBI_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_WEBSITE_CRON_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_DIGITAL_PAYMENT_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SSFB_API_PRE_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_IDFC_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_LOS_CO_LENDER_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SCORECARD_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_NEW_BIKE_BAZAAR_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_APP_SUAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_GBL_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_GBL_BACKEND_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_GBL_PAYMENTS_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_TEST_SERVER_NET}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_NACH_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_NACH_SERVER_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_MUTHOOT_DISBURSAL_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_MUTHOOT_CUSTOMER_COLLECTION_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_MIDDLEWARE_UAT_EKS}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_PA_INSURANCE_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_YUBI_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_AUTH_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_MANDATE_INTEGRATIONS_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_MANDATE_CRON_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SFDC_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_EKYC_ENCRYPTION_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_EKYC_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_PUSH_YUBI_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SSFB_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } }
]
}
},
{
"IPSetReferenceStatement": {
"ARN": "{{WAF_IPSET_OFFICE_UAT_ARN}}"
}
}
]
}
},
{
"AndStatement": {
"Statements": [
{
"OrStatement": {
"Statements": [
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_BUSINESS_RULES_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_SFDC_NEW_MW_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } }
]
}
},
{
"IPSetReferenceStatement": {
"ARN": "{{WAF_IPSET_BUSINESS_RULES_UAT_ARN}}"
}
}
]
}
},
{
"AndStatement": {
"Statements": [
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_DIGITAL_JOURNEY_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "IPSetReferenceStatement": { "ARN": "{{WAF_IPSET_DIGITAL_JOURNEY_UAT_ARN}}" } }
]
}
},
{
"AndStatement": {
"Statements": [
{ "ByteMatchStatement": { "SearchString": "{{DOMAIN_FINONE_LMS_API_UAT}}", "FieldToMatch": { "SingleHeader": { "Name": "host" } }, "TextTransformations": [{ "Priority": 0, "Type": "LOWERCASE" }], "PositionalConstraint": "EXACTLY" } },
{ "IPSetReferenceStatement": { "ARN": "{{WAF_IPSET_FINONE_LMS_API_UAT_ARN}}" } }
]
}
}
]
}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "DomainAndIPSetRoutingRule"
}
}Troubleshoot WAF 403 Errors
The curl -vk https://{{DOMAIN_CUSTOMER_PORTAL}}/ command is used to check whether your AWS WAF, ALB, or Ingress routing is working properly.
Test WITHOUT DNS mapping
curl -vk https://{{ALB_HOSTNAME_SHARED}} \
-H "Host: {{DOMAIN_APP_UAT}}"Flag meanings:
-v→ verbose output-k→ ignore SSL verification- URL → domain served behind WAF/ALB
Example 404 Error
curl -v {{DOMAIN_APP_UAT}}
* TLSv1.2 (IN), TLS header, Supplemental data (23):
< HTTP/2 404
< server: awselb/2.0
< date: Wed, 15 Oct 2025 08:19:04 GMT
< content-type: text/plain; charset=utf-8
< content-length: 0
<
* Connection #0 to host {{ALB_HOSTNAME_SHARED_UAT}}A 404 here was due to unhealthy target group caused by Ingress misconfiguration.
7. Verification and Testing
After applying the changes, verify everything end-to-end.
✔ Check ALB Status
kubectl get ingress -n <your-namespace> new-portal-service \
-o jsonpath='{.status.loadBalancer.ingress[0].hostname}'You should see:
{{ALB_HOSTNAME_SHARED}}✔ Access Logs
Check your S3 bucket to confirm logs are delivered to:
s3://{{S3_ALB_LOG_BUCKET}}/AWSLogs/{{ACCOUNT_ID}}/✔ WAF Association
In AWS WAF → Web ACLs → {{WAF_ACL_NAME}}, verify:
- The shared ALB is listed under Associated AWS Resources
✔ Application Connectivity
Test all services now routed via shared ALB:
- HTTP
- HTTPS
- All paths
/api,/login,/health - All hosts (
Host:headers)
Example test:
curl -vk https://{{ALB_HOSTNAME_SHARED}} \
-H "Host: {{DOMAIN_CUSTOMER_PORTAL}}"✔ WAF Rule Testing
Test your IP-based WAF logic:
- From allowed IP → must load normally
- From blocked IP → expect WAF 403
Examples:
# Allowed office network
curl -v https://{{DOMAIN_DASHBOARD}} --interface {{OFFICE_IP}}
# Blocked (home network)
curl -v https://{{DOMAIN_DASHBOARD}}Test public endpoints like:
https://{{DOMAIN_PUBLIC_API}}8. Troubleshooting
✔ Ingress Events
kubectl describe ingress <ingress-name>Look for errors from AWS Load Balancer Controller.
✔ Controller Logs
kubectl logs -n kube-system deploy/aws-load-balancer-controller