Skip to content
This repository was archived by the owner on Jul 11, 2023. It is now read-only.

Commit 436e24f

Browse files
authoredJun 2, 2022
Decouple certificate common name from proxy registry (#4763)
* Decouple certificate common name from proxy registry Signed-off-by: Sean Teeling <[email protected]> * address comment 1 Signed-off-by: Sean Teeling <[email protected]>
1 parent 28ed531 commit 436e24f

File tree

7 files changed

+86
-74
lines changed

7 files changed

+86
-74
lines changed
 

‎pkg/debugger/proxy.go

+56-36
Original file line numberDiff line numberDiff line change
@@ -6,71 +6,91 @@ import (
66
"sort"
77
"time"
88

9-
"github.com/openservicemesh/osm/pkg/certificate"
109
"github.com/openservicemesh/osm/pkg/envoy"
1110
)
1211

1312
const (
14-
specificProxyQueryKey = "proxy"
15-
proxyConfigQueryKey = "cfg"
13+
uuidQueryKey = "uuid"
14+
proxyConfigQueryKey = "cfg"
1615
)
1716

1817
func (ds DebugConfig) getProxies() http.Handler {
19-
// This function is needed to convert the list of connected proxies to
20-
// the type (map) required by the printProxies function.
21-
listConnected := func() map[certificate.CommonName]time.Time {
22-
proxies := make(map[certificate.CommonName]time.Time)
23-
for _, proxy := range ds.proxyRegistry.ListConnectedProxies() {
24-
proxies[proxy.GetCertificateCommonName()] = (*proxy).GetConnectedAt()
25-
}
26-
return proxies
27-
}
28-
2918
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
3019
w.Header().Set("Content-Type", "text/html")
31-
if proxyConfigDump, ok := r.URL.Query()[proxyConfigQueryKey]; ok {
32-
ds.getConfigDump(certificate.CommonName(proxyConfigDump[0]), w)
33-
} else if specificProxy, ok := r.URL.Query()[specificProxyQueryKey]; ok {
34-
ds.getProxy(certificate.CommonName(specificProxy[0]), w)
35-
} else {
36-
printProxies(w, listConnected(), "Connected")
20+
proxyConfigDump := r.URL.Query()[proxyConfigQueryKey]
21+
uuid := r.URL.Query()[uuidQueryKey]
22+
23+
switch {
24+
case len(uuid) == 0:
25+
ds.printProxies(w)
26+
case len(proxyConfigDump) > 0:
27+
ds.getConfigDump(uuid[0], w)
28+
default:
29+
ds.getProxy(uuid[0], w)
3730
}
3831
})
3932
}
4033

41-
func printProxies(w http.ResponseWriter, proxies map[certificate.CommonName]time.Time, category string) {
42-
var commonNames []string
43-
for cn := range proxies {
44-
commonNames = append(commonNames, cn.String())
34+
func (ds DebugConfig) printProxies(w http.ResponseWriter) {
35+
// This function is needed to convert the list of connected proxies to
36+
// the type (map) required by the printProxies function.
37+
proxyMap := ds.proxyRegistry.ListConnectedProxies()
38+
proxies := make([]*envoy.Proxy, 0, len(proxyMap))
39+
for _, proxy := range proxyMap {
40+
proxies = append(proxies, proxy)
4541
}
4642

47-
sort.Strings(commonNames)
43+
sort.Slice(proxies, func(i, j int) bool {
44+
return proxies[i].Identity.String() < proxies[j].Identity.String()
45+
})
4846

49-
_, _ = fmt.Fprintf(w, "<h1>%s Proxies (%d):</h1>", category, len(proxies))
47+
_, _ = fmt.Fprintf(w, "<h1>Connected Proxies (%d):</h1>", len(proxies))
5048
_, _ = fmt.Fprint(w, `<table>`)
51-
_, _ = fmt.Fprint(w, "<tr><td>#</td><td>Envoy's certificate CN</td><td>Connected At</td><td>How long ago</td><td>tools</td></tr>")
52-
for idx, cn := range commonNames {
53-
ts := proxies[certificate.CommonName(cn)]
54-
_, _ = fmt.Fprintf(w, `<tr><td>%d:</td><td>%s</td><td>%+v</td><td>(%+v ago)</td><td><a href="/debug/proxy?%s=%s">certs</a></td><td><a href="/debug/proxy?%s=%s">cfg</a></td></tr>`,
55-
idx, cn, ts, time.Since(ts), specificProxyQueryKey, cn, proxyConfigQueryKey, cn)
49+
_, _ = fmt.Fprint(w, "<tr><td>#</td><td>Envoy's Service Identity</td><td>Envoy's UUID</td><td>Connected At</td><td>How long ago</td><td>tools</td></tr>")
50+
for idx, proxy := range proxies {
51+
ts := proxy.GetConnectedAt()
52+
proxyURL := fmt.Sprintf("/debug/proxy?%s=%s", uuidQueryKey, proxy.UUID)
53+
configDumpURL := fmt.Sprintf("%s&%s=%t", proxyURL, proxyConfigQueryKey, true)
54+
_, _ = fmt.Fprintf(w, `<tr><td>%d:</td><td>%s</td><td>%+v</td><td>(%+v ago)</td><td><a href="%s">certs</a></td><td><a href="%s">cfg</a></td></tr>`,
55+
idx+1, proxy.Identity, ts, time.Since(ts), proxyURL, configDumpURL)
5656
}
5757
_, _ = fmt.Fprint(w, `</table>`)
5858
}
5959

60-
func (ds DebugConfig) getConfigDump(cn certificate.CommonName, w http.ResponseWriter) {
61-
pod, err := envoy.GetPodFromCertificate(cn, ds.kubeController)
60+
func (ds DebugConfig) getConfigDump(uuid string, w http.ResponseWriter) {
61+
proxy, ok := ds.proxyRegistry.GetConnectedProxy(uuid)
62+
if !ok {
63+
msg := fmt.Sprintf("Proxy for UUID %s not found, may have been disconnected", uuid)
64+
log.Error().Msg(msg)
65+
http.Error(w, msg, http.StatusNotFound)
66+
return
67+
}
68+
pod, err := envoy.GetPodFromCertificate(proxy.GetCertificateCommonName(), ds.kubeController)
6269
if err != nil {
63-
log.Error().Err(err).Msgf("Error getting Pod from certificate with CN=%s", cn)
70+
msg := fmt.Sprintf("Error getting Pod from certificate with CN=%s", proxy.GetCertificateCommonName())
71+
log.Error().Err(err).Msg(msg)
72+
http.Error(w, msg, http.StatusNotFound)
73+
return
6474
}
6575
w.Header().Set("Content-Type", "application/json")
6676
envoyConfig := ds.getEnvoyConfig(pod, "config_dump")
6777
_, _ = fmt.Fprintf(w, "%s", envoyConfig)
6878
}
6979

70-
func (ds DebugConfig) getProxy(cn certificate.CommonName, w http.ResponseWriter) {
71-
pod, err := envoy.GetPodFromCertificate(cn, ds.kubeController)
80+
func (ds DebugConfig) getProxy(uuid string, w http.ResponseWriter) {
81+
proxy, ok := ds.proxyRegistry.GetConnectedProxy(uuid)
82+
if !ok {
83+
msg := fmt.Sprintf("Proxy for UUID %s not found, may have been disconnected", uuid)
84+
log.Error().Msg(msg)
85+
http.Error(w, msg, http.StatusNotFound)
86+
return
87+
}
88+
pod, err := envoy.GetPodFromCertificate(proxy.GetCertificateCommonName(), ds.kubeController)
7289
if err != nil {
73-
log.Error().Err(err).Msgf("Error getting Pod from certificate with CN=%s", cn)
90+
msg := fmt.Sprintf("Error getting Pod from certificate with CN=%s", proxy.GetCertificateCommonName())
91+
log.Error().Err(err).Msg(msg)
92+
http.Error(w, msg, http.StatusNotFound)
93+
return
7494
}
7595
w.Header().Set("Content-Type", "application/json")
7696
envoyConfig := ds.getEnvoyConfig(pod, "certs")

‎pkg/envoy/ads/stream.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (s *Server) StreamAggregatedResources(server xds_discovery.AggregatedDiscov
3333
}
3434

3535
// If maxDataPlaneConnections is enabled i.e. not 0, then check that the number of Envoy connections is less than maxDataPlaneConnections
36-
if s.cfg.GetMaxDataPlaneConnections() != 0 && s.proxyRegistry.GetConnectedProxyCount() >= s.cfg.GetMaxDataPlaneConnections() {
36+
if s.cfg.GetMaxDataPlaneConnections() > 0 && s.proxyRegistry.GetConnectedProxyCount() >= s.cfg.GetMaxDataPlaneConnections() {
3737
metricsstore.DefaultMetricsStore.ProxyMaxConnectionsRejected.Inc()
3838
return errTooManyConnections
3939
}

‎pkg/envoy/registry/announcement_handlers.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/openservicemesh/osm/pkg/announcements"
77
"github.com/openservicemesh/osm/pkg/constants"
8+
"github.com/openservicemesh/osm/pkg/envoy"
89
"github.com/openservicemesh/osm/pkg/k8s/events"
910
)
1011

@@ -35,8 +36,8 @@ func (pr *ProxyRegistry) ReleaseCertificateHandler(certManager certificateReleas
3536

3637
proxyUUID := deletedPodObj.Labels[constants.EnvoyUniqueIDLabelName]
3738
if proxyIface, ok := pr.connectedProxies.Load(proxyUUID); ok {
38-
connectedProxy := proxyIface.(connectedProxy)
39-
cn := connectedProxy.proxy.GetCertificateCommonName()
39+
proxy := proxyIface.(*envoy.Proxy)
40+
cn := proxy.GetCertificateCommonName()
4041
log.Warn().Msgf("Pod with label %s: %s found in proxy registry; releasing certificate %s", constants.EnvoyUniqueIDLabelName, proxyUUID, cn)
4142
certManager.ReleaseCertificate(cn)
4243
} else {

‎pkg/envoy/registry/debugger.go

-17
This file was deleted.

‎pkg/envoy/registry/registry.go

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package registry
22

33
import (
4-
"time"
5-
64
"github.com/openservicemesh/osm/pkg/envoy"
75
"github.com/openservicemesh/osm/pkg/messaging"
86
)
@@ -15,22 +13,40 @@ func NewProxyRegistry(mapper ProxyServiceMapper, msgBroker *messaging.Broker) *P
1513
}
1614
}
1715

18-
// RegisterProxy implements MeshCatalog and registers a newly connected proxy.
16+
// RegisterProxy registers a newly connected proxy.
1917
func (pr *ProxyRegistry) RegisterProxy(proxy *envoy.Proxy) {
20-
pr.connectedProxies.Store(proxy.UUID.String(), connectedProxy{
21-
proxy: proxy,
22-
connectedAt: time.Now(),
23-
})
18+
pr.connectedProxies.Store(proxy.UUID.String(), proxy)
2419
log.Debug().Str("proxy", proxy.String()).Msg("Registered new proxy")
2520
}
2621

22+
// GetConnectedProxy loads a connected proxy from the registry.
23+
func (pr *ProxyRegistry) GetConnectedProxy(uuid string) (*envoy.Proxy, bool) {
24+
p, ok := pr.connectedProxies.Load(uuid)
25+
if !ok {
26+
return nil, false
27+
}
28+
return p.(*envoy.Proxy), true
29+
}
30+
2731
// UnregisterProxy unregisters the given proxy from the catalog.
2832
func (pr *ProxyRegistry) UnregisterProxy(p *envoy.Proxy) {
2933
pr.connectedProxies.Delete(p.UUID.String())
3034
log.Debug().Msgf("Unregistered proxy %s", p.String())
3135
}
3236

3337
// GetConnectedProxyCount counts the number of connected proxies
38+
// TODO(steeling): switch to a regular map with mutex so we can get the count without iterating the entire list.
3439
func (pr *ProxyRegistry) GetConnectedProxyCount() int {
3540
return len(pr.ListConnectedProxies())
3641
}
42+
43+
// ListConnectedProxies lists the Envoy proxies already connected and the time they first connected.
44+
func (pr *ProxyRegistry) ListConnectedProxies() map[string]*envoy.Proxy {
45+
proxies := make(map[string]*envoy.Proxy)
46+
pr.connectedProxies.Range(func(keyIface, propsIface interface{}) bool {
47+
uuid := keyIface.(string)
48+
proxies[uuid] = propsIface.(*envoy.Proxy)
49+
return true // continue the iteration
50+
})
51+
return proxies
52+
}

‎pkg/envoy/registry/debugger_test.go ‎pkg/envoy/registry/registry_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/google/uuid"
7+
78
. "github.com/onsi/ginkgo"
89
. "github.com/onsi/gomega"
910

@@ -13,7 +14,8 @@ import (
1314

1415
var _ = Describe("Test catalog proxy register/unregister", func() {
1516
proxyRegistry := NewProxyRegistry(nil, nil)
16-
certCommonName := certificate.CommonName(fmt.Sprintf("%s.sidecar.foo.bar", uuid.New()))
17+
uuid := uuid.New()
18+
certCommonName := certificate.CommonName(fmt.Sprintf("%s.sidecar.foo.bar", uuid))
1719
certSerialNumber := certificate.SerialNumber("123456")
1820
proxy, err := envoy.NewProxy(certCommonName, certSerialNumber, nil)
1921

‎pkg/envoy/registry/types.go

-10
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@ package registry
22

33
import (
44
"sync"
5-
"time"
65

76
"github.com/openservicemesh/osm/pkg/certificate"
8-
"github.com/openservicemesh/osm/pkg/envoy"
97
"github.com/openservicemesh/osm/pkg/logger"
108
"github.com/openservicemesh/osm/pkg/messaging"
119
)
@@ -22,14 +20,6 @@ type ProxyRegistry struct {
2220
msgBroker *messaging.Broker
2321
}
2422

25-
type connectedProxy struct {
26-
// Proxy which connected to the XDS control plane
27-
proxy *envoy.Proxy
28-
29-
// When the proxy connected to the XDS control plane
30-
connectedAt time.Time
31-
}
32-
3323
// A simple interface to release certificates. Created to abstract the certificate.Manager struct for testing purposes.
3424
type certificateReleaser interface {
3525
ReleaseCertificate(cn certificate.CommonName)

0 commit comments

Comments
 (0)
This repository has been archived.