-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Carlos Salas <carlos.salas@suse.com>
- Loading branch information
1 parent
d361c08
commit e23c05b
Showing
2 changed files
with
137 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package action | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/service/ec2" | ||
) | ||
|
||
func (a *action) cleanSecurityGroups(ctx context.Context, input *CleanupScope) error { | ||
client := ec2.New(input.Session) | ||
|
||
sgsToDelete := []*ec2.SecurityGroup{} | ||
// NOTE: we delete security groups based on whether we're later deleting the vpc they belong to or not. | ||
pageFunc := func(page *ec2.DescribeVpcsOutput, _ bool) bool { | ||
sgPageFunc := func(sgPage *ec2.GetSecurityGroupsForVpcOutput, _ bool) bool { | ||
for _, sg := range sgPage.SecurityGroupForVpcs { | ||
var ignore bool | ||
for _, tag := range sg.Tags { | ||
if *tag.Key == input.IgnoreTag { | ||
ignore = true | ||
break | ||
} | ||
} | ||
|
||
if ignore || *sg.GroupName == "default" { | ||
LogDebug("security group %s has ignore tag or is a default security group, skipping cleanup", *sg.GroupId) | ||
continue | ||
} | ||
|
||
securityGroups, err := client.DescribeSecurityGroupsWithContext(ctx, &ec2.DescribeSecurityGroupsInput{GroupIds: []*string{sg.GroupId}}) | ||
if err != nil || len(securityGroups.SecurityGroups) != 1 { | ||
LogError("failed to describe security group %s: %s", *sg.GroupId, err.Error()) | ||
continue | ||
} | ||
|
||
LogDebug("adding security group %s to delete list", *sg.GroupId) | ||
sgsToDelete = append(sgsToDelete, securityGroups.SecurityGroups[0]) | ||
} | ||
|
||
return true | ||
} | ||
|
||
for _, vpc := range page.Vpcs { | ||
var ignore bool | ||
for _, tag := range vpc.Tags { | ||
if *tag.Key == input.IgnoreTag { | ||
ignore = true | ||
break | ||
} | ||
} | ||
|
||
if ignore || aws.BoolValue(vpc.IsDefault) { | ||
LogDebug("vpc %s has ignore tag or is a default vpc, won't delete security groups associated with it", *vpc.VpcId) | ||
continue | ||
} | ||
|
||
if err := client.GetSecurityGroupsForVpcPagesWithContext(ctx, &ec2.GetSecurityGroupsForVpcInput{VpcId: vpc.VpcId}, sgPageFunc); err != nil { | ||
LogError("failed getting list of security groups for vpc %s: %s", *vpc.VpcId, err.Error()) | ||
continue | ||
} | ||
|
||
} | ||
|
||
return true | ||
} | ||
|
||
if err := client.DescribeVpcsPagesWithContext(ctx, &ec2.DescribeVpcsInput{}, pageFunc); err != nil { | ||
return fmt.Errorf("failed getting list of vpcs: %w", err) | ||
} | ||
|
||
if len(sgsToDelete) == 0 { | ||
Log("no security groups to delete") | ||
return nil | ||
} | ||
|
||
// NOTE: some security groups may have rules that reference other security groups. | ||
// deleting a security group that's referenced in another's rules will fail, | ||
// so we need to delete the rules first. | ||
for _, securityGroup := range sgsToDelete { | ||
if !a.commit { | ||
LogDebug("skipping deletion of security group %s as running in dry-mode", *securityGroup.GroupId) | ||
continue | ||
} | ||
|
||
if err := a.deleteSecurityGroupRules(ctx, *securityGroup.GroupId, securityGroup.IpPermissions, securityGroup.IpPermissionsEgress, client); err != nil { | ||
LogError("failed to delete security group rules for %s: %s", *securityGroup.GroupId, err.Error()) | ||
} | ||
|
||
} | ||
|
||
for _, securityGroup := range sgsToDelete { | ||
if !a.commit { | ||
LogDebug("skipping deletion of security group %s as running in dry-mode", *securityGroup.GroupId) | ||
continue | ||
} | ||
|
||
if err := a.deleteSecurityGroup(ctx, *securityGroup.GroupId, client); err != nil { | ||
LogError("failed to delete security group %s: %s", *securityGroup.GroupId, err.Error()) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (a *action) deleteSecurityGroupRules(ctx context.Context, sgId string, sgIngress, sgEgress []*ec2.IpPermission, client *ec2.EC2) error { | ||
Log("Deleting Ingress/Egress Rules from security group %s", sgId) | ||
|
||
if len(sgIngress) != 0 { | ||
if _, err := client.RevokeSecurityGroupIngressWithContext(ctx, &ec2.RevokeSecurityGroupIngressInput{GroupId: &sgId, IpPermissions: sgIngress}); err != nil { | ||
return fmt.Errorf("failed to revoke ingress rules from security group %s: %w", sgId, err) | ||
} | ||
} | ||
|
||
if len(sgEgress) != 0 { | ||
if _, err := client.RevokeSecurityGroupEgressWithContext(ctx, &ec2.RevokeSecurityGroupEgressInput{GroupId: &sgId, IpPermissions: sgEgress}); err != nil { | ||
return fmt.Errorf("failed to revoke egress rules from security group %s: %w", sgId, err) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (a *action) deleteSecurityGroup(ctx context.Context, sgId string, client *ec2.EC2) error { | ||
Log("Deleting Security Group %s", sgId) | ||
|
||
if _, err := client.DeleteSecurityGroupWithContext(ctx, &ec2.DeleteSecurityGroupInput{GroupId: &sgId}); err != nil { | ||
return fmt.Errorf("failed to delete security group %s: %w", sgId, err) | ||
} | ||
|
||
return nil | ||
} |