-
Notifications
You must be signed in to change notification settings - Fork 578
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
✨ Remove ingress and egress rules from vpc default security group #4707
✨ Remove ingress and egress rules from vpc default security group #4707
Conversation
Skipping CI for Draft Pull Request. |
/test all |
c48b5d6
to
6f6e516
Compare
/test all |
6f6e516
to
3435308
Compare
/test all |
3435308
to
2544b32
Compare
/test all |
2544b32
to
a91b151
Compare
/test all |
@@ -90,7 +90,7 @@ func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error { | |||
restoreIPAMPool(restored.Spec.NetworkSpec.VPC.IPv6.IPAMPool, dst.Spec.NetworkSpec.VPC.IPv6.IPAMPool) | |||
} | |||
|
|||
dst.Spec.NetworkSpec.AdditionalControlPlaneIngressRules = restored.Spec.NetworkSpec.AdditionalControlPlaneIngressRules |
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.
This was already done on line 75
api/v1beta2/network_types.go
Outdated
// SecureDefaultVPCSecurityGroup specifies whether the default VPC security group ingress | ||
// and egress rules should be removed. | ||
// +optional | ||
SecureDefaultVPCSecurityGroup bool `json:"secureDefaultVPCSecurityGroup,omitempty"` |
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 remove this field on the next major release containing breaking changes. And change CAPA behavior as if this field was always true. Should we add a @todo somewhere?
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.
At least, we should add here in the description that the default will become true in the future, while currently it's false. Regarding a TODO, an issue could be opened for the next milestone.
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 might be nice if this is true
for new clusters by default, but it stays false
for older clusters. The defaulting can happen if in the validation webhook if the vpc id of a managed VPC is already filled.
Part of me was also considering of not adding this flag at all, which can be confusing?
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 not adding the field/flag, because it makes things simpler and easier to understand. I don't think users should rely on this security group anyway. But someone in Slack suggested adding it to be backwards compatible, which also makes sense.
ec24551
to
5f19835
Compare
}, | ||
} | ||
err = s.revokeSecurityGroupIngressRules(defaultSecurityGroupID, ingressRules) | ||
if awserrors.IsIgnorableSecurityGroupError(errors.Cause(err)) != 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.
The ingress and egress rules are removed successfully, but on the next reconciliations, I keep getting
I1221 17:25:07.051779 1 recorder.go:104] "events: Failed to revoke security group ingress rules [protocol=-1/range=[-1--1]/description=] for SecurityGroup \"sg-09b4f9143ee0aeda4\": InvalidPermission.NotFound: The specified rule does not exist in this security group.\n\tstatus code: 400, request id: df8bbb6a-5674-4f0c-a255-8a2da44eb3e0" type="Warning" object={"kind":"AWSCluster","namespace":"org-giantswarm","name":"jose4","uid":"87039375-5a6c-4e7e-bbce-b784c05085e2","apiVersion":"infrastructure.cluster.x-k8s.io/v1beta2","resourceVersion":"811993128"} reason="FailedRevokeSecurityGroupIngressRules"
What would be the best way to unwrap the error so that it's ignored? I figured that we don't want to do anything if the ingress or egress rules were already removed.
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 can use the same logic as func (s *Service) ReconcileSecurityGroups
: first read existing rules with s.getSecurityGroupIngressRules
and then reconcile the differences.
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 don't think it makes sense in this case, because all we want is to delete the existing rules. We don't care what's inside, or "the differences". We want the group to have no rules at all.
api/v1beta2/network_types.go
Outdated
// SecureDefaultVPCSecurityGroup specifies whether the default VPC security group ingress | ||
// and egress rules should be removed. | ||
// +optional | ||
SecureDefaultVPCSecurityGroup bool `json:"secureDefaultVPCSecurityGroup,omitempty"` |
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.
At least, we should add here in the description that the default will become true in the future, while currently it's false. Regarding a TODO, an issue could be opened for the next milestone.
// The VPC default security group is created by AWS and cannot be deleted. | ||
// But we can revoke all ingress and egress rules from it to make it more secure. This security group is not used by CAPA. | ||
func (s *Service) revokeIngressAndEgressRulesFromVPCDefaultSecurityGroup() error { | ||
if s.scope.VPC().SecureDefaultVPCSecurityGroup { |
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.
Please return early instead of indenting the whole function code. Or alternatively, you could move the condition to the caller.
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.
Done
filter.EC2.SecurityGroupName("default"), | ||
}, | ||
}) | ||
if err != 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.
len(securityGroups) != 1
is also an 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.
The default
security group can't be removed. When creating a new security group, group names must be unique, so there can't be two groups named default
. I don't think len(securityGroups)
can ever be != 1
.
}, | ||
} | ||
err = s.revokeSecurityGroupIngressRules(defaultSecurityGroupID, ingressRules) | ||
if awserrors.IsIgnorableSecurityGroupError(errors.Cause(err)) != 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.
We can use the same logic as func (s *Service) ReconcileSecurityGroups
: first read existing rules with s.getSecurityGroupIngressRules
and then reconcile the differences.
@@ -90,6 +92,29 @@ func TestReconcileSecurityGroups(t *testing.T) { | |||
}, | |||
}, | |||
expect: func(m *mocks.MockEC2APIMockRecorder) { |
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 also have a test for reconciliation if the rules are already gone – in that case, no requests apart from DescribeSecurityGroups
and listing its rules should be done.
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.
Added a test case to cover that.
5f19835
to
26208de
Compare
api/v1beta2/network_types.go
Outdated
|
||
// SecureDefaultVPCSecurityGroup specifies whether the default VPC security group ingress | ||
// and egress rules should be removed. | ||
// +optional | ||
SecureDefaultVPCSecurityGroup bool `json:"secureDefaultVPCSecurityGroup,omitempty"` |
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.
// SecureDefaultVPCSecurityGroup specifies whether the default VPC security group ingress | |
// and egress rules should be removed. | |
// +optional | |
SecureDefaultVPCSecurityGroup bool `json:"secureDefaultVPCSecurityGroup,omitempty"` | |
// EmptyRoutesDefaultVPCSecurityGroup specifies whether the default VPC security group ingress | |
// and egress rules should be removed. | |
// | |
// By default, when creating a VPC, AWS creates a security group called `default` with ingress and egress | |
// rules that allow traffic from anywhere. The group could be used as a potential surface attack and | |
// it's generally suggested that the group rules are removed or modified appropriately. | |
// | |
// NOTE: This only applies when the VPC is managed by the Cluster API AWS controller. | |
// | |
// +optional | |
EmptyRoutesDefaultVPCSecurityGroup bool `json:"emptyRoutesDefaultVPCSecurityGroup,omitempty"` |
9c6af09
to
30a9257
Compare
} | ||
err = s.revokeSecurityGroupIngressRules(defaultSecurityGroupID, ingressRules) | ||
if awserrors.IsIgnorableSecurityGroupError(errors.Cause(err)) != nil { | ||
return errors.Wrapf(err, "failed to revoke ingress rules from vpc default security group in vpc %q", s.scope.VPC().ID) |
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.
return errors.Wrapf(err, "failed to revoke ingress rules from vpc default security group in vpc %q", s.scope.VPC().ID) | |
return errors.Wrapf(err, "failed to revoke ingress rules from vpc default security group %q in VPC %q", defaultSecurityGroupID, s.scope.VPC().ID) |
}, | ||
} | ||
err = s.revokeSecurityGroupIngressRules(defaultSecurityGroupID, ingressRules) | ||
if awserrors.IsIgnorableSecurityGroupError(errors.Cause(err)) != 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.
Are GroupNotFound
/PermissionNotFound
(which IsIgnorableSecurityGroupError
handles) really errors that we want to ignore? The default group cannot be deleted, so such errors here should fail, I think. From the test, it seems that you found that AWS throws a permission error if the given rules do not exist. So we could instead use ec2:DescribeSecurityGroupRules
(new permission which CAPA does not have yet) or handle the very specific 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.
After deleting the ingress/egress rules from the default security group, the next time we try to delete them we'll get a PermissionNotFound
error. I think this one can be ignored, because that's the state we want. To avoid swallowing the GroupNotFound
error, that should not happen in this scenario, we could handle PermissionNotFound
more specifically, like you mentioned. I'll add a new IsPermissionNotFoundError
function. How does that sound?
30a9257
to
50dc78d
Compare
50dc78d
to
c066167
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
@vincepri did you mean to |
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.
/approve
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: vincepri 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 |
/milestone v2.4.0 |
What type of PR is this?
/kind feature
What this PR does / why we need it:
We want to secure the VPC as much as possible.
Which issue(s) this PR fixes (optional, in
fixes #<issue number>(, fixes #<issue_number>, ...)
format, will close the issue(s) when PR gets merged):Fixes #4675
Special notes for your reviewer:
Checklist:
Release note: