Skip to content

Commit

Permalink
fix(MeshTrafficPermission): support permissive mtls (backport of #8171)…
Browse files Browse the repository at this point in the history
… (#8175)

Signed-off-by: Jakub Dyszkiewicz <[email protected]>
Co-authored-by: Jakub Dyszkiewicz <[email protected]>
  • Loading branch information
kumahq[bot] and jakubdyszkiewicz authored Oct 30, 2023
1 parent fd3309a commit 24e6bb9
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 160 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package v1alpha1
import (
envoy_listener "github.com/envoyproxy/go-control-plane/envoy/config/listener/v3"
envoy_resource "github.com/envoyproxy/go-control-plane/pkg/resource/v3"
"github.com/envoyproxy/go-control-plane/pkg/wellknown"

mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1"
"github.com/kumahq/kuma/pkg/core"
Expand Down Expand Up @@ -82,6 +83,10 @@ func (p plugin) Apply(rs *core_xds.ResourceSet, ctx xds_context.Context, proxy *
Mesh: proxy.Dataplane.GetMeta().GetMesh(),
}
for _, filterChain := range listener.FilterChains {
if filterChain.TransportSocket.GetName() != wellknown.TransportSocketTLS {
// we only want to configure RBAC on listeners protected by Kuma's TLS
continue
}
if err := configurer.Configure(filterChain); err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/kumahq/kuma/pkg/test/matchers"
"github.com/kumahq/kuma/pkg/test/resources/builders"
test_model "github.com/kumahq/kuma/pkg/test/resources/model"
"github.com/kumahq/kuma/pkg/test/resources/samples"
util_proto "github.com/kumahq/kuma/pkg/util/proto"
xds_context "github.com/kumahq/kuma/pkg/xds/context"
"github.com/kumahq/kuma/pkg/xds/envoy"
Expand All @@ -30,11 +31,17 @@ var _ = Describe("RBAC", func() {
It("should enrich matching listener with RBAC filter", func() {
// given
rs := core_xds.NewResourceSet()
ctx := xds_context.Context{
Mesh: xds_context.MeshContext{
Resource: samples.MeshMTLSBuilder().WithName("mesh-1").Build(),
},
}

// listener that matches
listener, err := listeners.NewListenerBuilder(envoy.APIV3).
Configure(listeners.InboundListener("test_listener", "192.168.0.1", 8080, core_xds.SocketAddressProtocolTCP)).
Configure(listeners.FilterChain(listeners.NewFilterChainBuilder(envoy.APIV3).
Configure(listeners.ServerSideMTLS(ctx.Mesh.Resource, envoy.NewSecretsTracker(ctx.Mesh.Resource.Meta.GetName(), nil))).
Configure(listeners.HttpConnectionManager("test_listener", false)))).
Build()
Expect(err).ToNot(HaveOccurred())
Expand All @@ -48,6 +55,7 @@ var _ = Describe("RBAC", func() {
listener2, err := listeners.NewListenerBuilder(envoy.APIV3).
Configure(listeners.InboundListener("test_listener2", "192.168.0.1", 8081, core_xds.SocketAddressProtocolTCP)).
Configure(listeners.FilterChain(listeners.NewFilterChainBuilder(envoy.APIV3).
Configure(listeners.ServerSideMTLS(ctx.Mesh.Resource, envoy.NewSecretsTracker(ctx.Mesh.Resource.Meta.GetName(), nil))).
Configure(listeners.HttpConnectionManager("test_listener2", false)))).
Build()
Expect(err).ToNot(HaveOccurred())
Expand All @@ -61,6 +69,7 @@ var _ = Describe("RBAC", func() {
listener3, err := listeners.NewListenerBuilder(envoy.APIV3).
Configure(listeners.InboundListener("test_listener3", "192.168.0.1", 8082, core_xds.SocketAddressProtocolTCP)).
Configure(listeners.FilterChain(listeners.NewFilterChainBuilder(envoy.APIV3).
Configure(listeners.ServerSideMTLS(ctx.Mesh.Resource, envoy.NewSecretsTracker(ctx.Mesh.Resource.Meta.GetName(), nil))).
Configure(listeners.HttpConnectionManager("test_listener3", false)))).
Build()
Expect(err).ToNot(HaveOccurred())
Expand All @@ -70,25 +79,18 @@ var _ = Describe("RBAC", func() {
Resource: listener3,
})

// mesh with enabled mTLS
ctx := xds_context.Context{
Mesh: xds_context.MeshContext{
Resource: &mesh.MeshResource{
Meta: &test_model.ResourceMeta{Name: "mesh-1", Mesh: core_model.NoMesh},
Spec: &mesh_proto.Mesh{
Mtls: &mesh_proto.Mesh_Mtls{
EnabledBackend: "builtin-1",
Backends: []*mesh_proto.CertificateAuthorityBackend{
{
Name: "builtin-1",
Type: "builtin",
},
},
},
},
},
},
}
// listener that matches but it does not have mTLS
listener4, err := listeners.NewListenerBuilder(envoy.APIV3).
Configure(listeners.InboundListener("test_listener4", "192.168.0.1", 8083, core_xds.SocketAddressProtocolTCP)).
Configure(listeners.FilterChain(listeners.NewFilterChainBuilder(envoy.APIV3).
Configure(listeners.HttpConnectionManager("test_listener", false)))).
Build()
Expect(err).ToNot(HaveOccurred())
rs.Add(&core_xds.Resource{
Name: listener4.GetName(),
Origin: generator.OriginInbound,
Resource: listener4,
})

proxy := &core_xds.Proxy{
Dataplane: &mesh.DataplaneResource{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,28 @@ resources:
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
statPrefix: test_listener
transportSocket:
name: envoy.transport_sockets.tls
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
commonTlsContext:
combinedValidationContext:
defaultValidationContext:
matchTypedSubjectAltNames:
- matcher:
prefix: spiffe://mesh-1/
sanType: URI
validationContextSdsSecretConfig:
name: mesh_ca:secret:mesh-1
sdsConfig:
ads: {}
resourceApiVersion: V3
tlsCertificateSdsSecretConfigs:
- name: identity_cert:secret:mesh-1
sdsConfig:
ads: {}
resourceApiVersion: V3
requireClientCertificate: true
name: test_listener
trafficDirection: INBOUND
- name: test_listener2
Expand All @@ -50,6 +72,28 @@ resources:
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
statPrefix: test_listener2
transportSocket:
name: envoy.transport_sockets.tls
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
commonTlsContext:
combinedValidationContext:
defaultValidationContext:
matchTypedSubjectAltNames:
- matcher:
prefix: spiffe://mesh-1/
sanType: URI
validationContextSdsSecretConfig:
name: mesh_ca:secret:mesh-1
sdsConfig:
ads: {}
resourceApiVersion: V3
tlsCertificateSdsSecretConfigs:
- name: identity_cert:secret:mesh-1
sdsConfig:
ads: {}
resourceApiVersion: V3
requireClientCertificate: true
name: test_listener2
trafficDirection: INBOUND
- name: test_listener3
Expand All @@ -70,5 +114,47 @@ resources:
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
statPrefix: test_listener3
transportSocket:
name: envoy.transport_sockets.tls
typedConfig:
'@type': type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
commonTlsContext:
combinedValidationContext:
defaultValidationContext:
matchTypedSubjectAltNames:
- matcher:
prefix: spiffe://mesh-1/
sanType: URI
validationContextSdsSecretConfig:
name: mesh_ca:secret:mesh-1
sdsConfig:
ads: {}
resourceApiVersion: V3
tlsCertificateSdsSecretConfigs:
- name: identity_cert:secret:mesh-1
sdsConfig:
ads: {}
resourceApiVersion: V3
requireClientCertificate: true
name: test_listener3
trafficDirection: INBOUND
- name: test_listener4
resource:
'@type': type.googleapis.com/envoy.config.listener.v3.Listener
address:
socketAddress:
address: 192.168.0.1
portValue: 8083
enableReusePort: false
filterChains:
- filters:
- name: envoy.filters.network.http_connection_manager
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
httpFilters:
- name: envoy.filters.http.router
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
statPrefix: test_listener
name: test_listener4
trafficDirection: INBOUND
7 changes: 7 additions & 0 deletions pkg/test/resources/builders/mesh_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ func (m *MeshBuilder) WithoutMTLSBackends() *MeshBuilder {
return m
}

func (m *MeshBuilder) WithPermissiveMTLSBackends() *MeshBuilder {
for _, backend := range m.res.Spec.Mtls.Backends {
backend.Mode = mesh_proto.CertificateAuthorityBackend_PERMISSIVE
}
return m
}

func (m *MeshBuilder) AddBuiltinMTLSBackend(name string) *MeshBuilder {
if m.res.Spec.Mtls == nil {
m.res.Spec.Mtls = &mesh_proto.Mesh_Mtls{}
Expand Down
14 changes: 9 additions & 5 deletions pkg/xds/generator/inbound_proxy_generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,7 @@ func (g InboundProxyGenerator) Generate(ctx context.Context, xdsCtx xds_context.
Configure(envoy_listeners.ServerSideMTLS(xdsCtx.Mesh.Resource, proxy.SecretsTracker))
}
return filterChainBuilder.
Configure(envoy_listeners.Timeout(defaults_mesh.DefaultInboundTimeout(), protocol)).
Configure(envoy_listeners.NetworkRBAC(inboundListenerName, xdsCtx.Mesh.Resource.MTLSEnabled(),
proxy.Policies.TrafficPermissions[endpoint]))
Configure(envoy_listeners.Timeout(defaults_mesh.DefaultInboundTimeout(), protocol))
}

listenerBuilder := envoy_listeners.NewListenerBuilder(proxy.APIVersion).
Expand All @@ -138,7 +136,9 @@ func (g InboundProxyGenerator) Generate(ctx context.Context, xdsCtx xds_context.
switch xdsCtx.Mesh.Resource.GetEnabledCertificateAuthorityBackend().GetMode() {
case mesh_proto.CertificateAuthorityBackend_STRICT:
listenerBuilder.
Configure(envoy_listeners.FilterChain(filterChainBuilder(true)))
Configure(envoy_listeners.FilterChain(filterChainBuilder(true).Configure(
envoy_listeners.NetworkRBAC(inboundListenerName, xdsCtx.Mesh.Resource.MTLSEnabled(), proxy.Policies.TrafficPermissions[endpoint]),
)))
case mesh_proto.CertificateAuthorityBackend_PERMISSIVE:
listenerBuilder.
Configure(envoy_listeners.TLSInspector()).
Expand All @@ -147,13 +147,17 @@ func (g InboundProxyGenerator) Generate(ctx context.Context, xdsCtx xds_context.
envoy_listeners.MatchTransportProtocol("raw_buffer"))),
).
Configure(envoy_listeners.FilterChain(
// we need to differentiate between just TLS and Kuma's TLS, because with permissive mode
// the app itself might be protected by TLS.
filterChainBuilder(false).Configure(
envoy_listeners.MatchTransportProtocol("tls"))),
).
Configure(envoy_listeners.FilterChain(
filterChainBuilder(true).Configure(
envoy_listeners.MatchTransportProtocol("tls"),
envoy_listeners.MatchApplicationProtocols(xds_tls.KumaALPNProtocols...))),
envoy_listeners.MatchApplicationProtocols(xds_tls.KumaALPNProtocols...),
envoy_listeners.NetworkRBAC(inboundListenerName, xdsCtx.Mesh.Resource.MTLSEnabled(), proxy.Policies.TrafficPermissions[endpoint]),
)),
)
default:
return nil, errors.New("unknown mode for CA backend")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,6 @@ resources:
- filterChainMatch:
transportProtocol: raw_buffer
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules: {}
statPrefix: inbound_192_168_0_1_443.
- name: envoy.filters.network.tcp_proxy
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
Expand All @@ -64,11 +59,6 @@ resources:
- filterChainMatch:
transportProtocol: tls
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules: {}
statPrefix: inbound_192_168_0_1_443.
- name: envoy.filters.network.tcp_proxy
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
Expand Down Expand Up @@ -135,24 +125,6 @@ resources:
- filterChainMatch:
transportProtocol: raw_buffer
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules:
policies:
tp-1:
permissions:
- any: true
principals:
- andIds:
ids:
- authenticated:
principalName:
exact: kuma://version/1.0
- authenticated:
principalName:
exact: spiffe://default/web1
statPrefix: inbound_192_168_0_1_80.
- name: envoy.filters.network.http_connection_manager
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
Expand Down Expand Up @@ -260,24 +232,6 @@ resources:
- filterChainMatch:
transportProtocol: tls
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules:
policies:
tp-1:
permissions:
- any: true
principals:
- andIds:
ids:
- authenticated:
principalName:
exact: kuma://version/1.0
- authenticated:
principalName:
exact: spiffe://default/web1
statPrefix: inbound_192_168_0_1_80.
- name: envoy.filters.network.http_connection_manager
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
Expand Down Expand Up @@ -554,11 +508,6 @@ resources:
- filterChainMatch:
transportProtocol: raw_buffer
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules: {}
statPrefix: inbound_192_168_0_2_443.
- name: envoy.filters.network.tcp_proxy
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
Expand All @@ -568,11 +517,6 @@ resources:
- filterChainMatch:
transportProtocol: tls
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules: {}
statPrefix: inbound_192_168_0_2_443.
- name: envoy.filters.network.tcp_proxy
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
Expand Down Expand Up @@ -639,11 +583,6 @@ resources:
- filterChainMatch:
transportProtocol: raw_buffer
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules: {}
statPrefix: inbound_192_168_0_2_80.
- name: envoy.filters.network.http_connection_manager
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
Expand Down Expand Up @@ -676,11 +615,6 @@ resources:
- filterChainMatch:
transportProtocol: tls
filters:
- name: envoy.filters.network.rbac
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC
rules: {}
statPrefix: inbound_192_168_0_2_80.
- name: envoy.filters.network.http_connection_manager
typedConfig:
'@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
Expand Down
Loading

0 comments on commit 24e6bb9

Please sign in to comment.