-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Add support for optionally enforcing NLB security groups on PrivateLi… #3594
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
Conversation
|
Welcome @wweiwei-li! |
Hi @wweiwei-li. Thanks for your PR. I'm waiting for a kubernetes-sigs member to verify that this patch is reasonable to test. If it is, they should reply with Once the patch is verified, the new status will be reflected by the I understand the commands that are listed here. Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
case string(elbv2model.SecurityGroupsInboundRulesOnPrivateLinkOff): | ||
return elbv2model.SecurityGroupsInboundRulesOnPrivateLinkOff, nil | ||
default: | ||
return "", errors.Errorf("unknown securityGroupsInboundRulesOnPrivateLink status: %v", securityGroupsInboundRulesOnPrivateLink) |
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.
We should modify this error message to give them suggestion to use the allowed values as well. Something like errors.Errorf("Invalid value for securityGroupsInboundRulesOnPrivateLink status: %v, value must be one of [%v, %v]", securityGroupsInboundRulesOnPrivateLink), string(elbv2model.SecurityGroupsInboundRulesOnPrivateLinkOn), string(elbv2model.SecurityGroupsInboundRulesOnPrivateLinkOff)
/check-cla |
/ok-to-test |
fedae1a
to
2189784
Compare
2189784
to
2382541
Compare
SecurityGroupsInboundRulesOnPrivateLinkOn SecurityGroupsInboundRulesOnPrivateLinkStatus = "on" | ||
SecurityGroupsInboundRulesOnPrivateLinkOff SecurityGroupsInboundRulesOnPrivateLinkStatus = "off" | ||
) | ||
|
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.
should we move these to pkg/model/ec2/security_group.go
instead?
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.
Yes, it is okay to move these to pkg/model/ec2/security_group.go. One concern is this field is actually a load balancer field, even though it is related to security groups
@@ -75,6 +76,12 @@ func (m *defaultLoadBalancerManager) Create(ctx context.Context, resLB *elbv2mod | |||
return elbv2model.LoadBalancerStatus{}, err | |||
} | |||
|
|||
if resLB.Spec.Type == elbv2model.LoadBalancerTypeNetwork && string(*resLB.Spec.SecurityGroupsInboundRulesOnPrivateLink) != "" { |
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.
why need to convert it to string? can we just check if it's nil or not? Same for all the string() != ""
below
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.
As you suggested if user does not specify the annotation, we will skip adding it as a spec. In this case, we will no longer have resLB.Spec.SecurityGroupsInboundRulesOnPrivateLink = "", so we can just check if it is nil.
|
||
if resLB.Spec.Type == elbv2model.LoadBalancerTypeNetwork { | ||
desiredEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic := string(*resLB.Spec.SecurityGroupsInboundRulesOnPrivateLink) | ||
currentEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic := "on" |
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.
why need a default value for currentEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic
? let's say, if the resLB.Spec.SecurityGroupsInboundRulesOnPrivateLink
is on
, and there's no such setting on sdkLB, so the currentEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic
defaults to on
, we ignore this situation?
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.
Good catch. I was thinking it was "on" by default, but it is not. I will the set currentEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic based on sdkLB as below.
var currentEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic string
if sdkLB.LoadBalancer.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic != nil {
currentEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic = awssdk.StringValue(sdkLB.LoadBalancer.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic)
}
@@ -173,6 +179,22 @@ func (t *defaultModelBuildTask) buildLoadBalancerIPAddressType(_ context.Context | |||
} | |||
} | |||
|
|||
func (t *defaultModelBuildTask) buildSecurityGroupsInboundRulesOnPrivateLink(_ context.Context) (elbv2model.SecurityGroupsInboundRulesOnPrivateLinkStatus, error) { | |||
securityGroupsInboundRulesOnPrivateLink := "" |
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.
maybe just a var securityGroupsInboundRulesOnPrivateLink string
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.
Sure, we can just use var securityGroupsInboundRulesOnPrivateLink string
func (t *defaultModelBuildTask) buildSecurityGroupsInboundRulesOnPrivateLink(_ context.Context) (elbv2model.SecurityGroupsInboundRulesOnPrivateLinkStatus, error) { | ||
securityGroupsInboundRulesOnPrivateLink := "" | ||
if exists := t.annotationParser.ParseStringAnnotation(annotations.SvcLBSuffixEnforceSGInboundRulesOnPrivateLinkTraffic, &securityGroupsInboundRulesOnPrivateLink, t.service.Annotations); !exists { | ||
return "", nil |
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.
if user does not specify the annotation, can we just skip adding it as a spec in the LB? it's a bit strange to have "securityGroupsInboundRulesOnPrivateLink":""
.
And I think we should have the default value to "off", for backward compatibility.
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.
Good point, I agree if user does not specify the annotation, we should just skip adding it as a spec in the LB.
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.
Just note : Default value for this is "On".
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.
we need unit tests added for the cases: 1)annotation setting to "on",
2)annotation setting to "off"
3)no annotation at all.
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.
I added some code in pkg/service/model_builder_test.go. When the annotation is set to "on", the build model will have "securityGroupsInboundRulesOnPrivateLink":"on". If the annotation is set to "off", the build model will have "securityGroupsInboundRulesOnPrivateLink":"off". If there is no annotation, "securityGroupsInboundRulesOnPrivateLink" will not be included. Is this sufficient?
return elbv2model.SecurityGroupsInboundRulesOnPrivateLinkOff, nil | ||
default: | ||
return "", errors.Errorf("Invalid value for securityGroupsInboundRulesOnPrivateLink status: %v, value must be one of [%v, %v]", securityGroupsInboundRulesOnPrivateLink, string(elbv2model.SecurityGroupsInboundRulesOnPrivateLinkOn), string(elbv2model.SecurityGroupsInboundRulesOnPrivateLinkOff)) | ||
} |
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.
it will be confusing that it says only accept "on" and "off", but it actually allows an empty string "".
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.
It won't allow empty string "". An empty string will also fall into the condition of an invalid value.
@wweiwei-li, thanks for the contribution. I left some comments.
For backward compatibility, I think we shouldn't have "on" as default. |
2382541
to
591a64a
Compare
/lgtm |
/lgtm |
SvcLBSuffixLoadBalancerAttributes = "aws-load-balancer-attributes" | ||
SvcLBSuffixLoadBalancerSecurityGroups = "aws-load-balancer-security-groups" | ||
SvcLBSuffixManageSGRules = "aws-load-balancer-manage-backend-security-group-rules" | ||
SvcLBSuffixEnforceSGInboundRulesOnPrivateLinkTraffic = "aws-load-balancer-inbound-sg-rules-on-private-link-traffic" |
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.
should this be something like
aws-load-balancer-enforce-sg-inbound-rules-on-pl-traffic
or
aws-load-balancer-enforce-sg-inbound-rules-on-private-link-traffic
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.
Good point, I like aws-load-balancer-enforce-sg-inbound-rules-on-private-link-traffic
but annotation must be 63 characters or less, so we decided to use aws-load-balancer-inbound-sg-rules-on-private-link-traffic
@@ -75,6 +76,12 @@ func (m *defaultLoadBalancerManager) Create(ctx context.Context, resLB *elbv2mod | |||
return elbv2model.LoadBalancerStatus{}, err | |||
} | |||
|
|||
if resLB.Spec.Type == elbv2model.LoadBalancerTypeNetwork && resLB.Spec.SecurityGroupsInboundRulesOnPrivateLink != nil { |
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.
is this EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic
can only be set with this SetSecurityGroups call after LB creation?
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.
Yes, we can only set it after LB creation
@@ -186,20 +193,52 @@ func (m *defaultLoadBalancerManager) updateSDKLoadBalancerWithSecurityGroups(ctx | |||
} | |||
desiredSecurityGroups := sets.NewString(awssdk.StringValueSlice(securityGroups)...) | |||
currentSecurityGroups := sets.NewString(awssdk.StringValueSlice(sdkLB.LoadBalancer.SecurityGroups)...) | |||
if desiredSecurityGroups.Equal(currentSecurityGroups) { | |||
|
|||
if desiredSecurityGroups.Equal(currentSecurityGroups) && (resLB.Spec.Type != elbv2model.LoadBalancerTypeNetwork || resLB.Spec.SecurityGroupsInboundRulesOnPrivateLink == nil) { |
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.
let's add a method that checks whether SGInboundRulesOnPrivateLink shall be enforced
something like
isEnforceSGInboundRulesOnPrivateLinkUpdated(sdkLB, resLB) {
...checks sdkLB.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic & resLB.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic
}
then if desiredSecurityGroups.Equal(currentSecurityGroups) && !isEnforceSGInboundRulesOnPrivateLinkUpdated(...) { return nil}
and later, simple set req. EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic based on resLB.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic
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.
Wrap up all checks into isEnforceSGInboundRulesOnPrivateLinkUpdated(sdkLB, resLB)
method is a great idea. I made change based on your suggestion. To be able to use current and desired value in logs, I also return currentEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic, desiredEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic value. Please let me know if it looks good to you.
591a64a
to
a7c57a3
Compare
@@ -87,6 +92,22 @@ func (t *defaultModelBuildTask) buildLoadBalancerSpec(ctx context.Context, schem | |||
LoadBalancerAttributes: lbAttributes, | |||
Tags: tags, | |||
} | |||
|
|||
if securityGroupsInboundRulesOnPrivateLink != "" { |
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.
i'd prefer to use below:
if securityGroupsInboundRulesOnPrivateLink != "" {
spec.SecurityGroupsInboundRulesOnPrivateLink = &securityGroupsInboundRulesOnPrivateLink
}
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.
Yes, good point, will update
@@ -177,6 +198,22 @@ func (t *defaultModelBuildTask) buildLoadBalancerIPAddressType(_ context.Context | |||
} | |||
} | |||
|
|||
func (t *defaultModelBuildTask) buildSecurityGroupsInboundRulesOnPrivateLink(_ context.Context) (elbv2model.SecurityGroupsInboundRulesOnPrivateLinkStatus, error) { |
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.
can we change the return value to be *elbv2model.SecurityGroupsInboundRulesOnPrivateLinkStatus, error
thus we can return nil
instead of ""
to represent "not set".
The reason why this is better is technically ""
is not a valid value for SecurityGroupsInboundRulesOnPrivateLinkStatus
enum.
return nil | ||
} | ||
|
||
if !desiredSecurityGroups.Equal(currentSecurityGroups) { |
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.
- Nit, since there is only one change call technically, i'd prefer to use a single log call
var changeDescriptions []string
if !desiredSecurityGroups.Equal(currentSecurityGroups) {
changeDescriptions = append(changeDescriptions, "changeSecurityGroups", changeSecurityGroupsDesc)
}
req := &elbv2sdk.SetSecurityGroupsInput{
LoadBalancerArn: sdkLB.LoadBalancer.LoadBalancerArn,
SecurityGroups: securityGroups,
}
if ! isEnforceSGInboundRulesOnPrivateLinkUpdated {
changeDescriptions = append(changeDescriptions, "changeEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic", changeEnforceSecurityGroupInboundRulesOnPrivateLinkTrafficDesc)
req.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic: awssdk.String(desiredEnforceSecurityGroupInboundRulesOnPrivateLinkTraffic),
}
m.logger.Info("modifying loadBalancer security group settings",
"stackID", resLB.Stack().StackID(),
"resourceID", resLB.ID(),
"arn", awssdk.StringValue(sdkLB.LoadBalancer.LoadBalancerArn),
...changeDescriptions)
2. per the current log, req.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic
is only set when there is a change. So if the security group changed but isEnforceSGInboundRulesOnPrivateLinkUpdated
is false, then req.EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic will be nil, what's the API behavior under such case, will it untouch the existing EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic settings on LB or reset it to default value(something we don't want).
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.
- Yes, we can switch to use a single log call.
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.
- Good question, it will untouch the existing EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic settings
a7c57a3
to
bfff95f
Compare
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.
/lgtm
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: M00nF1sh, shraddhabang, wweiwei-li The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Hi, can we know when this ticket is released? |
Any predictions on when this will be published in the release? |
I'm also waiting |
When will you implement this feature? |
Hey, This feature will be released in V2.8.0 targeting the end of this week. |
…nk traffic
Issue
#3386
Description
This is a feature to support optionally enforce NLB security groups on PrivateLink traffic. For the change, added a new annotation
aws-load-balancer-inbound-sg-rules-on-private-link-traffic
to configure whether to apply security group rules to traffic sent to the load balancer through AWS PrivateLink. The value of it can be set to "off" and "on". After creating new NLB, will check if the annotation is specified. If yes, will call updateSDKLoadBalancerWithSecurityGroups, where added the logic to check if we need to call setSecurityGroup to update EnforceSecurityGroupInboundRulesOnPrivateLinkTraffic.Checklist
README.md
, or thedocs
directory)BONUS POINTS checklist: complete for good vibes and maybe prizes?! 🤯