Skip to content

feat(translator): implement TCP security policy support#6496

Closed
davem-git wants to merge 129 commits intoenvoyproxy:mainfrom
davem-git:tcp-security-policy-features
Closed

feat(translator): implement TCP security policy support#6496
davem-git wants to merge 129 commits intoenvoyproxy:mainfrom
davem-git:tcp-security-policy-features

Conversation

@davem-git
Copy link
Copy Markdown
Contributor

feat(SecurityPolicies): add new featureAdding Security Policies for TCPGateways

adding security policies to TCPGateways using the existing API's

What this PR does / why we need it:

This PR will allow us to run authorization security policies only on TCPGateways
Which issue(s) this PR fixes:

Fixes # #4908

Release Notes: Yes/No

@davem-git davem-git requested a review from a team as a code owner July 9, 2025 20:50
@davem-git
Copy link
Copy Markdown
Contributor Author

This now works. I added. a security policy to the tcp example and you can verify getting rejected from that policy

@davem-git davem-git force-pushed the tcp-security-policy-features branch from 87ca72a to 5a4378c Compare July 9, 2025 21:06
@arkodg arkodg requested a review from zhaohuabing July 9, 2025 22:12
@arkodg arkodg added this to the v1.5.0-rc.1 Release milestone Jul 9, 2025
@davem-git davem-git force-pushed the tcp-security-policy-features branch 4 times, most recently from e6dbbc0 to 94ffdf1 Compare July 10, 2025 19:26
@davem-git davem-git force-pushed the tcp-security-policy-features branch from 899bbdb to 7f8c58f Compare July 11, 2025 21:15
@davem-git
Copy link
Copy Markdown
Contributor Author

didn't rebase cleanly trying that again

@davem-git davem-git force-pushed the tcp-security-policy-features branch from 925009c to 42ffe56 Compare July 11, 2025 21:22
@arkodg arkodg requested a review from zhaohuabing July 11, 2025 21:24
@davem-git davem-git force-pushed the tcp-security-policy-features branch from ec62e0e to afa5c43 Compare July 11, 2025 21:25
Copy link
Copy Markdown
Member

@zhaohuabing zhaohuabing left a comment

Choose a reason for hiding this comment

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

Can we add an e2e test to verify this works?

@davem-git
Copy link
Copy Markdown
Contributor Author

davem-git commented Jul 16, 2025

@zhaohuabing Running these e2e tests seems to fail on static-file-server, it doesn't have an image in docker. is there away to run them to just run my new tests?

@davem-git davem-git force-pushed the tcp-security-policy-features branch 2 times, most recently from 52ff275 to 86bd7b4 Compare July 16, 2025 21:53
@davem-git
Copy link
Copy Markdown
Contributor Author

@arkodg any advice Running these e2e tests seems to fail on static-file-server, it doesn't have an image in docker. is there away to run them to just run my new tests?

@arkodg
Copy link
Copy Markdown
Contributor

arkodg commented Jul 21, 2025

@davem-git recommend trying out these commands locally, make help has a lot more suggestions

  • make build
  • make test
  • make e2e
  • make generate && make manifests
  • make testdata

@arkodg
Copy link
Copy Markdown
Contributor

arkodg commented Jul 21, 2025

also suggest rebasing to main, which make it easier to run e2e tests

@davem-git
Copy link
Copy Markdown
Contributor Author

add some release note and updated documentation

@davem-git
Copy link
Copy Markdown
Contributor Author

I was able merge in the changes from main. please review it. I also noticed that these test that are failing, seem to fail on other branches https://github.com/envoyproxy/gateway/pull/6851/commits but were merged in anyways.

@davem-git
Copy link
Copy Markdown
Contributor Author

@arkodg any update on this?

@arkodg
Copy link
Copy Markdown
Contributor

arkodg commented Sep 26, 2025

hey @davem-git the complexity this PR introduces is still very high, are there ways we can make the logic more readable ?

for e.g. can we pass individual routes in

for _, tcpRoute := range tcpRoutes {
to avoid the if TCP logic inside the policy

@davem-git
Copy link
Copy Markdown
Contributor Author

Will do, any other comments? I've had this open a while with little feedback. The policies apply and work as expected, without input from your end this PR has dragged out for months.

@arkodg
Copy link
Copy Markdown
Contributor

arkodg commented Sep 26, 2025

hey @davem-git lets collab together to get this into v1.6, if youre on the Envoy Slack lets start a convo there (my handle is on slack is @ArkoDasgupta) ?

// +kubebuilder:validation:XValidation:rule="has(self.targetRef) ? self.targetRef.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'TCPRoute'] : true", message="this policy can only have a targetRef.kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.group == 'gateway.networking.k8s.io') : true ", message="this policy can only have a targetRefs[*].group of gateway.networking.k8s.io"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute']) : true ", message="this policy can only have a targetRefs[*].kind of Gateway/HTTPRoute/GRPCRoute"
// +kubebuilder:validation:XValidation:rule="has(self.targetRefs) ? self.targetRefs.all(ref, ref.kind in ['Gateway', 'HTTPRoute', 'GRPCRoute', 'TCPRoute']) : true ", message="this policy can only have a targetRefs[*].kind of Gateway/HTTPRoute/GRPCRoute/TCPRoute"
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.

As mentioned in https://github.com/envoyproxy/gateway/pull/6496/files#r2415900704, can we add a comment saying that only client-IP authorization will be applied to TCPRoute?

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 also need to update the comment of the ClientCIDRs field on how to get client IP from TCP requests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I updated this on #7168. @arkodg suggested breaking this up in to 5 PR's

return nil
}

func buildTCPRBACMatcherFromRules(rules []*ir.AuthorizationRule, defaultAction egv1a1.AuthorizationAction) *rbacconfig.RBAC {
Copy link
Copy Markdown
Member

@zhaohuabing zhaohuabing Oct 9, 2025

Choose a reason for hiding this comment

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

Nit: can we move all the authorization-related methods to a standalone file tcp_authorization.go?

if len(rule.Principal.Headers) > 0 {
return fmt.Errorf("rule %d: headers not supported for TCP", i)
}
if rule.Action == egv1a1.AuthorizationActionAllow && len(rule.Principal.ClientCIDRs) == 0 {
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.

What happens when rule.Action == egv1a1.AuthorizationActionDeny && len(rule.Principal.ClientCIDRs) == 0 ?

Copy link
Copy Markdown
Contributor Author

@davem-git davem-git Oct 9, 2025

Choose a reason for hiding this comment

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

I think it defaults to deny, and blocks everything Do we want it to do that? I know we wanted to allow placeholders for security policy, I would think that would be fine if they just didn't add the authorization to the security policy

Copy link
Copy Markdown
Contributor Author

@davem-git davem-git Oct 9, 2025

Choose a reason for hiding this comment

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

i guess it doesn't matter. When i try this

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
  namespace: default
  name: tcp-app-2
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: TCPRoute
    name: tcp-app-2
  authorization:
    defaultAction: Allow

or

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
  namespace: default
  name: tcp-app-2
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: TCPRoute
    name: tcp-app-2
  authorization:
    defaultAction: Deny

Both are accepted and do nothing

    HTTP/1.1 200 OK
Content-Type: application/json
X-Content-Type-Options: nosniff
Date: Thu, 09 Oct 2025 20:02:19 GMT
Content-Length: 189

{
 "path": "/",
 "host": "backend",
 "method": "GET",
 "proto": "HTTP/1.1",
 "headers": {},
 "namespace": "default",
 "ingress": "",
 "service": "bar",
 "pod": "backend-2-958dbb978-ffncm"
}%

When it try this

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
  namespace: default
  name: tcp-app-2
spec:
  targetRef:
    group: gateway.networking.k8s.io
    kind: TCPRoute
    name: tcp-app-2
  authorization:
    defaultAction: Deny
    rules:
    - action: Allow
      principal:
        clientCIDRs:

or this

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: SecurityPolicy
metadata:
 namespace: default
 name: tcp-app-2
spec:
 targetRef:
   group: gateway.networking.k8s.io
   kind: TCPRoute
   name: tcp-app-2
 authorization:
   defaultAction: Allow
   rules:
   - action: Deny
     principal:
       clientCIDRs:

I get this

The SecurityPolicy "tcp-app-2" is invalid: spec.authorization.rules[0].principal: Invalid value: "object": at least one of clientCIDRs, jwt, or headers must be specified

so I don't think its ever hit, i'll remove it and test again

if routeIsTCP {
if tl := xdsIR[irKey].GetTCPListener(irListenerName(listener)); tl != nil {
for _, r := range tl.Routes {
if r == nil || r.Security != nil {
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.

nit: I don't think r would be nil

Suggested change
if r == nil || r.Security != nil {
if r.Security != nil {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks added #7168

// Nothing else to do for this listener in TCP mode
continue
}
}
Copy link
Copy Markdown
Member

@zhaohuabing zhaohuabing Oct 9, 2025

Choose a reason for hiding this comment

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

Should we just return here?

Maybe we can use a switch to make the logic easier to read:

       switch route.GetRouteType() {
		case resource.KindTCPRoute:
			for _, listener := range parentRefCtx.listeners {
				if tl := xdsIR[irKey].GetTCPListener(irListenerName(listener)); tl != nil {
					for _, r := range tl.Routes {
                         if r.Name != expectedTCPRouteName { // exact match only
							continue
						}
                         // if already set - there's a specific level policy, so skip.
						if r.Security != nil {
							continue
						}
						// Only authorization for TCP
						r.Security = &ir.SecurityFeatures{Authorization: authorization}
					}
					// Nothing else to do for this listener in TCP mode
					continue
				}
			}
		case resource.KindHTTPRoute, resource.KindGRPCRoute:
			// The original HTTP/GRPC route logic
		}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think i got this. Can you please review it again? #7168

var tcpSecurityFeatures *ir.SecurityFeatures
if authorization != nil {
tcpSecurityFeatures = &ir.SecurityFeatures{Authorization: authorization}
}
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.

Nit: move this code block right before line 915.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

moved, please see other pr, trying to keep them in sync to help with the review

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.

8 participants