Skip to content

add platform api changes for event gateway hmac secret generation#2153

Closed
tharindu1st wants to merge 2 commits into
wso2:mainfrom
tharindu1st:event-gateway-test
Closed

add platform api changes for event gateway hmac secret generation#2153
tharindu1st wants to merge 2 commits into
wso2:mainfrom
tharindu1st:event-gateway-test

Conversation

@tharindu1st

Copy link
Copy Markdown
Contributor

add platform api changes for event gateway hmac secret generation

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@tharindu1st, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 55 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more credits in the billing tab to continue.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e2f917fe-b18c-40e6-878b-b318d892b42f

📥 Commits

Reviewing files that changed from the base of the PR and between e1c3fe2 and 703fa38.

⛔ Files ignored due to path filters (2)
  • event-gateway/gateway-controller/go.sum is excluded by !**/*.sum
  • go.work is excluded by !**/*.work
📒 Files selected for processing (36)
  • event-gateway/Makefile
  • event-gateway/gateway-controller/Dockerfile
  • event-gateway/gateway-controller/Makefile
  • event-gateway/gateway-controller/cmd/main/main.go
  • event-gateway/gateway-controller/go.mod
  • event-gateway/gateway-controller/pkg/eventgateway/extension.go
  • event-gateway/gateway-controller/pkg/eventgateway/sql/event-gateway-db.postgres.sql
  • event-gateway/gateway-controller/pkg/eventgateway/sql/event-gateway-db.sql
  • event-gateway/gateway-controller/pkg/eventgateway/subscription_processor.go
  • event-gateway/gateway-controller/pkg/eventgateway/webhook_secret_processor.go
  • gateway/gateway-controller/cmd/controller/main.go
  • gateway/gateway-controller/cmd/controller/main_test.go
  • gateway/gateway-controller/pkg/bootstrap/auth.go
  • gateway/gateway-controller/pkg/bootstrap/run.go
  • gateway/gateway-controller/pkg/bootstrap/runtime.go
  • gateway/gateway-controller/pkg/bootstrap/runtime_test.go
  • gateway/gateway-controller/pkg/controllerext/extension.go
  • gateway/gateway-controller/pkg/eventlistener/api_processor.go
  • gateway/gateway-controller/pkg/eventlistener/application_processor.go
  • gateway/gateway-controller/pkg/eventlistener/listener.go
  • gateway/gateway-controller/pkg/eventlistener/listener_test.go
  • gateway/gateway-controller/pkg/eventlistener/subscription_processor_test.go
  • gateway/gateway-controller/pkg/eventlistener/webhook_secret_processor.go
  • gateway/gateway-controller/pkg/policyxds/combined_cache.go
  • gateway/gateway-controller/pkg/policyxds/combined_cache_test.go
  • gateway/gateway-controller/pkg/policyxds/server.go
  • gateway/gateway-controller/pkg/storage/event-gateway-db.postgres.sql
  • gateway/gateway-controller/pkg/storage/event-gateway-db.sql
  • gateway/gateway-controller/pkg/storage/factory.go
  • gateway/gateway-controller/pkg/storage/gateway-controller-db.postgres.sql
  • gateway/gateway-controller/pkg/storage/gateway-controller-db.sql
  • gateway/gateway-controller/pkg/storage/postgres.go
  • gateway/gateway-controller/pkg/storage/sql_store.go
  • gateway/gateway-controller/pkg/storage/sqlite.go
  • gateway/gateway-controller/pkg/storage/sqlite_test.go
  • gateway/gateway-controller/tests/integration/schema_test.go
📝 Walkthrough

Walkthrough

This PR implements platform-managed WebSub HMAC secrets with end-to-end lifecycle support across both platform-api and gateway-controller. The platform-api introduces encrypted-at-rest database persistence, AES-256-GCM encryption with fallback key derivation, CRUD service operations, and REST endpoints for secret management. A new internal gateway API endpoint delivers decrypted secrets securely to controllers. The gateway-controller extends its WebSocket client to synchronize secrets via platform events, stores plaintext secrets locally in the webhook-secret xDS store for validator access, and provides APIs for retrieving encrypted secrets. The implementation includes unique-constraint error handling, feature gating for disabled services, and event broadcasting to keep all gateways in sync with platform secret changes.

Suggested reviewers

  • pubudu538
  • malinthaprasan
  • Krishanx92
  • RakhithaRR
  • Tharsanan1
  • VirajSalaka
  • renuka-fernando
  • AnuGayan
  • chamilaadhi
  • Arshardh
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is significantly incomplete; it merely restates the title without addressing the required template sections (Purpose, Goals, Approach, User stories, Documentation, Testing, Security, Samples, Related PRs, Test environment). Complete the PR description using the provided template. Include rationale, implementation approach, test coverage, security validation, and documentation links.
Docstring Coverage ⚠️ Warning Docstring coverage is 52.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the primary change: adding platform API changes for HMAC secret generation in the event gateway context.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@tharindu1st tharindu1st force-pushed the event-gateway-test branch 3 times, most recently from da41672 to def7de7 Compare June 11, 2026 13:40
@tharindu1st

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🤖 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 `@gateway/gateway-controller/pkg/controlplane/client.go`:
- Around line 2483-2525: Add a delete-side cleanup helper that removes platform
HMAC secrets from the in-memory store and refreshes the xDS snapshot, and call
it from both the normal WebSub delete path and the not-found branch;
specifically, implement a method (e.g., cleanupHmacSecretsForArtifact or reuse
existing logic around webhookSecretStore.RemoveAllByAPI and
webhookSecretSnapshotManager.RefreshSnapshot) that takes artifactID, calls
webhookSecretStore.RemoveAllByAPI(artifactID) and logs failures, then calls
webhookSecretSnapshotManager.RefreshSnapshot() if not nil and logs failures, and
invoke this helper from handleWebSubAPIDeletedEvent and the "not found" branch
so secrets are removed whenever a WebSub API is deleted.

In `@platform-api/src/internal/handler/gateway_internal.go`:
- Around line 826-829: In the hmacSecretService nil check block in
gateway_internal.go, the code currently returns HTTP 200 with an empty
GatewayHmacSecretsResponse when the service is not configured. Change the
http.StatusOK response code to http.StatusServiceUnavailable (503) to properly
signal that this is a temporary platform-side configuration issue rather than an
authoritative empty secrets list. This allows the gateway controller to retry
the request instead of reconciling with an empty set when the HMAC secret
service fails to initialize.

In `@platform-api/src/internal/handler/websub_api_hmac_secret.go`:
- Around line 94-99: The handler currently converts req.Secret to a plain string
before calling h.secretService.Generate, losing the difference between omitted
and empty; instead, detect and reject an explicit empty secret (if req.Secret !=
nil && *req.Secret == "" return 400) before calling h.secretService.Generate,
and apply the same check in the regenerate flow (the code around the second
occurrence at lines 194-199). Reference req.Secret, h.secretService.Generate
(and the regenerate handler) and ensure you return a proper 400 error for
explicit empty secrets rather than treating them as “auto-generate.”
- Around line 190-192: RegenerateHmacSecret currently swallows all JSON bind
errors by doing `_ = c.ShouldBindJSON(&req)`; change this to capture the error
(`err := c.ShouldBindJSON(&req)`) and if err != nil and err is not io.EOF,
respond with HTTP 400 (e.g., c.AbortWithStatusJSON(400, ...)) so malformed JSON
is rejected while still allowing an empty body; import io and reference the req
variable and c.ShouldBindJSON in your fix.

In `@platform-api/src/internal/repository/websub_api_hmac_secret.go`:
- Around line 57-70: The repository reads nullable database column display_name
into a plain string causing Scan to fail on NULL; update GetByArtifactAndName to
scan display_name into a nullable type (e.g., sql.NullString or *string) and
then assign s.DisplayName appropriately (convert NullString.Valid ?
NullString.String : "" or set pointer), and apply the same change to the other
read/list method in this file that also scans display_name so all read paths
match the table schema.

In `@platform-api/src/internal/service/websub_api_hmac_secret.go`:
- Around line 128-132: The Create error handling currently only checks
isSQLiteUniqueConstraint after calling s.repo.Create, so PostgreSQL
unique-constraint failures slip through; add a backend-agnostic uniqueness check
(e.g., isUniqueConstraint(err)) or extend the existing check to also detect
Postgres unique-constraint errors before returning a generic error. Update the
branch that handles s.repo.Create's error to call this normalized helper (or add
isPostgresUniqueConstraint and combine with isSQLiteUniqueConstraint) and return
constants.ErrHmacSecretAlreadyExists when the helper indicates a duplicate (so
the handler correctly maps to 409).
- Around line 91-94: The derived secret name from slugifyHmacSecret(displayName)
can exceed the DB column limit (name VARCHAR(63)); before calling repo.Create
use slugifyHmacSecret(displayName) then enforce a 63-character limit
(trim/truncate) and fall back to "secret-"+apiHandle if empty, and repeat the
same truncation/validation in the other places noted (the blocks around where
name is set at lines ~128-132 and ~273-285) so that repo.Create always receives
a name <=63 chars and never relies on DB to reject long values.
🪄 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: e041e676-6a4b-4ac9-8cf5-4280e33f3311

📥 Commits

Reviewing files that changed from the base of the PR and between 0b99088 and def7de7.

📒 Files selected for processing (20)
  • gateway/gateway-controller/cmd/controller/main.go
  • gateway/gateway-controller/pkg/controlplane/client.go
  • gateway/gateway-controller/pkg/controlplane/client_integration_test.go
  • gateway/gateway-controller/pkg/controlplane/controlplane_test.go
  • gateway/gateway-controller/pkg/utils/api_utils.go
  • platform-api/src/api/websub_hmac_secret.go
  • platform-api/src/config/config.go
  • platform-api/src/internal/constants/error.go
  • platform-api/src/internal/database/schema.postgres.sql
  • platform-api/src/internal/database/schema.sql
  • platform-api/src/internal/database/schema.sqlite.sql
  • platform-api/src/internal/dto/gateway_internal.go
  • platform-api/src/internal/handler/gateway_internal.go
  • platform-api/src/internal/handler/websub_api_hmac_secret.go
  • platform-api/src/internal/model/websub_api_hmac_secret.go
  • platform-api/src/internal/repository/interfaces.go
  • platform-api/src/internal/repository/websub_api_hmac_secret.go
  • platform-api/src/internal/server/server.go
  • platform-api/src/internal/service/gateway_events.go
  • platform-api/src/internal/service/websub_api_hmac_secret.go

Comment thread gateway/gateway-controller/pkg/controlplane/client.go
Comment thread platform-api/src/internal/handler/gateway_internal.go
Comment thread platform-api/src/internal/handler/websub_api_hmac_secret.go
Comment thread platform-api/src/internal/handler/websub_api_hmac_secret.go Outdated
Comment thread platform-api/src/internal/repository/websub_api_hmac_secret.go
Comment thread platform-api/src/internal/service/websub_api_hmac_secret.go
Comment thread platform-api/src/internal/service/websub_api_hmac_secret.go
@tharindu1st tharindu1st force-pushed the event-gateway-test branch 2 times, most recently from 98ebb36 to 4f693ea Compare June 14, 2026 18:38

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
gateway/gateway-controller/pkg/controlplane/client.go (1)

2486-2497: ⚡ Quick win

Add nil guard for apiUtilsService for consistency with similar methods.

Other sync methods in this file (e.g., syncSubscriptionPlans, syncSubscriptionsForExistingAPIs) check apiUtilsService for nil before invoking it. This method should follow the same pattern.

Suggested fix
 func (c *Client) syncHmacSecretsForArtifact(artifactID string) {
 	if c.webhookSecretStore == nil {
 		return
 	}
+	if c.apiUtilsService == nil {
+		return
+	}
 
 	secrets, err := c.apiUtilsService.FetchWebSubAPIHmacSecrets(artifactID)
🤖 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 `@gateway/gateway-controller/pkg/controlplane/client.go` around lines 2486 -
2497, Add a nil guard for c.apiUtilsService in the syncHmacSecretsForArtifact
method for consistency with other sync methods in the file. Right after the
existing nil check for c.webhookSecretStore, add a nil check for
c.apiUtilsService that returns early if it is nil, before calling
c.apiUtilsService.FetchWebSubAPIHmacSecrets.
🤖 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 `@platform-api/src/config/config.go`:
- Around line 170-173: The HMACSecretEncryptionKey field is using an envconfig
tag which is incompatible with the koanf-based configuration system used in this
file. Remove or update the envconfig tag to align with the koanf configuration
approach, and add a case in the envToKoanfKey function to properly map the
DATABASE_HMAC_SECRET_ENCRYPTION_KEY environment variable (which is documented in
the field's comment) so it gets loaded correctly as the koanf configuration key
for hmac_secret_encryption_key.

---

Nitpick comments:
In `@gateway/gateway-controller/pkg/controlplane/client.go`:
- Around line 2486-2497: Add a nil guard for c.apiUtilsService in the
syncHmacSecretsForArtifact method for consistency with other sync methods in the
file. Right after the existing nil check for c.webhookSecretStore, add a nil
check for c.apiUtilsService that returns early if it is nil, before calling
c.apiUtilsService.FetchWebSubAPIHmacSecrets.
🪄 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: a84496d1-f8fd-4433-87a1-751441adc318

📥 Commits

Reviewing files that changed from the base of the PR and between def7de7 and 4f693ea.

📒 Files selected for processing (24)
  • gateway/gateway-controller/cmd/controller/main.go
  • gateway/gateway-controller/pkg/controlplane/client.go
  • gateway/gateway-controller/pkg/controlplane/client_integration_test.go
  • gateway/gateway-controller/pkg/controlplane/controlplane_test.go
  • gateway/gateway-controller/pkg/utils/api_utils.go
  • platform-api/src/api/generated.go
  • platform-api/src/api/manual_types.go
  • platform-api/src/api/websub_hmac_secret.go
  • platform-api/src/config/config.go
  • platform-api/src/internal/constants/error.go
  • platform-api/src/internal/database/schema.postgres.sql
  • platform-api/src/internal/database/schema.sql
  • platform-api/src/internal/database/schema.sqlite.sql
  • platform-api/src/internal/dto/gateway_internal.go
  • platform-api/src/internal/handler/gateway_internal.go
  • platform-api/src/internal/handler/websub_api_hmac_secret.go
  • platform-api/src/internal/model/websub_api_hmac_secret.go
  • platform-api/src/internal/repository/interfaces.go
  • platform-api/src/internal/repository/websub_api_hmac_secret.go
  • platform-api/src/internal/server/server.go
  • platform-api/src/internal/service/gateway_events.go
  • platform-api/src/internal/service/websub_api_hmac_secret.go
  • platform-api/src/resources/gateway-internal-api.yaml
  • platform-api/src/resources/openapi.yaml
💤 Files with no reviewable changes (8)
  • platform-api/src/internal/service/gateway_events.go
  • platform-api/src/resources/gateway-internal-api.yaml
  • platform-api/src/internal/model/websub_api_hmac_secret.go
  • platform-api/src/resources/openapi.yaml
  • platform-api/src/internal/repository/interfaces.go
  • platform-api/src/internal/server/server.go
  • platform-api/src/internal/service/websub_api_hmac_secret.go
  • platform-api/src/internal/repository/websub_api_hmac_secret.go
✅ Files skipped from review due to trivial changes (2)
  • platform-api/src/api/websub_hmac_secret.go
  • platform-api/src/api/generated.go
🚧 Files skipped from review as they are similar to previous changes (8)
  • gateway/gateway-controller/pkg/controlplane/client_integration_test.go
  • platform-api/src/internal/dto/gateway_internal.go
  • platform-api/src/internal/database/schema.postgres.sql
  • gateway/gateway-controller/pkg/utils/api_utils.go
  • platform-api/src/internal/database/schema.sqlite.sql
  • platform-api/src/internal/database/schema.sql
  • gateway/gateway-controller/cmd/controller/main.go
  • platform-api/src/internal/handler/websub_api_hmac_secret.go

Comment on lines +170 to +173
// HMACSecretEncryptionKey is the 32-byte key for AES-256-GCM encryption of WebSub API HMAC secrets.
// Provide as 64 hex chars or 44 base64 chars.
// Env: DATABASE_HMAC_SECRET_ENCRYPTION_KEY. If empty, falls back to SubscriptionTokenEncryptionKey then JWT_SECRET_KEY.
HMACSecretEncryptionKey string `envconfig:"HMAC_SECRET_ENCRYPTION_KEY" default:""`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Environment variable mapping missing for HMACSecretEncryptionKey.

The field uses envconfig tag, but this file uses koanf-based configuration. Additionally, envToKoanfKey has no case for database_hmac_secret_encryption_key, so the documented DATABASE_HMAC_SECRET_ENCRYPTION_KEY environment variable won't be loaded.

Suggested fix

Update the struct field tag:

-	HMACSecretEncryptionKey string `envconfig:"HMAC_SECRET_ENCRYPTION_KEY" default:""`
+	HMACSecretEncryptionKey string `koanf:"hmac_secret_encryption_key"`

Add case in envToKoanfKey (around line 355):

 	case "database_subscription_token_encryption_key":
 		return "database.subscription_token_encryption_key"
+	case "database_hmac_secret_encryption_key":
+		return "database.hmac_secret_encryption_key"
🤖 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 `@platform-api/src/config/config.go` around lines 170 - 173, The
HMACSecretEncryptionKey field is using an envconfig tag which is incompatible
with the koanf-based configuration system used in this file. Remove or update
the envconfig tag to align with the koanf configuration approach, and add a case
in the envToKoanfKey function to properly map the
DATABASE_HMAC_SECRET_ENCRYPTION_KEY environment variable (which is documented in
the field's comment) so it gets loaded correctly as the koanf configuration key
for hmac_secret_encryption_key.

@github-actions

Copy link
Copy Markdown
Contributor

Dependency Validation Results

Dependency name: github.com/gin-gonic/gin
Version: v1.11.0
Approved: ❌ No - Module not found in dependency registry

Dependency name: github.com/wso2/api-platform/common
Version: v0.0.0
Approved: ❌ No - Module not found in dependency registry

Dependency name: github.com/wso2/api-platform/gateway/gateway-controller
Version: v0.0.0
Approved: ❌ No - Module not found in dependency registry


Next Steps

  1. Review the validation failures listed above
  2. Check if dependencies are in the approved dependency list
  3. Options to resolve:
    • Remove the unapproved dependencies from this PR
    • OR submit a PR to add these dependencies to the approved list in engineering-governance
  4. Once resolved, push changes to re-run validation

This PR is blocked until all dependencies are approved.

⚠️ Please verify the scope of the dependencies usage is necessary

@github-actions

Copy link
Copy Markdown
Contributor

Dependency Validation Results

Dependency name: github.com/gin-gonic/gin
Version: v1.11.0
Approved: ❌ No - Module not found in dependency registry

Dependency name: github.com/wso2/api-platform/common
Version: v0.0.0
Approved: ❌ No - Module not found in dependency registry

Dependency name: github.com/wso2/api-platform/gateway/gateway-controller
Version: v0.0.0
Approved: ❌ No - Module not found in dependency registry


Next Steps

  1. Review the validation failures listed above
  2. Check if dependencies are in the approved dependency list
  3. Options to resolve:
    • Remove the unapproved dependencies from this PR
    • OR submit a PR to add these dependencies to the approved list in engineering-governance
  4. Once resolved, push changes to re-run validation

This PR is blocked until all dependencies are approved.

⚠️ Please verify the scope of the dependencies usage is necessary

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