forked from kubernetes-sigs/aws-load-balancer-controller
-
Notifications
You must be signed in to change notification settings - Fork 0
/
protection_synthesizer.go
110 lines (99 loc) · 3.6 KB
/
protection_synthesizer.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
package shield
import (
"context"
"github.com/go-logr/logr"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/util/sets"
"github.com/sonal-chauhan/aws-load-balancer-controller/pkg/model/core"
elbv2model "github.com/sonal-chauhan/aws-load-balancer-controller/pkg/model/elbv2"
shieldmodel "github.com/sonal-chauhan/aws-load-balancer-controller/pkg/model/shield"
)
const (
protectionNameManaged = "managed by aws-load-balancer-controller"
protectionNameManagedLegacy = "managed by aws-alb-ingress-controller"
)
// NewProtectionSynthesizer constructs new protectionSynthesizer
func NewProtectionSynthesizer(protectionManager ProtectionManager, logger logr.Logger, stack core.Stack) *protectionSynthesizer {
return &protectionSynthesizer{
protectionManager: protectionManager,
logger: logger,
stack: stack,
}
}
type protectionSynthesizer struct {
protectionManager ProtectionManager
logger logr.Logger
stack core.Stack
}
func (s *protectionSynthesizer) Synthesize(ctx context.Context) error {
var resProtections []*shieldmodel.Protection
s.stack.ListResources(&resProtections)
resProtectionsByResARN, err := mapResProtectionByResourceARN(resProtections)
if err != nil {
return err
}
var resLBs []*elbv2model.LoadBalancer
s.stack.ListResources(&resLBs)
for _, resLB := range resLBs {
// shield protection can only be associated with ALB for now.
if resLB.Spec.Type != elbv2model.LoadBalancerTypeApplication {
continue
}
lbARN, err := resLB.LoadBalancerARN().Resolve(ctx)
if err != nil {
return err
}
resProtections := resProtectionsByResARN[lbARN]
if err := s.synthesizeProtectionsOnLB(ctx, lbARN, resProtections); err != nil {
return err
}
}
return nil
}
func (s *protectionSynthesizer) PostSynthesize(ctx context.Context) error {
// nothing to do here.
return nil
}
func (s *protectionSynthesizer) synthesizeProtectionsOnLB(ctx context.Context, lbARN string, resProtections []*shieldmodel.Protection) error {
if len(resProtections) > 1 {
return errors.Errorf("[should never happen] multiple shield protection desired on LoadBalancer: %v", lbARN)
}
enableProtection := false
if len(resProtections) == 1 {
enableProtection = true
}
protectionInfo, err := s.protectionManager.GetProtection(ctx, lbARN)
if err != nil {
return err
}
switch {
case !enableProtection && protectionInfo != nil:
managedProtectionNames := sets.NewString(protectionNameManaged, protectionNameManagedLegacy)
if managedProtectionNames.Has(protectionInfo.Name) {
if err := s.protectionManager.DeleteProtection(ctx, lbARN, protectionInfo.ID); err != nil {
return errors.Wrap(err, "failed to delete shield protection on LoadBalancer")
}
} else {
s.logger.Info("ignoring unmanaged shield protection",
"protectionName", protectionInfo.Name,
"protectionID", protectionInfo.ID)
}
case enableProtection && protectionInfo == nil:
if _, err := s.protectionManager.CreateProtection(ctx, lbARN, protectionNameManaged); err != nil {
return errors.Wrap(err, "failed to create shield protection on LoadBalancer")
}
}
return nil
}
func mapResProtectionByResourceARN(resProtections []*shieldmodel.Protection) (map[string][]*shieldmodel.Protection, error) {
resProtectionsByResARN := make(map[string][]*shieldmodel.Protection, len(resProtections))
ctx := context.Background()
for _, resProtection := range resProtections {
resARN, err := resProtection.Spec.ResourceARN.Resolve(ctx)
if err != nil {
return nil, err
}
resProtectionsByResARN[resARN] = append(resProtectionsByResARN[resARN], resProtection)
}
return resProtectionsByResARN, nil
}