-
Notifications
You must be signed in to change notification settings - Fork 337
/
Copy pathadmin_proxy_generator.go
124 lines (106 loc) · 4.33 KB
/
admin_proxy_generator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package generator
import (
"context"
"github.com/asaskevich/govalidator"
core_xds "github.com/kumahq/kuma/pkg/core/xds"
xds_context "github.com/kumahq/kuma/pkg/xds/context"
envoy_common "github.com/kumahq/kuma/pkg/xds/envoy"
envoy_clusters "github.com/kumahq/kuma/pkg/xds/envoy/clusters"
envoy_listeners "github.com/kumahq/kuma/pkg/xds/envoy/listeners"
envoy_names "github.com/kumahq/kuma/pkg/xds/envoy/names"
)
// OriginAdmin is a marker to indicate by which ProxyGenerator resources were generated.
const OriginAdmin = "admin"
var staticEndpointPaths = []*envoy_common.StaticEndpointPath{
{
Path: "/ready",
RewritePath: "/ready",
},
}
var staticTlsEndpointPaths = []*envoy_common.StaticEndpointPath{
{
Path: "/",
RewritePath: "/",
},
}
// AdminProxyGenerator generates resources to expose some endpoints of Admin API on public interface.
// By default, Admin API is exposed only on loopback interface because of security reasons.
type AdminProxyGenerator struct{}
func (g AdminProxyGenerator) Generate(ctx context.Context, xdsCtx xds_context.Context, proxy *core_xds.Proxy) (*core_xds.ResourceSet, error) {
if proxy.Metadata.GetAdminPort() == 0 {
// It's not possible to export Admin endpoints if Envoy Admin API has not been enabled on that dataplane.
return nil, nil
}
adminPort := proxy.Metadata.GetAdminPort()
// We assume that Admin API must be available on a loopback interface (while users
// can override the default value `127.0.0.1` in the Bootstrap Server section of `kuma-cp` config,
// the only reasonable alternative is `0.0.0.0`).
// In contrast to `AdminPort`, we shouldn't trust `AdminAddress` from the Envoy node metadata
// since it would allow a malicious user to manipulate that value and use Prometheus endpoint
// as a gateway to another host.
envoyAdminClusterName := envoy_names.GetEnvoyAdminClusterName()
adminAddress := proxy.Metadata.GetAdminAddress()
if adminAddress == "" {
adminAddress = "127.0.0.1"
}
cluster, err := envoy_clusters.NewClusterBuilder(proxy.APIVersion, envoyAdminClusterName).
Configure(envoy_clusters.ProvidedEndpointCluster(
govalidator.IsIPv6(adminAddress),
core_xds.Endpoint{Target: adminAddress, Port: adminPort})).
Configure(envoy_clusters.DefaultTimeout()).
Build()
if err != nil {
return nil, err
}
resources := core_xds.NewResourceSet()
for _, se := range staticEndpointPaths {
se.ClusterName = envoyAdminClusterName
}
// We bind admin to 127.0.0.1 by default, creating another listener with same address and port will result in error.
if g.getAddress(proxy) != adminAddress {
filterChains := []envoy_listeners.ListenerBuilderOpt{
envoy_listeners.FilterChain(envoy_listeners.NewFilterChainBuilder(proxy.APIVersion, envoy_common.AnonymousResource).
Configure(envoy_listeners.StaticEndpoints(envoy_names.GetAdminListenerName(), staticEndpointPaths)),
),
}
for _, se := range staticTlsEndpointPaths {
se.ClusterName = envoyAdminClusterName
}
filterChains = append(filterChains, envoy_listeners.FilterChain(envoy_listeners.NewFilterChainBuilder(proxy.APIVersion, envoy_common.AnonymousResource).
Configure(envoy_listeners.MatchTransportProtocol("tls")).
Configure(envoy_listeners.StaticEndpoints(envoy_names.GetAdminListenerName(), staticTlsEndpointPaths)).
Configure(envoy_listeners.ServerSideStaticMTLS(proxy.EnvoyAdminMTLSCerts)),
))
listener, err := envoy_listeners.NewInboundListenerBuilder(proxy.APIVersion, g.getAddress(proxy), adminPort, core_xds.SocketAddressProtocolTCP).
WithOverwriteName(envoy_names.GetAdminListenerName()).
Configure(envoy_listeners.TLSInspector()).
Configure(filterChains...).
Build()
if err != nil {
return nil, err
}
resources.Add(&core_xds.Resource{
Name: listener.GetName(),
Origin: OriginAdmin,
Resource: listener,
})
}
resources.Add(&core_xds.Resource{
Name: cluster.GetName(),
Origin: OriginAdmin,
Resource: cluster,
})
return resources, nil
}
func (g AdminProxyGenerator) getAddress(proxy *core_xds.Proxy) string {
if proxy.Dataplane != nil {
return proxy.Dataplane.Spec.GetNetworking().Address
}
if proxy.ZoneEgressProxy != nil {
return proxy.ZoneEgressProxy.ZoneEgressResource.Spec.GetNetworking().GetAddress()
}
if proxy.ZoneIngressProxy != nil {
return proxy.ZoneIngressProxy.ZoneIngressResource.Spec.GetNetworking().GetAddress()
}
return ""
}