Skip to content

Refactored WAF code and added caches #437

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 33 additions & 33 deletions pkg/alb/lb/loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func NewDesiredLoadBalancer(o *NewDesiredLoadBalancerOptions) (newLoadBalancer *
options: options{
desired: opts{
idleTimeout: o.Annotations.ConnectionIdleTimeout,
wafACLID: o.Annotations.WafACLID,
webACLId: o.Annotations.WebACLId,
},
},
lb: lb{
Expand Down Expand Up @@ -103,7 +103,7 @@ func NewDesiredLoadBalancer(o *NewDesiredLoadBalancerOptions) (newLoadBalancer *
existinglb.lb.desired = newLoadBalancer.lb.desired
existinglb.tags.desired = newLoadBalancer.tags.desired
existinglb.options.desired.idleTimeout = newLoadBalancer.options.desired.idleTimeout
existinglb.options.desired.wafACLID = newLoadBalancer.options.desired.wafACLID
existinglb.options.desired.webACLId = newLoadBalancer.options.desired.webACLId
if len(o.ExistingLoadBalancer.lb.desired.SecurityGroups) == 0 {
existinglb.options.desired.ports = lsps
existinglb.options.desired.inboundCidrs = o.Annotations.InboundCidrs
Expand Down Expand Up @@ -245,13 +245,13 @@ func NewCurrentLoadBalancer(o *NewCurrentLoadBalancerOptions) (newLoadBalancer *
}

// Check WAF
wafResult, err := albwaf.WAFRegionalsvc.GetWebACLSummary(o.LoadBalancer.LoadBalancerArn)
webACLResult, err := albwaf.WAFRegionalsvc.GetWebACLSummary(o.LoadBalancer.LoadBalancerArn)
if err != nil {
return newLoadBalancer, fmt.Errorf("Failed to get associated WAF ACL. Error: %s", err.Error())
return newLoadBalancer, fmt.Errorf("Failed to get associated Web ACL. Error: %s", err.Error())
}
var wafACLID *string
if wafResult != nil {
wafACLID = wafResult.WebACLId
var webACLId *string
if webACLResult != nil {
webACLId = webACLResult.WebACLId
}

newLoadBalancer = &LoadBalancer{
Expand All @@ -265,7 +265,7 @@ func NewCurrentLoadBalancer(o *NewCurrentLoadBalancerOptions) (newLoadBalancer *
ports: managedSGPorts,
managedInstanceSG: managedInstanceSG,
idleTimeout: idleTimeout,
wafACLID: wafACLID,
webACLId: webACLId,
},
},
}
Expand Down Expand Up @@ -519,11 +519,11 @@ func (l *LoadBalancer) create(rOpts *ReconcileOptions) error {
}
}

if l.options.desired.wafACLID != nil {
_, err = albwaf.WAFRegionalsvc.Associate(l.lb.current.LoadBalancerArn, l.options.desired.wafACLID)
if l.options.desired.webACLId != nil {
_, err = albwaf.WAFRegionalsvc.Associate(l.lb.current.LoadBalancerArn, l.options.desired.webACLId)
if err != nil {
rOpts.Eventf(api.EventTypeWarning, "ERROR", "%s WAF (%s) association failed: %s", *l.lb.current.LoadBalancerName, l.options.desired.wafACLID, err.Error())
l.logger.Errorf("Failed ELBV2 (ALB) WAF (%s) association: %s", l.options.desired.wafACLID, err.Error())
rOpts.Eventf(api.EventTypeWarning, "ERROR", "%s Web ACL (%s) association failed: %s", *l.lb.current.LoadBalancerName, l.options.desired.webACLId, err.Error())
l.logger.Errorf("Failed ELBV2 (ALB) Web ACL (%s) association: %s", l.options.desired.webACLId, err.Error())
return err
}
}
Expand Down Expand Up @@ -644,24 +644,24 @@ func (l *LoadBalancer) modify(rOpts *ReconcileOptions) error {
l.logger.Infof("Completed ELBV2 tag modification. Attributes are %s.", log.Prettify(l.attributes.current))
}

if needsMod&wafAssociationModified != 0 {
if l.options.desired.wafACLID != nil {
if _, err := albwaf.WAFRegionalsvc.Associate(l.lb.current.LoadBalancerArn, l.options.desired.wafACLID); err != nil {
rOpts.Eventf(api.EventTypeWarning, "ERROR", "%s Waf (%s) association failed: %s", *l.lb.current.LoadBalancerName, *l.options.desired.wafACLID, err.Error())
l.logger.Errorf("Failed ELBV2 (ALB) Waf (%s) association failed: %s", *l.options.desired.wafACLID, err.Error())
if needsMod&webACLAssociationModified != 0 {
if l.options.desired.webACLId != nil {
if _, err := albwaf.WAFRegionalsvc.Associate(l.lb.current.LoadBalancerArn, l.options.desired.webACLId); err != nil {
rOpts.Eventf(api.EventTypeWarning, "ERROR", "%s Web ACL (%s) association failed: %s", *l.lb.current.LoadBalancerName, *l.options.desired.webACLId, err.Error())
l.logger.Errorf("Failure adding Web ACL (%s) association: %s", *l.options.desired.webACLId, err.Error())
} else {
l.options.current.wafACLID = l.options.desired.wafACLID
rOpts.Eventf(api.EventTypeNormal, "MODIFY", "WAF Association updated to %s", *l.options.desired.wafACLID)
l.logger.Infof("WAF Association updated %s", *l.options.desired.wafACLID)
l.options.current.webACLId = l.options.desired.webACLId
rOpts.Eventf(api.EventTypeNormal, "MODIFY", "Web ACL association updated to %s", *l.options.desired.webACLId)
l.logger.Infof("Web ACL association updated to %s", *l.options.desired.webACLId)
}
} else if l.options.current.wafACLID != nil {
} else if l.options.current.webACLId != nil {
if _, err := albwaf.WAFRegionalsvc.Disassociate(l.lb.current.LoadBalancerArn); err != nil {
rOpts.Eventf(api.EventTypeWarning, "ERROR", "%s Waf disassociation failed: %s", *l.lb.current.LoadBalancerName, err.Error())
l.logger.Errorf("Failed ELBV2 (ALB) Waf disassociation failed: %s", err.Error())
rOpts.Eventf(api.EventTypeWarning, "ERROR", "%s Web ACL disassociation failed: %s", *l.lb.current.LoadBalancerName, err.Error())
l.logger.Errorf("Failure removing Web ACL association: %s", err.Error())
} else {
l.options.current.wafACLID = l.options.desired.wafACLID
rOpts.Eventf(api.EventTypeNormal, "MODIFY", "WAF Disassociated")
l.logger.Infof("WAF Disassociated")
l.options.current.webACLId = l.options.desired.webACLId
rOpts.Eventf(api.EventTypeNormal, "MODIFY", "Web ACL disassociated")
l.logger.Infof("Web ACL disassociated")
}
}
}
Expand All @@ -687,7 +687,7 @@ func (l *LoadBalancer) modify(rOpts *ReconcileOptions) error {
func (l *LoadBalancer) delete(rOpts *ReconcileOptions) error {

// we need to disassociate the WAF before deletion
if l.options.current.wafACLID != nil {
if l.options.current.webACLId != nil {
if _, err := albwaf.WAFRegionalsvc.Disassociate(l.lb.current.LoadBalancerArn); err != nil {
rOpts.Eventf(api.EventTypeWarning, "ERROR", "Error disassociating WAF for %s: %s", *l.lb.current.LoadBalancerName, err.Error())
l.logger.Errorf("Failed disassociation of ELBV2 (ALB) WAF: %s.", err.Error())
Expand Down Expand Up @@ -827,11 +827,11 @@ func (l *LoadBalancer) needsModification() (loadBalancerChange, bool) {
changes |= attributesModified
}

if dopts.wafACLID != nil && copts.wafACLID == nil ||
dopts.wafACLID == nil && copts.wafACLID != nil ||
(copts.wafACLID != nil && dopts.wafACLID != nil && *copts.wafACLID != *dopts.wafACLID) {
l.logger.Debugf("WAF needs to be changed: (%v != %v)", log.Prettify(copts.wafACLID), log.Prettify(dopts.wafACLID))
changes |= wafAssociationModified
if dopts.webACLId != nil && copts.webACLId == nil ||
dopts.webACLId == nil && copts.webACLId != nil ||
(copts.webACLId != nil && dopts.webACLId != nil && *copts.webACLId != *dopts.webACLId) {
l.logger.Debugf("WAF needs to be changed: (%v != %v)", log.Prettify(copts.webACLId), log.Prettify(dopts.webACLId))
changes |= webACLAssociationModified
}
return changes, true
}
Expand All @@ -841,7 +841,7 @@ func (l *LoadBalancer) StripDesiredState() {
l.lb.desired = nil
l.options.desired.ports = nil
l.options.desired.managedSG = nil
l.options.desired.wafACLID = nil
l.options.desired.webACLId = nil
if l.listeners != nil {
l.listeners.StripDesiredState()
}
Expand Down
24 changes: 12 additions & 12 deletions pkg/alb/lb/loadbalancer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const (
tag1Value = "value1"
tag2Key = "tag2"
tag2Value = "value2"
wafACL = "current-id-of-waf-acl"
expectedWAFACL = "new-id-of-waf-acl"
webACL = "current-id-of-web-acl"
expectedWebACL = "new-id-of-web-acl"
)

var (
Expand All @@ -34,8 +34,8 @@ var (
expectedName string
existing *elbv2.LoadBalancer
lbOpts *NewCurrentLoadBalancerOptions
expectedWaf *string
currentWaf *string
expectedWeb *string
currentWeb *string
)

func init() {
Expand Down Expand Up @@ -69,8 +69,8 @@ func init() {
},
}

currentWaf = aws.String(wafACL)
expectedWaf = aws.String(expectedWAFACL)
currentWeb = aws.String(webACL)
expectedWeb = aws.String(expectedWebACL)
lbOpts = &NewCurrentLoadBalancerOptions{
LoadBalancer: existing,
Logger: logr,
Expand All @@ -83,7 +83,7 @@ func TestNewDesiredLoadBalancer(t *testing.T) {
anno := &annotations.Annotations{
Scheme: lbScheme,
SecurityGroups: types.AWSStringSlice{aws.String(sg1), aws.String(sg2)},
WafACLID: expectedWaf,
WebACLId: expectedWeb,
}

lbOpts := &NewDesiredLoadBalancerOptions{
Expand All @@ -109,8 +109,8 @@ func TestNewDesiredLoadBalancer(t *testing.T) {
t.Errorf("Security group was wrong. Expected: %s | Actual: %s", sg2, *l.lb.desired.SecurityGroups[0])
case key1 != tag1Value:
t.Errorf("Tag was invalid. Expected: %s | Actual: %s", tag1Value, key1)
case *l.options.desired.wafACLID != *expectedWaf:
t.Errorf("WAF ACL ID was invalid. Expected: %s | Actual: %s", *expectedWaf, *l.options.desired.wafACLID)
case *l.options.desired.webACLId != *expectedWeb:
t.Errorf("Web ACL ID was invalid. Expected: %s | Actual: %s", *expectedWeb, *l.options.desired.webACLId)

}
}
Expand All @@ -128,9 +128,9 @@ func TestNewDesiredLoadBalancer(t *testing.T) {
// case *l.lb.current.LoadBalancerName != expectedName:
// t.Errorf("Current LB created returned improper LoadBalancerName. Expected: %s | "+
// "Desired: %s", expectedName, *l.lb.current.LoadBalancerName)
// case *l.options.current.wafACLID != *currentWaf:
// t.Errorf("Current LB created returned improper WAF ACL Id. Expected: %s | "+
// "Desired: %s", *currentWaf, *l.options.current.wafACLID)
// case *l.options.current.webACLId != *currentWeb:
// t.Errorf("Current LB created returned improper Web ACL Id. Expected: %s | "+
// "Desired: %s", *currentWeb, *l.options.current.webACLId)
// }
// }

Expand Down
4 changes: 2 additions & 2 deletions pkg/alb/lb/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type opts struct {
idleTimeout *int64
ports portList
inboundCidrs util.Cidrs
wafACLID *string
webACLId *string
managedSG *string
managedInstanceSG *string
}
Expand All @@ -63,7 +63,7 @@ const (
managedSecurityGroupsModified
connectionIdleTimeoutModified
ipAddressTypeModified
wafAssociationModified
webACLAssociationModified
)

type ReconcileOptions struct {
Expand Down
26 changes: 16 additions & 10 deletions pkg/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ const (
backendProtocolKey = "alb.ingress.kubernetes.io/backend-protocol"
certificateArnKey = "alb.ingress.kubernetes.io/certificate-arn"
connectionIdleTimeoutKey = "alb.ingress.kubernetes.io/connection-idle-timeout"
wafACLIDKey = "alb.ingress.kubernetes.io/waf-acl-id"
webACLIdKey = "alb.ingress.kubernetes.io/web-acl-id"
webACLIdAltKey = "alb.ingress.kubernetes.io/waf-acl-id"
healthcheckIntervalSecondsKey = "alb.ingress.kubernetes.io/healthcheck-interval-seconds"
healthcheckPathKey = "alb.ingress.kubernetes.io/healthcheck-path"
healthcheckPortKey = "alb.ingress.kubernetes.io/healthcheck-port"
Expand Down Expand Up @@ -61,7 +62,7 @@ type Annotations struct {
BackendProtocol *string
CertificateArn *string
ConnectionIdleTimeout *int64
WafACLID *string
WebACLId *string
HealthcheckIntervalSeconds *int64
HealthcheckPath *string
HealthcheckPort *string
Expand Down Expand Up @@ -156,7 +157,7 @@ func (vf *ValidatingAnnotationFactory) ParseAnnotations(opts *ParseAnnotationsOp
a.setSuccessCodes(annotations),
a.setTags(annotations),
a.setIgnoreHostHeader(annotations),
a.setWafACLID(annotations, vf.validator),
a.setWebACLId(annotations, vf.validator),
a.setLoadBalancerAttributes(annotations),
a.setTargetGroupAttributes(annotations),
a.setSslPolicy(annotations, vf.validator),
Expand Down Expand Up @@ -714,15 +715,20 @@ func (a *Annotations) setIgnoreHostHeader(annotations map[string]string) error {
return nil
}

func (a *Annotations) setWafACLID(annotations map[string]string, validator Validator) error {
if wafACLID, ok := annotations[wafACLIDKey]; ok {
a.WafACLID = aws.String(wafACLID)
if c := cacheLookup(wafACLID); c == nil || c.Expired() {
if err := validator.ValidateWafACLID(a); err != nil {
cache.Set(wafACLID, "error", 1*time.Hour)
func (a *Annotations) setWebACLId(annotations map[string]string, validator Validator) error {
webACLId, ok := annotations[webACLIdKey]
if !ok {
webACLId = annotations[webACLIdAltKey]
}

if webACLId != "" {
a.WebACLId = aws.String(webACLId)
if c := cacheLookup(webACLId); c == nil || c.Expired() {
if err := validator.ValidateWebACLId(a); err != nil {
cache.Set(webACLId, "error", 1*time.Hour)
return err
}
cache.Set(wafACLID, "success", 30*time.Minute)
cache.Set(webACLId, "success", 30*time.Minute)
}
}
return nil
Expand Down
8 changes: 4 additions & 4 deletions pkg/annotations/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type Validator interface {
ValidateCertARN(a *Annotations) error
ValidateInboundCidrs(a *Annotations) error
ValidateScheme(a *Annotations, ingressNamespace, ingressName string) bool
ValidateWafACLID(a *Annotations) error
ValidateWebACLId(a *Annotations) error
ValidateSslPolicy(a *Annotations) error
}

Expand Down Expand Up @@ -106,9 +106,9 @@ func (v ConcreteValidator) ValidateScheme(a *Annotations, ingressNamespace, ingr
return true
}

func (v ConcreteValidator) ValidateWafACLID(a *Annotations) error {
if success, err := albwaf.WAFRegionalsvc.WafAclExists(a.WafACLID); !success {
return fmt.Errorf("waf ACL Id does not exist. Id: %s, error: %s", *a.WafACLID, err.Error())
func (v ConcreteValidator) ValidateWebACLId(a *Annotations) error {
if success, err := albwaf.WAFRegionalsvc.WebACLExists(a.WebACLId); !success {
return fmt.Errorf("Web ACL Id does not exist. Id: %s, error: %s", *a.WebACLId, err.Error())
}
return nil
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/annotations/validation_fake.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type FakeValidator struct {
ValidateCertARNDelegate func() error
ValidateInboundCidrsDelegate func() error
ValidateSchemeDelegate func() bool
ValidateWafACLIDDelegate func() error
ValidateWebACLIdDelegate func() error
ValidateSslPolicyDelegate func() error
}

Expand Down Expand Up @@ -47,9 +47,9 @@ func (fv FakeValidator) ValidateScheme(a *Annotations, ingressNamespace, ingress
return true
}

func (fv FakeValidator) ValidateWafACLID(a *Annotations) error {
if fv.ValidateWafACLIDDelegate != nil {
return fv.ValidateWafACLIDDelegate()
func (fv FakeValidator) ValidateWebACLId(a *Annotations) error {
if fv.ValidateWebACLIdDelegate != nil {
return fv.ValidateWebACLIdDelegate()
}
return nil
}
Expand Down
Loading