mirror of https://github.com/kubernetes/kops.git
Use sg rule ids and tags where possible
This commit is contained in:
parent
fe28b8587c
commit
d98994686a
|
|
@ -42,6 +42,7 @@ type MockEC2 struct {
|
||||||
|
|
||||||
securityGroupNumber int
|
securityGroupNumber int
|
||||||
SecurityGroups map[string]*ec2.SecurityGroup
|
SecurityGroups map[string]*ec2.SecurityGroup
|
||||||
|
SecurityGroupRules map[string]*ec2.SecurityGroupRule
|
||||||
|
|
||||||
subnets map[string]*subnetInfo
|
subnets map[string]*subnetInfo
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,7 @@ func (m *MockEC2) RevokeSecurityGroupIngress(request *ec2.RevokeSecurityGroupIng
|
||||||
return nil, fmt.Errorf("SecurityGroup not found")
|
return nil, fmt.Errorf("SecurityGroup not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.Warningf("RevokeSecurityGroupIngress not implemented - does not actually revoke permissions")
|
klog.Warningf("RevokeSecurityGroupIngress mock not implemented - does not actually revoke permissions")
|
||||||
|
|
||||||
response := &ec2.RevokeSecurityGroupIngressOutput{}
|
response := &ec2.RevokeSecurityGroupIngressOutput{}
|
||||||
return response, nil
|
return response, nil
|
||||||
|
|
@ -269,6 +269,61 @@ func (m *MockEC2) AuthorizeSecurityGroupEgress(request *ec2.AuthorizeSecurityGro
|
||||||
|
|
||||||
// TODO: We need to fold permissions
|
// TODO: We need to fold permissions
|
||||||
|
|
||||||
|
if m.SecurityGroupRules == nil {
|
||||||
|
m.SecurityGroupRules = make(map[string]*ec2.SecurityGroupRule)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, permission := range request.IpPermissions {
|
||||||
|
|
||||||
|
for _, iprange := range permission.IpRanges {
|
||||||
|
|
||||||
|
n := len(m.SecurityGroupRules) + 1
|
||||||
|
id := fmt.Sprintf("sgr-%d", n)
|
||||||
|
rule := &ec2.SecurityGroupRule{
|
||||||
|
SecurityGroupRuleId: &id,
|
||||||
|
GroupId: sg.GroupId,
|
||||||
|
FromPort: permission.FromPort,
|
||||||
|
ToPort: permission.ToPort,
|
||||||
|
IsEgress: aws.Bool(true),
|
||||||
|
CidrIpv4: iprange.CidrIp,
|
||||||
|
IpProtocol: permission.IpProtocol,
|
||||||
|
Tags: tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeSecurityGroupRule),
|
||||||
|
}
|
||||||
|
if permission.FromPort == nil {
|
||||||
|
rule.FromPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
if permission.ToPort == nil {
|
||||||
|
rule.ToPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.SecurityGroupRules[id] = rule
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, iprange := range permission.Ipv6Ranges {
|
||||||
|
|
||||||
|
n := len(m.SecurityGroupRules) + 1
|
||||||
|
id := fmt.Sprintf("sgr-%d", n)
|
||||||
|
rule := &ec2.SecurityGroupRule{
|
||||||
|
SecurityGroupRuleId: &id,
|
||||||
|
GroupId: sg.GroupId,
|
||||||
|
FromPort: permission.FromPort,
|
||||||
|
ToPort: permission.ToPort,
|
||||||
|
IsEgress: aws.Bool(true),
|
||||||
|
CidrIpv6: iprange.CidrIpv6,
|
||||||
|
IpProtocol: permission.IpProtocol,
|
||||||
|
Tags: tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeSecurityGroupRule),
|
||||||
|
}
|
||||||
|
if permission.FromPort == nil {
|
||||||
|
rule.FromPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
if permission.ToPort == nil {
|
||||||
|
rule.ToPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.SecurityGroupRules[id] = rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
response := &ec2.AuthorizeSecurityGroupEgressOutput{}
|
response := &ec2.AuthorizeSecurityGroupEgressOutput{}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
@ -325,6 +380,111 @@ func (m *MockEC2) AuthorizeSecurityGroupIngress(request *ec2.AuthorizeSecurityGr
|
||||||
|
|
||||||
// TODO: We need to fold permissions
|
// TODO: We need to fold permissions
|
||||||
|
|
||||||
|
if m.SecurityGroupRules == nil {
|
||||||
|
m.SecurityGroupRules = make(map[string]*ec2.SecurityGroupRule)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, permission := range request.IpPermissions {
|
||||||
|
|
||||||
|
for _, iprange := range permission.IpRanges {
|
||||||
|
|
||||||
|
n := len(m.SecurityGroupRules) + 1
|
||||||
|
id := fmt.Sprintf("sgr-%d", n)
|
||||||
|
rule := &ec2.SecurityGroupRule{
|
||||||
|
SecurityGroupRuleId: &id,
|
||||||
|
GroupId: sg.GroupId,
|
||||||
|
FromPort: permission.FromPort,
|
||||||
|
ToPort: permission.ToPort,
|
||||||
|
IsEgress: aws.Bool(false),
|
||||||
|
CidrIpv4: iprange.CidrIp,
|
||||||
|
IpProtocol: permission.IpProtocol,
|
||||||
|
Tags: tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeSecurityGroupRule),
|
||||||
|
}
|
||||||
|
if permission.FromPort == nil {
|
||||||
|
rule.FromPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
if permission.ToPort == nil {
|
||||||
|
rule.ToPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.SecurityGroupRules[id] = rule
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, iprange := range permission.Ipv6Ranges {
|
||||||
|
|
||||||
|
n := len(m.SecurityGroupRules) + 1
|
||||||
|
id := fmt.Sprintf("sgr-%d", n)
|
||||||
|
rule := &ec2.SecurityGroupRule{
|
||||||
|
SecurityGroupRuleId: &id,
|
||||||
|
GroupId: sg.GroupId,
|
||||||
|
FromPort: permission.FromPort,
|
||||||
|
ToPort: permission.ToPort,
|
||||||
|
IsEgress: aws.Bool(false),
|
||||||
|
CidrIpv6: iprange.CidrIpv6,
|
||||||
|
IpProtocol: permission.IpProtocol,
|
||||||
|
Tags: tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeSecurityGroupRule),
|
||||||
|
}
|
||||||
|
if permission.FromPort == nil {
|
||||||
|
rule.FromPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
if permission.ToPort == nil {
|
||||||
|
rule.ToPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.SecurityGroupRules[id] = rule
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, group := range permission.UserIdGroupPairs {
|
||||||
|
|
||||||
|
n := len(m.SecurityGroupRules) + 1
|
||||||
|
id := fmt.Sprintf("sgr-%d", n)
|
||||||
|
rule := &ec2.SecurityGroupRule{
|
||||||
|
SecurityGroupRuleId: &id,
|
||||||
|
GroupId: sg.GroupId,
|
||||||
|
FromPort: permission.FromPort,
|
||||||
|
ToPort: permission.ToPort,
|
||||||
|
IsEgress: aws.Bool(false),
|
||||||
|
ReferencedGroupInfo: &ec2.ReferencedSecurityGroup{
|
||||||
|
GroupId: group.GroupId,
|
||||||
|
},
|
||||||
|
IpProtocol: permission.IpProtocol,
|
||||||
|
Tags: tagSpecificationsToTags(request.TagSpecifications, ec2.ResourceTypeSecurityGroupRule),
|
||||||
|
}
|
||||||
|
if permission.FromPort == nil {
|
||||||
|
rule.FromPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
if permission.ToPort == nil {
|
||||||
|
rule.ToPort = aws.Int64(int64(-1))
|
||||||
|
}
|
||||||
|
|
||||||
|
m.SecurityGroupRules[id] = rule
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
response := &ec2.AuthorizeSecurityGroupIngressOutput{}
|
response := &ec2.AuthorizeSecurityGroupIngressOutput{}
|
||||||
return response, nil
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MockEC2) DescribeSecurityGroupRules(request *ec2.DescribeSecurityGroupRulesInput) (*ec2.DescribeSecurityGroupRulesOutput, error) {
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
|
rules := []*ec2.SecurityGroupRule{}
|
||||||
|
|
||||||
|
sgid := ""
|
||||||
|
for _, filter := range request.Filters {
|
||||||
|
if aws.StringValue(filter.Name) == "group-id" {
|
||||||
|
sgid = aws.StringValue(filter.Values[0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rule := range m.SecurityGroupRules {
|
||||||
|
if aws.StringValue(rule.GroupId) == sgid {
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ec2.DescribeSecurityGroupRulesOutput{
|
||||||
|
SecurityGroupRules: rules,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -429,6 +429,12 @@ func AddDirectionalGroupRule(c *fi.ModelBuilderContext, t *awstasks.SecurityGrou
|
||||||
|
|
||||||
name := generateName(t)
|
name := generateName(t)
|
||||||
t.Name = fi.String(name)
|
t.Name = fi.String(name)
|
||||||
|
tags := make(map[string]string)
|
||||||
|
for key, value := range t.SecurityGroup.Tags {
|
||||||
|
tags[key] = value
|
||||||
|
}
|
||||||
|
tags["Name"] = *t.Name
|
||||||
|
t.Tags = tags
|
||||||
|
|
||||||
klog.V(8).Infof("Adding rule %v", name)
|
klog.V(8).Infof("Adding rule %v", name)
|
||||||
c.AddTask(t)
|
c.AddTask(t)
|
||||||
|
|
|
||||||
|
|
@ -261,26 +261,24 @@ func (e *SecurityGroup) CloudformationLink() *cloudformation.Literal {
|
||||||
}
|
}
|
||||||
|
|
||||||
type deleteSecurityGroupRule struct {
|
type deleteSecurityGroupRule struct {
|
||||||
groupID *string
|
rule *ec2.SecurityGroupRule
|
||||||
permission *ec2.IpPermission
|
|
||||||
egress bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ fi.Deletion = &deleteSecurityGroupRule{}
|
var _ fi.Deletion = &deleteSecurityGroupRule{}
|
||||||
|
|
||||||
func (d *deleteSecurityGroupRule) Delete(t fi.Target) error {
|
func (d *deleteSecurityGroupRule) Delete(t fi.Target) error {
|
||||||
klog.V(2).Infof("deleting security group permission: %v", fi.DebugAsJsonString(d.permission))
|
klog.V(2).Infof("deleting security group permission: %v", fi.DebugAsJsonString(d.rule))
|
||||||
|
|
||||||
awsTarget, ok := t.(*awsup.AWSAPITarget)
|
awsTarget, ok := t.(*awsup.AWSAPITarget)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("unexpected target type for deletion: %T", t)
|
return fmt.Errorf("unexpected target type for deletion: %T", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.egress {
|
if fi.BoolValue(d.rule.IsEgress) {
|
||||||
request := &ec2.RevokeSecurityGroupEgressInput{
|
request := &ec2.RevokeSecurityGroupEgressInput{
|
||||||
GroupId: d.groupID,
|
GroupId: d.rule.GroupId,
|
||||||
|
SecurityGroupRuleIds: []*string{d.rule.SecurityGroupRuleId},
|
||||||
}
|
}
|
||||||
request.IpPermissions = []*ec2.IpPermission{d.permission}
|
|
||||||
|
|
||||||
klog.V(2).Infof("Calling EC2 RevokeSecurityGroupEgress")
|
klog.V(2).Infof("Calling EC2 RevokeSecurityGroupEgress")
|
||||||
_, err := awsTarget.Cloud.EC2().RevokeSecurityGroupEgress(request)
|
_, err := awsTarget.Cloud.EC2().RevokeSecurityGroupEgress(request)
|
||||||
|
|
@ -289,9 +287,9 @@ func (d *deleteSecurityGroupRule) Delete(t fi.Target) error {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
request := &ec2.RevokeSecurityGroupIngressInput{
|
request := &ec2.RevokeSecurityGroupIngressInput{
|
||||||
GroupId: d.groupID,
|
GroupId: d.rule.GroupId,
|
||||||
|
SecurityGroupRuleIds: []*string{d.rule.SecurityGroupRuleId},
|
||||||
}
|
}
|
||||||
request.IpPermissions = []*ec2.IpPermission{d.permission}
|
|
||||||
|
|
||||||
klog.V(2).Infof("Calling EC2 RevokeSecurityGroupIngress")
|
klog.V(2).Infof("Calling EC2 RevokeSecurityGroupIngress")
|
||||||
_, err := awsTarget.Cloud.EC2().RevokeSecurityGroupIngress(request)
|
_, err := awsTarget.Cloud.EC2().RevokeSecurityGroupIngress(request)
|
||||||
|
|
@ -308,8 +306,8 @@ func (d *deleteSecurityGroupRule) TaskName() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deleteSecurityGroupRule) Item() string {
|
func (d *deleteSecurityGroupRule) Item() string {
|
||||||
s := fi.StringValue(d.groupID) + ":"
|
s := fi.StringValue(d.rule.GroupId) + ":"
|
||||||
p := d.permission
|
p := d.rule
|
||||||
if aws.Int64Value(p.FromPort) != 0 {
|
if aws.Int64Value(p.FromPort) != 0 {
|
||||||
s += fmt.Sprintf(" port=%d", aws.Int64Value(p.FromPort))
|
s += fmt.Sprintf(" port=%d", aws.Int64Value(p.FromPort))
|
||||||
if aws.Int64Value(p.ToPort) != aws.Int64Value(p.FromPort) {
|
if aws.Int64Value(p.ToPort) != aws.Int64Value(p.FromPort) {
|
||||||
|
|
@ -319,59 +317,17 @@ func (d *deleteSecurityGroupRule) Item() string {
|
||||||
if aws.StringValue(p.IpProtocol) != "-1" {
|
if aws.StringValue(p.IpProtocol) != "-1" {
|
||||||
s += fmt.Sprintf(" protocol=%s", aws.StringValue(p.IpProtocol))
|
s += fmt.Sprintf(" protocol=%s", aws.StringValue(p.IpProtocol))
|
||||||
}
|
}
|
||||||
for _, ug := range p.UserIdGroupPairs {
|
if p.ReferencedGroupInfo != nil {
|
||||||
s += fmt.Sprintf(" group=%s", aws.StringValue(ug.GroupId))
|
s += fmt.Sprintf(" group=%s", aws.StringValue(p.ReferencedGroupInfo.GroupId))
|
||||||
}
|
|
||||||
for _, r := range p.IpRanges {
|
|
||||||
s += fmt.Sprintf(" ip=%s", aws.StringValue(r.CidrIp))
|
|
||||||
}
|
|
||||||
for _, r := range p.Ipv6Ranges {
|
|
||||||
s += fmt.Sprintf(" ipv6=%s", aws.StringValue(r.CidrIpv6))
|
|
||||||
}
|
}
|
||||||
|
s += fmt.Sprintf(" ip=%s", aws.StringValue(p.CidrIpv4))
|
||||||
|
s += fmt.Sprintf(" ipv6=%s", aws.StringValue(p.CidrIpv6))
|
||||||
//permissionString := fi.DebugAsJsonString(d.permission)
|
//permissionString := fi.DebugAsJsonString(d.permission)
|
||||||
//s += permissionString
|
//s += permissionString
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandPermissions(sgID *string, permission *ec2.IpPermission, egress bool) []*ec2.IpPermission {
|
|
||||||
var rules []*ec2.IpPermission
|
|
||||||
|
|
||||||
master := &ec2.IpPermission{
|
|
||||||
FromPort: permission.FromPort,
|
|
||||||
ToPort: permission.ToPort,
|
|
||||||
IpProtocol: permission.IpProtocol,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ipRange := range permission.IpRanges {
|
|
||||||
a := &ec2.IpPermission{}
|
|
||||||
*a = *master
|
|
||||||
a.IpRanges = []*ec2.IpRange{ipRange}
|
|
||||||
rules = append(rules, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ipv6Range := range permission.Ipv6Ranges {
|
|
||||||
a := &ec2.IpPermission{}
|
|
||||||
*a = *master
|
|
||||||
a.Ipv6Ranges = []*ec2.Ipv6Range{ipv6Range}
|
|
||||||
rules = append(rules, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ug := range permission.UserIdGroupPairs {
|
|
||||||
a := &ec2.IpPermission{}
|
|
||||||
*a = *master
|
|
||||||
a.UserIdGroupPairs = []*ec2.UserIdGroupPair{ug}
|
|
||||||
rules = append(rules, a)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rules) == 0 {
|
|
||||||
// If there are no group or cidr restrictions, it is just a generic rule
|
|
||||||
rules = append(rules, master)
|
|
||||||
}
|
|
||||||
|
|
||||||
return rules
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *SecurityGroup) FindDeletions(c *fi.Context) ([]fi.Deletion, error) {
|
func (e *SecurityGroup) FindDeletions(c *fi.Context) ([]fi.Deletion, error) {
|
||||||
var removals []fi.Deletion
|
var removals []fi.Deletion
|
||||||
|
|
||||||
|
|
@ -396,13 +352,20 @@ func (e *SecurityGroup) FindDeletions(c *fi.Context) ([]fi.Deletion, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ingress []*ec2.IpPermission
|
cloud := c.Cloud.(awsup.AWSCloud)
|
||||||
for _, permission := range sg.IpPermissions {
|
|
||||||
rules := expandPermissions(sg.GroupId, permission, false)
|
request := &ec2.DescribeSecurityGroupRulesInput{
|
||||||
ingress = append(ingress, rules...)
|
Filters: []*ec2.Filter{
|
||||||
|
awsup.NewEC2Filter("group-id", *e.ID),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, permission := range ingress {
|
response, err := cloud.EC2().DescribeSecurityGroupRules(request)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, permission := range response.SecurityGroupRules {
|
||||||
// Because of #478, we can't remove all non-matching security groups
|
// Because of #478, we can't remove all non-matching security groups
|
||||||
// Instead we consider only certain rules to be 'in-scope'
|
// Instead we consider only certain rules to be 'in-scope'
|
||||||
// (in the model, we typically consider only rules on port 22 and 443)
|
// (in the model, we typically consider only rules on port 22 and 443)
|
||||||
|
|
@ -436,34 +399,7 @@ func (e *SecurityGroup) FindDeletions(c *fi.Context) ([]fi.Deletion, error) {
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
removals = append(removals, &deleteSecurityGroupRule{
|
removals = append(removals, &deleteSecurityGroupRule{
|
||||||
groupID: sg.GroupId,
|
rule: permission,
|
||||||
permission: permission,
|
|
||||||
egress: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var egress []*ec2.IpPermission
|
|
||||||
for _, permission := range sg.IpPermissionsEgress {
|
|
||||||
rules := expandPermissions(sg.GroupId, permission, true)
|
|
||||||
egress = append(egress, rules...)
|
|
||||||
}
|
|
||||||
for _, permission := range egress {
|
|
||||||
found := false
|
|
||||||
for _, t := range c.AllTasks() {
|
|
||||||
er, ok := t.(*SecurityGroupRule)
|
|
||||||
if !ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if er.matches(permission) {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
removals = append(removals, &deleteSecurityGroupRule{
|
|
||||||
groupID: sg.GroupId,
|
|
||||||
permission: permission,
|
|
||||||
egress: true,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -473,7 +409,7 @@ func (e *SecurityGroup) FindDeletions(c *fi.Context) ([]fi.Deletion, error) {
|
||||||
|
|
||||||
// RemovalRule is a rule that filters the permissions we should remove
|
// RemovalRule is a rule that filters the permissions we should remove
|
||||||
type RemovalRule interface {
|
type RemovalRule interface {
|
||||||
Matches(permission *ec2.IpPermission) bool
|
Matches(permission *ec2.SecurityGroupRule) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseRemovalRule parses our removal rule DSL into a RemovalRule
|
// ParseRemovalRule parses our removal rule DSL into a RemovalRule
|
||||||
|
|
@ -511,7 +447,7 @@ func (r *PortRemovalRule) String() string {
|
||||||
return fi.DebugAsJsonString(r)
|
return fi.DebugAsJsonString(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *PortRemovalRule) Matches(permission *ec2.IpPermission) bool {
|
func (r *PortRemovalRule) Matches(permission *ec2.SecurityGroupRule) bool {
|
||||||
// Check if port matches
|
// Check if port matches
|
||||||
if permission.FromPort == nil || *permission.FromPort != int64(r.Port) {
|
if permission.FromPort == nil || *permission.FromPort != int64(r.Port) {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -60,34 +60,34 @@ func testParsesAsPort(t *testing.T, rule string, port int) {
|
||||||
|
|
||||||
func TestPortRemovalRule(t *testing.T) {
|
func TestPortRemovalRule(t *testing.T) {
|
||||||
r := &PortRemovalRule{Port: 22}
|
r := &PortRemovalRule{Port: 22}
|
||||||
testMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(22), ToPort: aws.Int64(22)})
|
testMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(22), ToPort: aws.Int64(22)})
|
||||||
|
|
||||||
testNotMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(0), ToPort: aws.Int64(0)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(0), ToPort: aws.Int64(0)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(23), ToPort: aws.Int64(23)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(23), ToPort: aws.Int64(23)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(20), ToPort: aws.Int64(22)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(20), ToPort: aws.Int64(22)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(22), ToPort: aws.Int64(23)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(22), ToPort: aws.Int64(23)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{ToPort: aws.Int64(22)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{ToPort: aws.Int64(22)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(22)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(22)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPortRemovalRule_Zero(t *testing.T) {
|
func TestPortRemovalRule_Zero(t *testing.T) {
|
||||||
r := &PortRemovalRule{Port: 0}
|
r := &PortRemovalRule{Port: 0}
|
||||||
testMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(0), ToPort: aws.Int64(0)})
|
testMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(0), ToPort: aws.Int64(0)})
|
||||||
|
|
||||||
testNotMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(0), ToPort: aws.Int64(20)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(0), ToPort: aws.Int64(20)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{ToPort: aws.Int64(0)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{ToPort: aws.Int64(0)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{FromPort: aws.Int64(0)})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{FromPort: aws.Int64(0)})
|
||||||
testNotMatches(t, r, &ec2.IpPermission{})
|
testNotMatches(t, r, &ec2.SecurityGroupRule{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMatches(t *testing.T, rule *PortRemovalRule, permission *ec2.IpPermission) {
|
func testMatches(t *testing.T, rule *PortRemovalRule, permission *ec2.SecurityGroupRule) {
|
||||||
if !rule.Matches(permission) {
|
if !rule.Matches(permission) {
|
||||||
t.Fatalf("rule %q failed to match permission %q", rule, permission)
|
t.Fatalf("rule %q failed to match permission %q", rule, permission)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testNotMatches(t *testing.T, rule *PortRemovalRule, permission *ec2.IpPermission) {
|
func testNotMatches(t *testing.T, rule *PortRemovalRule, permission *ec2.SecurityGroupRule) {
|
||||||
if rule.Matches(permission) {
|
if rule.Matches(permission) {
|
||||||
t.Fatalf("rule %q unexpectedly matched permission %q", rule, permission)
|
t.Fatalf("rule %q unexpectedly matched permission %q", rule, permission)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ import (
|
||||||
|
|
||||||
// +kops:fitask
|
// +kops:fitask
|
||||||
type SecurityGroupRule struct {
|
type SecurityGroupRule struct {
|
||||||
|
ID *string
|
||||||
Name *string
|
Name *string
|
||||||
Lifecycle fi.Lifecycle
|
Lifecycle fi.Lifecycle
|
||||||
|
|
||||||
|
|
@ -49,6 +50,8 @@ type SecurityGroupRule struct {
|
||||||
SourceGroup *SecurityGroup
|
SourceGroup *SecurityGroup
|
||||||
|
|
||||||
Egress *bool
|
Egress *bool
|
||||||
|
|
||||||
|
Tags map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *SecurityGroupRule) Find(c *fi.Context) (*SecurityGroupRule, error) {
|
func (e *SecurityGroupRule) Find(c *fi.Context) (*SecurityGroupRule, error) {
|
||||||
|
|
@ -63,35 +66,24 @@ func (e *SecurityGroupRule) Find(c *fi.Context) (*SecurityGroupRule, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
request := &ec2.DescribeSecurityGroupsInput{
|
request := &ec2.DescribeSecurityGroupRulesInput{
|
||||||
Filters: []*ec2.Filter{
|
Filters: []*ec2.Filter{
|
||||||
awsup.NewEC2Filter("group-id", *e.SecurityGroup.ID),
|
awsup.NewEC2Filter("group-id", *e.SecurityGroup.ID),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := cloud.EC2().DescribeSecurityGroups(request)
|
response, err := cloud.EC2().DescribeSecurityGroupRules(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error listing SecurityGroup: %v", err)
|
return nil, fmt.Errorf("error listing SecurityGroup: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if response == nil || len(response.SecurityGroups) == 0 {
|
if response == nil || len(response.SecurityGroupRules) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(response.SecurityGroups) != 1 {
|
var foundRule *ec2.SecurityGroupRule
|
||||||
klog.Fatalf("found multiple security groups for id=%s", *e.SecurityGroup.ID)
|
|
||||||
}
|
|
||||||
sg := response.SecurityGroups[0]
|
|
||||||
//klog.V(2).Info("found existing security group")
|
|
||||||
|
|
||||||
var foundRule *ec2.IpPermission
|
for _, rule := range response.SecurityGroupRules {
|
||||||
|
|
||||||
ipPermissions := sg.IpPermissions
|
|
||||||
if fi.BoolValue(e.Egress) {
|
|
||||||
ipPermissions = sg.IpPermissionsEgress
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rule := range ipPermissions {
|
|
||||||
if e.matches(rule) {
|
if e.matches(rule) {
|
||||||
foundRule = rule
|
foundRule = rule
|
||||||
break
|
break
|
||||||
|
|
@ -100,17 +92,30 @@ func (e *SecurityGroupRule) Find(c *fi.Context) (*SecurityGroupRule, error) {
|
||||||
|
|
||||||
if foundRule != nil {
|
if foundRule != nil {
|
||||||
actual := &SecurityGroupRule{
|
actual := &SecurityGroupRule{
|
||||||
|
ID: foundRule.SecurityGroupRuleId,
|
||||||
Name: e.Name,
|
Name: e.Name,
|
||||||
SecurityGroup: &SecurityGroup{ID: e.SecurityGroup.ID},
|
SecurityGroup: &SecurityGroup{ID: e.SecurityGroup.ID},
|
||||||
FromPort: foundRule.FromPort,
|
FromPort: foundRule.FromPort,
|
||||||
ToPort: foundRule.ToPort,
|
ToPort: foundRule.ToPort,
|
||||||
Protocol: foundRule.IpProtocol,
|
Protocol: foundRule.IpProtocol,
|
||||||
Egress: e.Egress,
|
Egress: e.Egress,
|
||||||
|
|
||||||
|
Tags: intersectTags(foundRule.Tags, e.Tags),
|
||||||
}
|
}
|
||||||
|
|
||||||
if aws.StringValue(actual.Protocol) == "-1" {
|
if aws.StringValue(actual.Protocol) == "-1" {
|
||||||
actual.Protocol = nil
|
actual.Protocol = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if fi.StringValue(actual.Protocol) != "icmpv6" {
|
||||||
|
if fi.Int64Value(actual.FromPort) == int64(-1) {
|
||||||
|
actual.FromPort = nil
|
||||||
|
}
|
||||||
|
if fi.Int64Value(actual.ToPort) == int64(-1) {
|
||||||
|
actual.ToPort = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if e.CIDR != nil {
|
if e.CIDR != nil {
|
||||||
actual.CIDR = e.CIDR
|
actual.CIDR = e.CIDR
|
||||||
}
|
}
|
||||||
|
|
@ -124,17 +129,27 @@ func (e *SecurityGroupRule) Find(c *fi.Context) (*SecurityGroupRule, error) {
|
||||||
// Avoid spurious changes
|
// Avoid spurious changes
|
||||||
actual.Lifecycle = e.Lifecycle
|
actual.Lifecycle = e.Lifecycle
|
||||||
|
|
||||||
|
e.ID = actual.ID
|
||||||
|
|
||||||
return actual, nil
|
return actual, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *SecurityGroupRule) matches(rule *ec2.IpPermission) bool {
|
func (e *SecurityGroupRule) matches(rule *ec2.SecurityGroupRule) bool {
|
||||||
if aws.Int64Value(rule.FromPort) != aws.Int64Value(e.FromPort) {
|
matchFromPort := int64(-1)
|
||||||
|
if e.FromPort != nil {
|
||||||
|
matchFromPort = *e.FromPort
|
||||||
|
}
|
||||||
|
if aws.Int64Value(rule.FromPort) != matchFromPort {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if aws.Int64Value(rule.ToPort) != aws.Int64Value(e.ToPort) {
|
|
||||||
|
matchToPort := int64(-1)
|
||||||
|
if e.ToPort != nil {
|
||||||
|
matchToPort = *e.ToPort
|
||||||
|
}
|
||||||
|
if aws.Int64Value(rule.ToPort) != matchToPort {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -146,50 +161,19 @@ func (e *SecurityGroupRule) matches(rule *ec2.IpPermission) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.CIDR != nil {
|
if fi.StringValue(e.CIDR) != fi.StringValue(rule.CidrIpv4) {
|
||||||
match := false
|
return false
|
||||||
for _, ipRange := range rule.IpRanges {
|
|
||||||
if aws.StringValue(ipRange.CidrIp) == *e.CIDR {
|
|
||||||
match = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !match {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.IPv6CIDR != nil {
|
if fi.StringValue(e.IPv6CIDR) != fi.StringValue(rule.CidrIpv6) {
|
||||||
match := false
|
return false
|
||||||
for _, ipv6Range := range rule.Ipv6Ranges {
|
|
||||||
if aws.StringValue(ipv6Range.CidrIpv6) == *e.IPv6CIDR {
|
|
||||||
match = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !match {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.SourceGroup != nil {
|
if e.SourceGroup != nil || rule.ReferencedGroupInfo != nil {
|
||||||
match := false
|
if e.SourceGroup == nil || rule.ReferencedGroupInfo == nil {
|
||||||
for _, spec := range rule.UserIdGroupPairs {
|
return false
|
||||||
if e.SourceGroup == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if e.SourceGroup.ID == nil {
|
|
||||||
klog.Warningf("SourceGroup had nil ID: %v", e.SourceGroup)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if aws.StringValue(spec.GroupId) == *e.SourceGroup.ID {
|
|
||||||
match = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if !match {
|
if fi.StringValue(e.SourceGroup.ID) != fi.StringValue(rule.ReferencedGroupInfo.GroupId) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -295,6 +279,7 @@ func (_ *SecurityGroupRule) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Secu
|
||||||
GroupId: e.SecurityGroup.ID,
|
GroupId: e.SecurityGroup.ID,
|
||||||
}
|
}
|
||||||
request.IpPermissions = []*ec2.IpPermission{ipPermission}
|
request.IpPermissions = []*ec2.IpPermission{ipPermission}
|
||||||
|
request.TagSpecifications = awsup.EC2TagSpecification(ec2.ResourceTypeSecurityGroupRule, e.Tags)
|
||||||
|
|
||||||
klog.V(2).Infof("%s: Calling EC2 AuthorizeSecurityGroupEgress (%s)", name, description)
|
klog.V(2).Infof("%s: Calling EC2 AuthorizeSecurityGroupEgress (%s)", name, description)
|
||||||
_, err := t.Cloud.EC2().AuthorizeSecurityGroupEgress(request)
|
_, err := t.Cloud.EC2().AuthorizeSecurityGroupEgress(request)
|
||||||
|
|
@ -306,6 +291,7 @@ func (_ *SecurityGroupRule) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Secu
|
||||||
GroupId: e.SecurityGroup.ID,
|
GroupId: e.SecurityGroup.ID,
|
||||||
}
|
}
|
||||||
request.IpPermissions = []*ec2.IpPermission{ipPermission}
|
request.IpPermissions = []*ec2.IpPermission{ipPermission}
|
||||||
|
request.TagSpecifications = awsup.EC2TagSpecification(ec2.ResourceTypeSecurityGroupRule, e.Tags)
|
||||||
|
|
||||||
klog.V(2).Infof("%s: Calling EC2 AuthorizeSecurityGroupIngress (%s)", name, description)
|
klog.V(2).Infof("%s: Calling EC2 AuthorizeSecurityGroupIngress (%s)", name, description)
|
||||||
_, err := t.Cloud.EC2().AuthorizeSecurityGroupIngress(request)
|
_, err := t.Cloud.EC2().AuthorizeSecurityGroupIngress(request)
|
||||||
|
|
@ -314,6 +300,8 @@ func (_ *SecurityGroupRule) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Secu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if changes.Tags != nil {
|
||||||
|
return t.AddAWSTags(*a.ID, e.Tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// No tags on security group rules (there are tags on the group though)
|
// No tags on security group rules (there are tags on the group though)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue