-
Notifications
You must be signed in to change notification settings - Fork 685
/
syntheticauth.go
119 lines (109 loc) · 4.73 KB
/
syntheticauth.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
package entrypoint
import (
"context"
"fmt"
"github.com/datawire/dlib/dlog"
"github.com/emissary-ingress/emissary/v3/pkg/api/getambassador.io/v3alpha1"
"github.com/emissary-ingress/emissary/v3/pkg/emissaryutil"
"github.com/emissary-ingress/emissary/v3/pkg/kates"
)
// Checks if the provided string is a loopback IP address with port 8500
func IsLocalhost8500(svcStr string) bool {
_, hostname, port, err := emissaryutil.ParseServiceName(svcStr)
return err == nil && port == 8500 && emissaryutil.IsLocalhost(hostname)
}
func iterateOverAuthServices(sh *SnapshotHolder, cb func(
authService *v3alpha1.AuthService, // duh
name string, // name to unambiguously refer to the authService by; might be more complex than "name.namespace" if it's an annotation
parentName string, // name of the thing that the annotation is on (or empty if not an annotation)
idx int, // index of the authService; either in sh.k8sSnapshot.AuthServices or in sh.k8sSnapshot.Annotations[parentName]
)) {
envAmbID := GetAmbassadorID()
for i, authService := range sh.k8sSnapshot.AuthServices {
if authService.Spec.AmbassadorID.Matches(envAmbID) {
name := authService.TypeMeta.Kind + "/" + authService.ObjectMeta.Name + "." + authService.ObjectMeta.Namespace
cb(authService, name, "", i)
}
}
for parentName, list := range sh.k8sSnapshot.Annotations {
for i, obj := range list {
if authService, ok := obj.(*v3alpha1.AuthService); ok && authService.Spec.AmbassadorID.Matches(envAmbID) {
name := fmt.Sprintf("%s#%d", parentName, i)
cb(authService, name, parentName, i)
}
}
}
}
// This is a gross hack to remove all AuthServices using protocol_version: v2 only when running Edge-Stack and then inject an
// AuthService with protocol_version: v3 if needed. The purpose of this hack is to prevent Edge-Stack 2.3 from
// using any other AuthService than the default one running as part of amb-sidecar and force the protocol version to v3.
func ReconcileAuthServices(ctx context.Context, sh *SnapshotHolder, deltas *[]*kates.Delta) error {
// We only want to remove AuthServices if this is an instance of Edge-Stack
if isEdgeStack, err := IsEdgeStack(); err != nil {
return fmt.Errorf("ReconcileAuthServices: %w", err)
} else if !isEdgeStack {
return nil
}
// using a name with underscores prevents it from colliding with anything real in the
// cluster--Kubernetes resources can't have underscores in their name.
const syntheticAuthServiceName = "synthetic_edge_stack_auth"
var (
numAuthServices uint64
syntheticAuth *v3alpha1.AuthService
syntheticAuthIdx int
)
iterateOverAuthServices(sh, func(authService *v3alpha1.AuthService, name, parentName string, i int) {
numAuthServices++
if IsLocalhost8500(authService.Spec.AuthService) {
if parentName == "" && authService.ObjectMeta.Name == syntheticAuthServiceName {
syntheticAuth = authService
syntheticAuthIdx = i
}
if authService.Spec.ProtocolVersion != "v3" {
// Force the Edge Stack AuthService to be protocol_version=v3. This
// is important so that <2.3 and >=2.3 installations can coexist.
// This is important, because for zero-downtime upgrades, they must
// coexist briefly while the new Deployment is getting rolled out.
dlog.Debugf(ctx, "ReconcileAuthServices: Forcing protocol_version=v3 on %s", name)
authService.Spec.ProtocolVersion = "v3"
}
}
})
switch {
case numAuthServices == 0: // add the synthetic auth service
dlog.Debug(ctx, "ReconcileAuthServices: No user-provided AuthServices detected; injecting synthetic AuthService")
syntheticAuth = &v3alpha1.AuthService{
TypeMeta: kates.TypeMeta{
Kind: "AuthService",
APIVersion: "getambassador.io/v3alpha1",
},
ObjectMeta: kates.ObjectMeta{
Name: syntheticAuthServiceName,
Namespace: GetAmbassadorNamespace(),
},
Spec: v3alpha1.AuthServiceSpec{
AmbassadorID: []string{GetAmbassadorID()},
AuthService: "127.0.0.1:8500",
Proto: "grpc",
ProtocolVersion: "v3",
},
}
sh.k8sSnapshot.AuthServices = append(sh.k8sSnapshot.AuthServices, syntheticAuth)
*deltas = append(*deltas, &kates.Delta{
TypeMeta: syntheticAuth.TypeMeta,
ObjectMeta: syntheticAuth.ObjectMeta,
DeltaType: kates.ObjectAdd,
})
case numAuthServices > 1 && syntheticAuth != nil: // remove the synthetic auth service
dlog.Debugf(ctx, "ReconcileAuthServices: %d user-provided AuthServices detected; removing synthetic AuthService", numAuthServices-1)
sh.k8sSnapshot.AuthServices = append(
sh.k8sSnapshot.AuthServices[:syntheticAuthIdx],
sh.k8sSnapshot.AuthServices[syntheticAuthIdx+1:]...)
*deltas = append(*deltas, &kates.Delta{
TypeMeta: syntheticAuth.TypeMeta,
ObjectMeta: syntheticAuth.ObjectMeta,
DeltaType: kates.ObjectDelete,
})
}
return nil
}