Skip to content

elb_target_group strips HealthCheckPath and Matcher when protocol is TCP but health_check_protocol is HTTP/HTTPS #2462

Description

@rudolfkastl

Summary

When creating or modifying an AWS Network Load Balancer (NLB) Target Group, AWS allows configuring Layer 7 health checks (HTTP/HTTPS) for Layer 4 (TCP) target groups.

However, the elb_target_group module incorrectly strips the health_check_path (HealthCheckPath) and successful_response_codes (Matcher) parameters from the Boto3 payload if the main target group protocol is TCP or TLS, completely ignoring the health_check_protocol value.

This causes the AWS API to reject the request because Layer 7 health checks strictly require a path and return codes.

Expected Results

The target group should be created successfully with a TCP routing protocol and an HTTPS health check querying the / path and expecting a 200-399 or 401 HTTP status code.

Actual Results

The module fails with a Boto3 ValidationError because it silently removes the L7 health check parameters before making the API call:

fatal: [localhost]: FAILED! => changed=false 
  boto3_version: 1.40.71
  botocore_version: 1.40.71
  error:
    code: ValidationError
    message: Path and return code are required for layer 7 health checks.
    type: Sender
  msg: 'Couldn''t update target group: An error occurred (ValidationError) when calling the ModifyTargetGroup operation: Path and return code are required for layer 7 health checks.'

Root Cause & Proposed Fix

The parameter sanitization logic inside the module evaluates the main Target Group protocol instead of the health_check_protocol when deciding whether to keep HTTP-specific parameters.

Somewhere in the payload mapping logic, it does something equivalent to this:

# CURRENT FLAWED LOGIC:
if protocol in ['TCP', 'TLS', 'UDP', 'TCP_UDP']:
    target_group_args.pop('HealthCheckPath', None)
    target_group_args.pop('Matcher', None)

Proposed Fix: The stripping logic must evaluate the health_check_protocol parameter, not the main routing protocol, because AWS fully supports HTTP/HTTPS health checks for TCP target groups:

# SUGGESTED LOGIC:
health_check_proto = module.params.get('health_check_protocol', '')
if health_check_proto.upper() not in ['HTTP', 'HTTPS']:
    target_group_args.pop('HealthCheckPath', None)
    target_group_args.pop('Matcher', None)

Environment Info

  • Ansible version: ansible-13.7.0-1.fc44.noarch
  • Collection version: amazon.aws 10.1.0
  • Boto3 version: 1.40.71

Issue Type

Bug Report

Component Name

elb_target_group

Ansible Version

$ ansible --version

13.7.0

Collection Versions

$ ansible-galaxy collection list

amazon.aws 10.1.0

AWS SDK versions

$ pip show boto boto3 botocore

Name: boto3
Version: 1.40.71
Summary: The AWS SDK for Python
Home-page: https://github.com/boto/boto3
Author: Amazon Web Services
Author-email:
License: Apache-2.0
Location: /home/rkastl/.local/lib/python3.14/site-packages
Requires: botocore, jmespath, s3transfer
Required-by:

Name: botocore
Version: 1.40.71
Summary: Low-level, data-driven core of boto 3.
Home-page: https://github.com/boto/botocore
Author: Amazon Web Services
Author-email:
License: Apache-2.0
Location: /home/rkastl/.local/lib/python3.14/site-packages
Requires: jmespath, python-dateutil, urllib3
Required-by: boto3, s3transfer

Configuration

$ ansible-config dump --only-changed

OS / Environment

Fedora 44

Steps to Reproduce

Steps to Reproduce

Attempt to create a TCP Target Group with an HTTPS health check using the following task:

- name: "AWS NLB: Create Target Group with L7 Health Check"
  amazon.aws.elb_target_group:
    region: "us-east-1"
    name: "my-nlb-target-group"
    vpc_id: "vpc-123456789"
    protocol: "TCP"                 # Main Protocol
    port: 9200
    health_check_protocol: "HTTPS"  # Health Check Protocol
    health_check_path: "/"
    successful_response_codes: "200-399,401"
    state: present

Expected Results

Root Cause & Proposed Fix

The parameter sanitization logic inside the module evaluates the main Target Group protocol instead of the health_check_protocol when deciding whether to keep HTTP-specific parameters.

Somewhere in the payload mapping logic, it does something equivalent to this:

# CURRENT FLAWED LOGIC:
if protocol in ['TCP', 'TLS', 'UDP', 'TCP_UDP']:
    target_group_args.pop('HealthCheckPath', None)
    target_group_args.pop('Matcher', None)

Proposed Fix: The stripping logic must evaluate the health_check_protocol parameter, not the main routing protocol, because AWS fully supports HTTP/HTTPS health checks for TCP target groups:

# SUGGESTED LOGIC:
health_check_proto = module.params.get('health_check_protocol', '')
if health_check_proto.upper() not in ['HTTP', 'HTTPS']:
    target_group_args.pop('HealthCheckPath', None)
    target_group_args.pop('Matcher', None)

Actual Results

See above.

Code of Conduct

  • I agree to follow the Ansible Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions