-
Notifications
You must be signed in to change notification settings - Fork 93
Support configuration of security list management modes as LB service annotation #225
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
Changes from 5 commits
3056f4a
63e384e
3aeb662
7a753ae
2973f06
4d5e784
a1e8632
97727e2
08542f0
ddacd25
8ea9b48
feadb79
47efdfd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,14 +58,18 @@ const ( | |
ServiceAnnotationLoadBalancerSSLPorts = "service.beta.kubernetes.io/oci-load-balancer-ssl-ports" | ||
|
||
// ServiceAnnotationLoadBalancerTLSSecret is a Service annotation for | ||
// specifying the TLS secret ti install on the load balancer listeners which | ||
// specifying the TLS secret to install on the load balancer listeners which | ||
// have SSL enabled. | ||
// See: https://kubernetes.io/docs/concepts/services-networking/ingress/#tls | ||
ServiceAnnotationLoadBalancerTLSSecret = "service.beta.kubernetes.io/oci-load-balancer-tls-secret" | ||
|
||
// ServiceAnnotationLoadBalancerConnectionIdleTimeout is the annotation used | ||
// on the service to specify the idle connection timeout. | ||
ServiceAnnotationLoadBalancerConnectionIdleTimeout = "service.beta.kubernetes.io/oci-load-balancer-connection-idle-timeout" | ||
|
||
//ServiceAnnotaionLoadBalancerSecurityListManagementMode is a Service annotation for | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
//specifying the security list managment mode ("All","Frontend","None") that configures how security lists are managed by the CCM | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
ServiceAnnotaionLoadBalancerSecurityListManagementMode = "service.beta.kubernetes.io/oci-load-balancer-security-list-management-mode" | ||
) | ||
|
||
// DefaultLoadBalancerPolicy defines the default traffic policy for load | ||
|
@@ -242,7 +246,7 @@ func (cp *CloudProvider) createLoadBalancer(ctx context.Context, spec *LBSpec) ( | |
} | ||
|
||
for _, ports := range spec.Ports { | ||
if err = cp.securityListManager.Update(ctx, lbSubnets, nodeSubnets, spec.SourceCIDRs, nil, ports); err != nil { | ||
if err = spec.SecurityListManager.Update(ctx, lbSubnets, nodeSubnets, spec.SourceCIDRs, nil, ports); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
@@ -305,7 +309,7 @@ func (cp *CloudProvider) EnsureLoadBalancer(ctx context.Context, clusterName str | |
ssl = NewSSLConfig(lbName, ports, cp) | ||
} | ||
subnets := []string{cp.config.LoadBalancer.Subnet1, cp.config.LoadBalancer.Subnet2} | ||
spec, err := NewLBSpec(service, nodes, subnets, ssl) | ||
spec, err := NewLBSpec(service, nodes, subnets, ssl, cp.securityListManagerFactory) | ||
if err != nil { | ||
glog.Errorf("Failed to derive LBSpec: %+v", err) | ||
return nil, err | ||
|
@@ -364,7 +368,7 @@ func (cp *CloudProvider) updateLoadBalancer(ctx context.Context, lb *loadbalance | |
for _, action := range actions { | ||
switch a := action.(type) { | ||
case *BackendSetAction: | ||
err := cp.updateBackendSet(ctx, lbID, a, lbSubnets, nodeSubnets) | ||
err := cp.updateBackendSet(ctx, lbID, a, lbSubnets, nodeSubnets, spec.SecurityListManager) | ||
if err != nil { | ||
return errors.Wrap(err, "updating BackendSet") | ||
} | ||
|
@@ -381,7 +385,7 @@ func (cp *CloudProvider) updateLoadBalancer(ctx context.Context, lb *loadbalance | |
ports = spec.Ports[backendSetName] | ||
} | ||
|
||
err := cp.updateListener(ctx, lbID, a, ports, lbSubnets, nodeSubnets, spec.SourceCIDRs) | ||
err := cp.updateListener(ctx, lbID, a, ports, lbSubnets, nodeSubnets, spec.SourceCIDRs, spec.SecurityListManager) | ||
if err != nil { | ||
return errors.Wrap(err, "updating listener") | ||
} | ||
|
@@ -390,7 +394,7 @@ func (cp *CloudProvider) updateLoadBalancer(ctx context.Context, lb *loadbalance | |
return nil | ||
} | ||
|
||
func (cp *CloudProvider) updateBackendSet(ctx context.Context, lbID string, action *BackendSetAction, lbSubnets, nodeSubnets []*core.Subnet) error { | ||
func (cp *CloudProvider) updateBackendSet(ctx context.Context, lbID string, action *BackendSetAction, lbSubnets, nodeSubnets []*core.Subnet, secListManager securityListManager) error { | ||
var ( | ||
sourceCIDRs = []string{} | ||
workRequestID string | ||
|
@@ -403,19 +407,19 @@ func (cp *CloudProvider) updateBackendSet(ctx context.Context, lbID string, acti | |
|
||
switch action.Type() { | ||
case Create: | ||
err = cp.securityListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, nil, ports) | ||
err = secListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, nil, ports) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
workRequestID, err = cp.client.LoadBalancer().CreateBackendSet(ctx, lbID, action.Name(), bs) | ||
case Update: | ||
if err = cp.securityListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, action.OldPorts, ports); err != nil { | ||
if err = secListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, action.OldPorts, ports); err != nil { | ||
return err | ||
} | ||
workRequestID, err = cp.client.LoadBalancer().UpdateBackendSet(ctx, lbID, action.Name(), bs) | ||
case Delete: | ||
err = cp.securityListManager.Delete(ctx, lbSubnets, nodeSubnets, ports) | ||
err = secListManager.Delete(ctx, lbSubnets, nodeSubnets, ports) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -435,7 +439,7 @@ func (cp *CloudProvider) updateBackendSet(ctx context.Context, lbID string, acti | |
return nil | ||
} | ||
|
||
func (cp *CloudProvider) updateListener(ctx context.Context, lbID string, action *ListenerAction, ports portSpec, lbSubnets, nodeSubnets []*core.Subnet, sourceCIDRs []string) error { | ||
func (cp *CloudProvider) updateListener(ctx context.Context, lbID string, action *ListenerAction, ports portSpec, lbSubnets, nodeSubnets []*core.Subnet, sourceCIDRs []string, secListManager securityListManager) error { | ||
var workRequestID string | ||
var err error | ||
listener := action.Listener | ||
|
@@ -445,21 +449,21 @@ func (cp *CloudProvider) updateListener(ctx context.Context, lbID string, action | |
|
||
switch action.Type() { | ||
case Create: | ||
err = cp.securityListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, nil, ports) | ||
err = secListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, nil, ports) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
workRequestID, err = cp.client.LoadBalancer().CreateListener(ctx, lbID, action.Name(), listener) | ||
case Update: | ||
err = cp.securityListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, nil, ports) | ||
err = secListManager.Update(ctx, lbSubnets, nodeSubnets, sourceCIDRs, nil, ports) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
workRequestID, err = cp.client.LoadBalancer().UpdateListener(ctx, lbID, action.Name(), listener) | ||
case Delete: | ||
err = cp.securityListManager.Delete(ctx, lbSubnets, nodeSubnets, ports) | ||
err = secListManager.Delete(ctx, lbSubnets, nodeSubnets, ports) | ||
if err != nil { | ||
return err | ||
} | ||
|
@@ -547,6 +551,9 @@ func (cp *CloudProvider) EnsureLoadBalancerDeleted(ctx context.Context, clusterN | |
return errors.Wrap(err, "getting subnets for load balancers") | ||
} | ||
|
||
securityListManager := cp.securityListManagerFactory( | ||
service.Annotations[ServiceAnnotaionLoadBalancerSecurityListManagementMode]) | ||
|
||
for listenerName, listener := range lb.Listeners { | ||
backendSetName := *listener.DefaultBackendSetName | ||
bs, ok := lb.BackendSets[backendSetName] | ||
|
@@ -559,7 +566,7 @@ func (cp *CloudProvider) EnsureLoadBalancerDeleted(ctx context.Context, clusterN | |
|
||
glog.V(4).Infof("Deleting security rules for listener %q for load balancer %q ports=%+v", listenerName, id, ports) | ||
|
||
if err := cp.securityListManager.Delete(ctx, lbSubnets, nodeSubnets, ports); err != nil { | ||
if err := securityListManager.Delete(ctx, lbSubnets, nodeSubnets, ports); err != nil { | ||
return errors.Wrapf(err, "delete security rules for listener %q on load balancer %q", listenerName, name) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -74,16 +74,17 @@ type LBSpec struct { | |
Listeners map[string]loadbalancer.ListenerDetails | ||
BackendSets map[string]loadbalancer.BackendSetDetails | ||
|
||
Ports map[string]portSpec | ||
SourceCIDRs []string | ||
SSLConfig *SSLConfig | ||
Ports map[string]portSpec | ||
SourceCIDRs []string | ||
SSLConfig *SSLConfig | ||
SecurityListManager securityListManager | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't export this field so |
||
|
||
service *v1.Service | ||
nodes []*v1.Node | ||
} | ||
|
||
// NewLBSpec creates a LB Spec from a Kubernetes service and a slice of nodes. | ||
func NewLBSpec(svc *v1.Service, nodes []*v1.Node, defaultSubnets []string, sslCfg *SSLConfig) (*LBSpec, error) { | ||
func NewLBSpec(svc *v1.Service, nodes []*v1.Node, defaultSubnets []string, sslCfg *SSLConfig, secListFactory securityListManagerFactory) (*LBSpec, error) { | ||
if len(defaultSubnets) != 2 { | ||
return nil, errors.New("default subnets incorrectly configured") | ||
} | ||
|
@@ -134,6 +135,10 @@ func NewLBSpec(svc *v1.Service, nodes []*v1.Node, defaultSubnets []string, sslCf | |
return nil, err | ||
} | ||
|
||
//A security list manager will be configured based on the annotation specified when creating the service, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
//if an annotation is not specified, then the mode specified in cloud provider config file is used. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
slManagerSpec := secListFactory(svc.Annotations[ServiceAnnotaionLoadBalancerSecurityListManagementMode]) | ||
|
||
return &LBSpec{ | ||
Name: GetLoadBalancerName(svc), | ||
Shape: shape, | ||
|
@@ -146,8 +151,9 @@ func NewLBSpec(svc *v1.Service, nodes []*v1.Node, defaultSubnets []string, sslCf | |
SSLConfig: sslCfg, | ||
SourceCIDRs: sourceCIDRs, | ||
|
||
service: svc, | ||
nodes: nodes, | ||
service: svc, | ||
nodes: nodes, | ||
SecurityListManager: slManagerSpec, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SecurityListManager: secListFactory(
svc.Annotations[ServiceAnnotaionLoadBalancerSecurityListManagementMode],
) |
||
}, nil | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,6 +83,7 @@ func TestNewLBSpecSuccess(t *testing.T) { | |
HealthCheckerPort: 10256, | ||
}, | ||
}, | ||
SecurityListManager: newSecurityListManagerNOOP(), | ||
}, | ||
}, | ||
"internal": { | ||
|
@@ -137,6 +138,7 @@ func TestNewLBSpecSuccess(t *testing.T) { | |
HealthCheckerPort: 10256, | ||
}, | ||
}, | ||
SecurityListManager: newSecurityListManagerNOOP(), | ||
}, | ||
}, | ||
"subnet annotations": { | ||
|
@@ -192,8 +194,10 @@ func TestNewLBSpecSuccess(t *testing.T) { | |
HealthCheckerPort: 10256, | ||
}, | ||
}, | ||
SecurityListManager: newSecurityListManagerNOOP(), | ||
}, | ||
}, | ||
//"security list manager annotation": | ||
"custom shape": { | ||
defaultSubnetOne: "one", | ||
defaultSubnetTwo: "two", | ||
|
@@ -246,6 +250,7 @@ func TestNewLBSpecSuccess(t *testing.T) { | |
HealthCheckerPort: 10256, | ||
}, | ||
}, | ||
SecurityListManager: newSecurityListManagerNOOP(), | ||
}, | ||
}, | ||
"custom idle connection timeout": { | ||
|
@@ -303,6 +308,7 @@ func TestNewLBSpecSuccess(t *testing.T) { | |
HealthCheckerPort: 10256, | ||
}, | ||
}, | ||
SecurityListManager: newSecurityListManagerNOOP(), | ||
}, | ||
}, | ||
} | ||
|
@@ -312,7 +318,11 @@ func TestNewLBSpecSuccess(t *testing.T) { | |
// we expect the service to be unchanged | ||
tc.expected.service = tc.service | ||
subnets := []string{tc.defaultSubnetOne, tc.defaultSubnetTwo} | ||
result, err := NewLBSpec(tc.service, tc.nodes, subnets, nil) | ||
//reference default cp added | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
slManagerFactory := func(mode string) securityListManager { | ||
return newSecurityListManagerNOOP() | ||
} | ||
result, err := NewLBSpec(tc.service, tc.nodes, subnets, nil, slManagerFactory) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
@@ -330,7 +340,8 @@ func TestNewLBSpecFailure(t *testing.T) { | |
defaultSubnetTwo string | ||
nodes []*v1.Node | ||
service *v1.Service | ||
expectedErrMsg string | ||
//add cp or cp security list | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
expectedErrMsg string | ||
}{ | ||
"unsupported udp protocol": { | ||
service: &v1.Service{ | ||
|
@@ -415,6 +426,7 @@ func TestNewLBSpecFailure(t *testing.T) { | |
Spec: v1.ServiceSpec{ | ||
SessionAffinity: v1.ServiceAffinityNone, | ||
Ports: []v1.ServicePort{}, | ||
//add security list mananger in spec | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Space after |
||
}, | ||
}, | ||
expectedErrMsg: "a configuration for subnet1 must be specified for an internal load balancer", | ||
|
@@ -424,7 +436,10 @@ func TestNewLBSpecFailure(t *testing.T) { | |
for name, tc := range testCases { | ||
t.Run(name, func(t *testing.T) { | ||
subnets := []string{tc.defaultSubnetOne, tc.defaultSubnetTwo} | ||
_, err := NewLBSpec(tc.service, tc.nodes, subnets, nil) | ||
slManagerFactory := func(mode string) securityListManager { | ||
return newSecurityListManagerNOOP() | ||
} | ||
_, err := NewLBSpec(tc.service, tc.nodes, subnets, nil, slManagerFactory) | ||
if err == nil || err.Error() != tc.expectedErrMsg { | ||
t.Errorf("Expected error with message %q but got %q", tc.expectedErrMsg, err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might want to stick a
\n
under here to separate out the setup vs the cache sync