Skip to content

Add support for HTTP External Authorization Services#7418

Open
therealak12 wants to merge 2 commits intoprojectcontour:mainfrom
snapp-incubator:http-ext-authz
Open

Add support for HTTP External Authorization Services#7418
therealak12 wants to merge 2 commits intoprojectcontour:mainfrom
snapp-incubator:http-ext-authz

Conversation

@therealak12
Copy link
Copy Markdown
Contributor

@therealak12 therealak12 commented Feb 14, 2026

Envoy external authorization filter supports HTTP and GRPC servers. Contour only supports configuring gRPC services at the moment. The PR adds support for HTTP ext-authz services.

We've been using this in production for >1 year.

  1. feat: add http support to authz filter snapp-incubator/contour#4
  2. refactor: add http auth support to contour snapp-incubator/contour#5

Closes #6509

@therealak12 therealak12 requested a review from a team as a code owner February 14, 2026 05:57
@therealak12 therealak12 requested review from sunjayBhatia and tsaarni and removed request for a team February 14, 2026 05:57
@sunjayBhatia sunjayBhatia requested review from a team, davinci26 and wilsonwu and removed request for a team February 14, 2026 05:57
Signed-off-by: therealak12 <ak12hastam@gmail.com>
@tsaarni tsaarni added the release-note/minor A minor change that needs about a paragraph of explanation in the release notes. label Feb 14, 2026
@codecov
Copy link
Copy Markdown

codecov bot commented Feb 14, 2026

Codecov Report

❌ Patch coverage is 72.66187% with 38 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.78%. Comparing base (9477aaf) to head (e0bce55).
⚠️ Report is 70 commits behind head on main.

Files with missing lines Patch % Lines
cmd/contour/serve.go 0.00% 18 Missing ⚠️
internal/envoy/v3/listener.go 77.41% 14 Missing ⚠️
internal/dag/conditions.go 75.00% 2 Missing and 2 partials ⚠️
cmd/contour/servecontext.go 33.33% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7418      +/-   ##
==========================================
- Coverage   81.85%   81.78%   -0.07%     
==========================================
  Files         130      130              
  Lines       15747    15895     +148     
==========================================
+ Hits        12889    13000     +111     
- Misses       2574     2608      +34     
- Partials      284      287       +3     
Files with missing lines Coverage Δ
internal/dag/dag.go 98.44% <ø> (ø)
internal/dag/httpproxy_processor.go 91.57% <100.00%> (+0.13%) ⬆️
internal/envoy/v3/cluster.go 96.24% <100.00%> (+0.03%) ⬆️
internal/featuretests/v3/envoy.go 99.36% <100.00%> (+0.01%) ⬆️
internal/xdscache/v3/listener.go 92.09% <100.00%> (+0.16%) ⬆️
pkg/config/parameters.go 87.10% <ø> (ø)
cmd/contour/servecontext.go 86.29% <33.33%> (-0.34%) ⬇️
internal/dag/conditions.go 96.29% <75.00%> (-1.35%) ⬇️
internal/envoy/v3/listener.go 96.03% <77.41%> (-2.14%) ⬇️
cmd/contour/serve.go 23.80% <0.00%> (+0.19%) ⬆️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Member

@tsaarni tsaarni left a comment

Choose a reason for hiding this comment

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

Thank you @therealak12 for the contribution!

The changes look good overall but I would like to discuss some of the API aspects and potential error scenarios.

Comment thread pkg/config/parameters.go Outdated
// or a gRPC authorization server.
//
// +optional
ServiceAPIType contour_v1.AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Config file is parsed as YAML

Suggested change
ServiceAPIType contour_v1.AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"`
ServiceAPIType contour_v1.AuthorizationServiceAPIType `yaml:"serviceAPIType,omitempty"`

Comment thread pkg/config/parameters.go Outdated
// HttpAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
//
// +optional
HTTPServerSettings *contour_v1.HTTPAuthorizationServerSettings `json:"httpSettings,omitempty"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Config file is parsed as YAML

Suggested change
HTTPServerSettings *contour_v1.HTTPAuthorizationServerSettings `json:"httpSettings,omitempty"`
HTTPServerSettings *contour_v1.HTTPAuthorizationServerSettings `yaml:"httpSettings,omitempty"`

}).Status(p).IsValid()
}

func AuthzTypeHTTPWithContext(t *testing.T, rh ResourceEventHandlerWrapper, c *Contour) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

AuthzTypeHTTPWithContext is not called anywhere. Forgot to call it from TestAuthorization?

HttpService: &envoy_filter_http_ext_authz_v3.HttpService{
ServerUri: &envoy_config_core_v3.HttpUri{
// Uri: externalAuthorization.HttpServerURI,
Uri: "http://dummy/",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is the Uri field mandatory, or can it be left empty? If it is required, we should add an explanation for not to cause confusion for reader.

Comment on lines +268 to +271
// HTTPAuthorizationServerSettings defines configurations for interacting with an external HTTP authorization server.
//
// +optional
HTTPServerSettings *HTTPAuthorizationServerSettings `json:"httpSettings,omitempty"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Add a comment stating that httpSettings is used only for HTTP based authorization service.

To enforce this and prevent confusion, we can add a CEL validation rule to the AuthorizationServer struct. Something like below but note that I did not test this yet

// +kubebuilder:validation:XValidation:message="httpSettings can only be set when serviceAPIType is 'http'",rule="!has(self.httpSettings) || self.serviceAPIType == 'http'"

Comment thread cmd/contour/serve.go Outdated
Comment on lines +839 to +841
switch contourConfiguration.GlobalExternalAuthorization.ServiceAPIType {
case contour_v1.AuthorizationGRPCService:
globalExternalAuthConfig.ServiceAPIType = contour_v1.AuthorizationGRPCService
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we have fall back to the gRPC authorization server type here if type is not set?

Comment thread cmd/contour/serve.go Outdated
Context: context,
}

switch contourConfiguration.GlobalExternalAuthorization.ServiceAPIType {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should refactor the switch-case logic in cmd/contour/serve.go within setupGlobalExternalAuthentication() and the corresponding logic in internal/dag/httpproxy_processor.go within computeVirtualHostAuthorization() into one.

Comment thread internal/dag/httpproxy_processor.go Outdated
AuthorizationResponseTimeout: *respTimeout,
}

switch auth.ServiceAPIType {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should refactor the switch-case logic in internal/dag/httpproxy_processor.go within computeVirtualHostAuthorization() and the corresponding logic in cmd/contour/serve.go within setupGlobalExternalAuthentication() into one.

Comment on lines +1023 to +1027
"AuthzTypeGRPC": AuthzTypeGRPC,
"AuthzTypeHTTP": authzTypeHTTP,
"AuthzTypeHTTPWithPathPrefix": AuthzTypeHTTPWithPathPrefix,
"AuthzTypeHTTPWithAllowedAuthorizationHeaders": AuthzTypeHTTPWithAllowedAuthorizationHeaders,
"AuthzTypeHTTPWithAllowedUpstreamHeaders": AuthzTypeHTTPWithAllowedUpstreamHeaders,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Minor nit: these test functions do not need to be exported. All of them can start with a lowercase letter.

Comment thread apis/projectcontour/v1/httpproxy.go Outdated
// +optional
// +kubebuilder:validation:Enum=http;grpc
// +kubebuilder:default=grpc
ServiceAPIType AuthorizationServiceAPIType `json:"serviceAPIType,omitempty"`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I recommend using serviceType (without API) to align with how Envoy seems to call it.

Comment thread internal/envoy/v3/listener.go Outdated
HttpUpstreamType: &envoy_config_core_v3.HttpUri_Cluster{
Cluster: externalAuthorization.AuthorizationService.Name,
},
Timeout: envoy.Timeout(externalAuthorization.AuthorizationResponseTimeout),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The httpproxy.spec.virtualhost.authorization.responseTimeout parameter is optional in our configuration, and envoy.Timeout() returns nil if the value is not set. However, HttpUri requires a defined value.

For gRPC, the default value is documented as infinite. We should apply the same setting by using 0, as leaving the field empty causes an error.

@tsaarni
Copy link
Copy Markdown
Member

tsaarni commented Feb 27, 2026

@therealak12 I did some experiments related to my previous comments. You are free to use any of this work: snapp-incubator/contour@http-ext-authz...Nordix:contour:http-based-ext-authz

@github-actions
Copy link
Copy Markdown

The Contour project currently lacks enough contributors to adequately respond to all PRs.

This bot triages PRs according to the following rules:

  • After 30d of inactivity, lifecycle/stale is applied
  • After 60d of inactivity since lifecycle/stale was applied, the PR is closed

You can:

  • Ensure your PR is passing all CI checks. PRs that are fully green are more likely to be reviewed. If you are having trouble with CI checks, reach out to the #contour channel in the Kubernetes Slack workspace.
  • Mark this PR as fresh by commenting or pushing a commit
  • Close this PR
  • Offer to help out with triage

Please send feedback to the #contour channel in the Kubernetes Slack

@github-actions github-actions bot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Apr 11, 2026
Signed-off-by: therealak12 <ak12hastam@gmail.com>
@therealak12
Copy link
Copy Markdown
Contributor Author

Hi, thank you for your review and the helpful suggestions.

Apologies for the delay. Due to the recent war affecting my country, I was unable to continue working on this PR for some time. Now that the situation has stabilized, I applied the requested changes.

Please take another look when you have a chance.

@github-actions github-actions bot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Apr 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/minor A minor change that needs about a paragraph of explanation in the release notes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for HTTP based external auth server

2 participants