Skip to content

fix: parse hmac-auth signed_headers from Secret as a header list#436

Open
shreemaan-abhishek wants to merge 1 commit into
masterfrom
fix/hmac-signed-headers-secret-parsing
Open

fix: parse hmac-auth signed_headers from Secret as a header list#436
shreemaan-abhishek wants to merge 1 commit into
masterfrom
fix/hmac-signed-headers-secret-parsing

Conversation

@shreemaan-abhishek

@shreemaan-abhishek shreemaan-abhishek commented Jul 19, 2026

Copy link
Copy Markdown

What this PR does

translateConsumerHMACAuthPlugin read signed_headers from a Secret by ranging over its raw bytes:

signedHeadersRaw := sec.Data["signed_headers"] // []byte
for _, b := range signedHeadersRaw {           // ranges over bytes
    signedHeaders = append(signedHeaders, string(b)) // one 1-char entry per byte
}

Ranging over a []byte yields (index, byte), so "X-Date,Host" became ["X","-","D","a","t","e",",","H","o","s","t"]. The data-plane hmac-auth policy then bound those single-character names into the signature, which never match real headers, so the operator's intended headers were silently not enforced as part of the HMAC signature. Only the secretRef path was affected; the inline Value path already passes a []string.

Fix

  • Split the signed_headers value on commas and trim entries.
  • Surface strconv.ParseInt failures for clock_skew and max_req_body instead of discarding them, so a typo no longer coerces silently to a default.

Tests

  • New unit tests: signed_headers from a Secret yields the correct header list; an unparseable clock_skew is rejected.

Paired open-source PR: apache/apisix-ingress-controller#2809. Fixes FINDING-050 (rfcs#184).

Summary by CodeRabbit

  • Bug Fixes

    • Improved HMAC authentication secret handling by validating numeric settings and reporting invalid values.
    • Correctly parses comma-separated signed headers, trimming whitespace and ignoring empty entries.
    • Preserves default behavior for negative or unspecified configuration values.
  • Tests

    • Added coverage for signed-header parsing and invalid clock-skew configuration.

translateConsumerHMACAuthPlugin ranged over the raw bytes of the
signed_headers Secret value, emitting one single-character string per
byte instead of the configured header names. The data-plane signature
policy then bound nonsensical headers, silently voiding the operator's
intended integrity control. Only the secretRef path was affected; the
inline Value path already passed a []string.

Split the value on commas and trim entries. Also surface strconv.ParseInt
failures for clock_skew and max_req_body instead of discarding them, so a
typo no longer coerces silently to a default.
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

HMAC secret translation now rejects invalid numeric values, applies defaults for negative values, and parses comma-separated signed headers with trimming and empty-entry removal. Tests cover signed-header translation and invalid clock_skew handling.

Changes

HMAC secret translation

Layer / File(s) Summary
Strict HMAC parsing and validation
internal/adc/translator/apisixconsumer.go, internal/adc/translator/apisixconsumer_test.go
HMAC clock_skew and max_req_body values now return errors when invalid, while negative values retain defaults. signed_headers values are split, trimmed, and filtered; tests cover successful parsing and invalid clock_skew input.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: alinsran

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
E2e Test Quality Review ⚠️ Warning These are translator unit tests with a fake context; they don't exercise an end-to-end API/controller/dependency flow. Add an E2E test that drives consumer creation through the controller to APISIX, and cover the remaining max_req_body and empty signed_headers cases.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes a real part of the change by fixing Secret-based signed_headers parsing for HMAC auth.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed No security issues in the changed paths; the patch only hardens HMAC secret parsing and adds non-sensitive validation errors.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/hmac-signed-headers-secret-parsing

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/adc/translator/apisixconsumer_test.go`:
- Around line 68-82: Extend
TestTranslateApisixConsumer_HMACAuthRejectsInvalidClockSkew with cases covering
an invalid max_req_body value and an empty entry in signed_headers. For each
case, configure the corresponding secret data, call TranslateApisixConsumer, and
assert an error mentioning the affected field, while preserving the existing
clock_skew coverage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0edda70f-e478-4d19-8882-e40479af60b9

📥 Commits

Reviewing files that changed from the base of the PR and between 5f84a00 and 1cde587.

📒 Files selected for processing (2)
  • internal/adc/translator/apisixconsumer.go
  • internal/adc/translator/apisixconsumer_test.go

Comment on lines +68 to +82
func TestTranslateApisixConsumer_HMACAuthRejectsInvalidClockSkew(t *testing.T) {
translator := NewTranslator(logr.Discard())
tctx := provider.NewDefaultTranslateContext(context.Background())
tctx.Secrets[k8stypes.NamespacedName{Namespace: "default", Name: "hmac"}] = &corev1.Secret{
Data: map[string][]byte{
"key_id": []byte("my-key"),
"secret_key": []byte("my-secret"),
"clock_skew": []byte("3O0"), // typo: letter O
},
}

_, err := translator.TranslateApisixConsumer(tctx, hmacConsumerWithSecret("hmac"))
require.Error(t, err)
require.Contains(t, err.Error(), "clock_skew")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Cover the remaining changed parsing paths.

Add cases for invalid max_req_body and empty signed_headers entries; the current inputs do not verify either new behavior.

Proposed test adjustments
-			"signed_headers": []byte("X-Date, Host"),
+			"signed_headers": []byte(" X-Date, , Host, "),
+func TestTranslateApisixConsumer_HMACAuthRejectsInvalidMaxReqBody(t *testing.T) {
+	translator := NewTranslator(logr.Discard())
+	tctx := provider.NewDefaultTranslateContext(context.Background())
+	tctx.Secrets[k8stypes.NamespacedName{Namespace: "default", Name: "hmac"}] = &corev1.Secret{
+		Data: map[string][]byte{
+			"key_id":       []byte("my-key"),
+			"secret_key":   []byte("my-secret"),
+			"max_req_body": []byte("invalid"),
+		},
+	}
+
+	_, err := translator.TranslateApisixConsumer(tctx, hmacConsumerWithSecret("hmac"))
+	require.Error(t, err)
+	require.Contains(t, err.Error(), "max_req_body")
+}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/adc/translator/apisixconsumer_test.go` around lines 68 - 82, Extend
TestTranslateApisixConsumer_HMACAuthRejectsInvalidClockSkew with cases covering
an invalid max_req_body value and an empty entry in signed_headers. For each
case, configure the corresponding secret data, call TranslateApisixConsumer, and
assert an error mentioning the affected field, while preserving the existing
clock_skew coverage.

@github-actions

Copy link
Copy Markdown
Contributor

conformance test report - apisix-standalone mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-07-19T05:11:06Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: success
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests succeeded.
- core:
    result: partial
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 0
      Passed: 32
      Skipped: 1
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 11
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests partially succeeded with 1 test skips. Extended tests partially
    succeeded with 1 test skips.
- core:
    result: partial
    skippedTests:
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 10
      Skipped: 1
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 1 test skips.

@github-actions

Copy link
Copy Markdown
Contributor

conformance test report - apisix mode

apiVersion: gateway.networking.k8s.io/v1
date: "2026-07-19T05:11:43Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    result: success
    statistics:
      Failed: 0
      Passed: 12
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests succeeded.
- core:
    failedTests:
    - HTTPRouteInvalidBackendRefUnknownKind
    result: failure
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 1
      Passed: 31
      Skipped: 1
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 11
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests failed with 1 test failures. Extended tests partially succeeded
    with 1 test skips.
- core:
    result: partial
    skippedTests:
    - TLSRouteSimpleSameNamespace
    statistics:
      Failed: 0
      Passed: 10
      Skipped: 1
  name: GATEWAY-TLS
  summary: Core tests partially succeeded with 1 test skips.

@github-actions

Copy link
Copy Markdown
Contributor

conformance test report

apiVersion: gateway.networking.k8s.io/v1
date: "2026-07-19T05:28:57Z"
gatewayAPIChannel: experimental
gatewayAPIVersion: v1.3.0
implementation:
  contact: null
  organization: APISIX
  project: apisix-ingress-controller
  url: https://github.com/apache/apisix-ingress-controller.git
  version: v2.0.0
kind: ConformanceReport
mode: default
profiles:
- core:
    failedTests:
    - GatewayModifyListeners
    result: failure
    statistics:
      Failed: 1
      Passed: 11
      Skipped: 0
  name: GATEWAY-GRPC
  summary: Core tests failed with 1 test failures.
- core:
    failedTests:
    - GatewayModifyListeners
    result: failure
    skippedTests:
    - HTTPRouteHTTPSListener
    statistics:
      Failed: 1
      Passed: 31
      Skipped: 1
  extended:
    result: partial
    skippedTests:
    - HTTPRouteRedirectPortAndScheme
    statistics:
      Failed: 0
      Passed: 11
      Skipped: 1
    supportedFeatures:
    - GatewayAddressEmpty
    - GatewayPort8080
    - HTTPRouteBackendProtocolWebSocket
    - HTTPRouteDestinationPortMatching
    - HTTPRouteHostRewrite
    - HTTPRouteMethodMatching
    - HTTPRoutePathRewrite
    - HTTPRoutePortRedirect
    - HTTPRouteQueryParamMatching
    - HTTPRouteRequestMirror
    - HTTPRouteResponseHeaderModification
    - HTTPRouteSchemeRedirect
    unsupportedFeatures:
    - GatewayHTTPListenerIsolation
    - GatewayInfrastructurePropagation
    - GatewayStaticAddresses
    - HTTPRouteBackendProtocolH2C
    - HTTPRouteBackendRequestHeaderModification
    - HTTPRouteBackendTimeout
    - HTTPRouteParentRefPort
    - HTTPRoutePathRedirect
    - HTTPRouteRequestMultipleMirrors
    - HTTPRouteRequestPercentageMirror
    - HTTPRouteRequestTimeout
  name: GATEWAY-HTTP
  summary: Core tests failed with 1 test failures. Extended tests partially succeeded
    with 1 test skips.
- core:
    failedTests:
    - GatewayModifyListeners
    - TLSRouteSimpleSameNamespace
    result: failure
    statistics:
      Failed: 2
      Passed: 9
      Skipped: 0
  name: GATEWAY-TLS
  summary: Core tests failed with 2 test failures.

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

Successfully merging this pull request may close these issues.

1 participant