Skip to content

Commit

Permalink
mockGCP for compute firewall policy rule
Browse files Browse the repository at this point in the history
  • Loading branch information
gemmahou committed Oct 1, 2024
1 parent e2ce9af commit b9e231f
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 33 deletions.
1 change: 1 addition & 0 deletions config/tests/samples/create/harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ func MaybeSkip(t *testing.T, name string, resources []*unstructured.Unstructured
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeBackendService"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeDisk"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeFirewallPolicy"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeFirewallPolicyRule"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeForwardingRule"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeHealthCheck"}:
case schema.GroupKind{Group: "compute.cnrm.cloud.google.com", Kind: "ComputeInstance"}:
Expand Down
246 changes: 244 additions & 2 deletions mockgcp/mockcompute/firewallpoliciesv1.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ package mockcompute

import (
"context"
"strconv"
"strings"

"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
"strconv"
"strings"

pb "github.com/GoogleCloudPlatform/k8s-config-connector/mockgcp/generated/mockgcp/cloud/compute/v1"
)
Expand Down Expand Up @@ -227,6 +228,247 @@ func (s *FirewallPoliciesV1) Delete(ctx context.Context, req *pb.DeleteFirewallP
})
}

func (s *FirewallPoliciesV1) GetRule(ctx context.Context, req *pb.GetRuleFirewallPolicyRequest) (*pb.FirewallPolicyRule, error) {
reqName := "locations/global/firewallPolicies/" + req.GetFirewallPolicy()
name, err := s.parseFirewallPolicyName(reqName)
if err != nil {
return nil, err
}

fqn := name.String()

obj := &pb.FirewallPolicy{}
if err := s.storage.Get(ctx, fqn, obj); err != nil {
return nil, err
}

if obj.Rules == nil {
// add default rule
obj.Rules = []*pb.FirewallPolicyRule{
{
Action: PtrTo("goto_next"),
Description: PtrTo("default egress rule ipv6"),
Direction: PtrTo("EGRESS"),
EnableLogging: PtrTo(false),
Kind: PtrTo("compute#firewallPolicyRule"),
Match: &pb.FirewallPolicyRuleMatcher{
DestIpRanges: []string{"::/0"},
Layer4Configs: []*pb.FirewallPolicyRuleMatcherLayer4Config{
{
IpProtocol: PtrTo("all"),
},
},
},
Priority: PtrTo(int32(2147483644)),
RuleTupleCount: PtrTo(int32(2)),
},
{
Action: PtrTo("goto_next"),
Description: PtrTo("default ingress rule ipv6"),
Direction: PtrTo("INGRESS"),
EnableLogging: PtrTo(false),
Kind: PtrTo("compute#firewallPolicyRule"),
Match: &pb.FirewallPolicyRuleMatcher{
SrcIpRanges: []string{"::/0"},
Layer4Configs: []*pb.FirewallPolicyRuleMatcherLayer4Config{
{
IpProtocol: PtrTo("all"),
},
},
},
Priority: PtrTo(int32(2147483645)),
RuleTupleCount: PtrTo(int32(2)),
},
{
Action: PtrTo("goto_next"),
Description: PtrTo("default egress rule"),
Direction: PtrTo("EGRESS"),
EnableLogging: PtrTo(false),
Kind: PtrTo("compute#firewallPolicyRule"),
Match: &pb.FirewallPolicyRuleMatcher{
DestIpRanges: []string{"0.0.0.0/0"},
Layer4Configs: []*pb.FirewallPolicyRuleMatcherLayer4Config{
{
IpProtocol: PtrTo("all"),
},
},
},
Priority: PtrTo(int32(2147483646)),
RuleTupleCount: PtrTo(int32(2)),
},
{
Action: PtrTo("goto_next"),
Description: PtrTo("default ingress rule"),
Direction: PtrTo("INGRESS"),
EnableLogging: PtrTo(false),
Kind: PtrTo("compute#firewallPolicyRule"),
Match: &pb.FirewallPolicyRuleMatcher{
SrcIpRanges: []string{"0.0.0.0/0"},
Layer4Configs: []*pb.FirewallPolicyRuleMatcherLayer4Config{
{
IpProtocol: PtrTo("all"),
},
},
},
Priority: PtrTo(int32(2147483647)),
RuleTupleCount: PtrTo(int32(2)),
},
}
if err := s.storage.Update(ctx, fqn, obj); err != nil {
return nil, err
}
}

var rule *pb.FirewallPolicyRule
rules := obj.GetRules()

for _, r := range rules {
if r.Priority != nil && *r.Priority == *req.Priority {
rule = r
}
}
if rule == nil {
return nil, status.Errorf(codes.InvalidArgument, "Invalid value for field 'priority': '%d'. The firewall policy does not contain a rule at priority %d.", int(*req.Priority), int(*req.Priority))
}

return rule, nil
}

func (s *FirewallPoliciesV1) AddRule(ctx context.Context, req *pb.AddRuleFirewallPolicyRequest) (*pb.Operation, error) {
reqName := "locations/global/firewallPolicies/" + req.GetFirewallPolicy()
name, err := s.parseFirewallPolicyName(reqName)
if err != nil {
return nil, err
}

fqn := name.String()

obj := &pb.FirewallPolicy{}
if err := s.storage.Get(ctx, fqn, obj); err != nil {
return nil, err
}

r := req.GetFirewallPolicyRuleResource()
// RuleTupleCount is output only, calculation of the complexity of a single firewall policy rule.
// Manually set different ruleTupleCount to match the realGCP log
if r.TargetResources != nil {
r.RuleTupleCount = PtrTo(int32(4))
} else {
r.RuleTupleCount = PtrTo(int32(2))
}
r.Kind = PtrTo("compute#firewallPolicyRule")
if r.Description == nil {
r.Description = PtrTo("")
}

obj.Rules = []*pb.FirewallPolicyRule{r}
if err := s.storage.Update(ctx, fqn, obj); err != nil {
return nil, err
}

op := &pb.Operation{
TargetId: obj.Id,
TargetLink: obj.SelfLink,
OperationType: PtrTo("addFirewallRuleToFirewallPolicy"),
User: PtrTo("[email protected]"),
}
return s.startGlobalOrganizationLRO(ctx, op, func() (proto.Message, error) {
return obj, nil
})
}

func (s *FirewallPoliciesV1) PatchRule(ctx context.Context, req *pb.PatchRuleFirewallPolicyRequest) (*pb.Operation, error) {
reqName := "locations/global/firewallPolicies/" + req.GetFirewallPolicy()

name, err := s.parseFirewallPolicyName(reqName)
if err != nil {
return nil, err
}

fqn := name.String()
obj := &pb.FirewallPolicy{}
if err := s.storage.Get(ctx, fqn, obj); err != nil {
return nil, err
}

rules := []*pb.FirewallPolicyRule{}
for _, rule := range obj.Rules {
if rule.Priority != nil && *rule.Priority == *req.Priority {
// update the rule
r := req.GetFirewallPolicyRuleResource()
r.Priority = PtrTo(*rule.Priority)
// RuleTupleCount is output only, calculation of the complexity of a single firewall policy rule.
// Manually set different ruleTupleCount to match the realGCP log
if r.TargetResources != nil {
r.RuleTupleCount = PtrTo(int32(4))
} else {
r.RuleTupleCount = PtrTo(int32(2))
}
r.Kind = PtrTo("compute#firewallPolicyRule")
if r.Description == nil {
r.Description = PtrTo("")
}
rules = append(rules, r)
} else {
rules = append(rules, rule)
}
}

obj.Rules = rules
if err := s.storage.Update(ctx, fqn, obj); err != nil {
return nil, err
}

op := &pb.Operation{
TargetId: obj.Id,
TargetLink: obj.SelfLink,
OperationType: PtrTo("patchFirewallRuleInFirewallPolicy"),
User: PtrTo("[email protected]"),
}
return s.startGlobalOrganizationLRO(ctx, op, func() (proto.Message, error) {
return obj, nil
})
}
func (s *FirewallPoliciesV1) RemoveRule(ctx context.Context, req *pb.RemoveRuleFirewallPolicyRequest) (*pb.Operation, error) {
reqName := "locations/global/firewallPolicies/" + req.GetFirewallPolicy()
name, err := s.parseFirewallPolicyName(reqName)
if err != nil {
return nil, err
}

fqn := name.String()

obj := &pb.FirewallPolicy{}
if err := s.storage.Get(ctx, fqn, obj); err != nil {
return nil, err
}

rules := []*pb.FirewallPolicyRule{}
for _, rule := range obj.Rules {
if rule.Priority != nil && *rule.Priority == *req.Priority {
// remove the rule
continue
} else {
rules = append(rules, rule)
}
}

obj.Rules = rules
if err := s.storage.Update(ctx, fqn, obj); err != nil {
return nil, err
}

op := &pb.Operation{
TargetId: obj.Id,
TargetLink: obj.SelfLink,
OperationType: PtrTo("removeFirewallRuleFromFirewallPolicy"),
User: PtrTo("[email protected]"),
}
return s.startGlobalOrganizationLRO(ctx, op, func() (proto.Message, error) {
return obj, nil
})
}

type firewallPolicyName struct {
Name string
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ X-Xss-Protection: 0
"selfLink": "https://www.googleapis.com/compute/v1/locations/global/operations/${operationID}",
"startTime": "2024-04-01T12:34:56.123456Z",
"status": "RUNNING",
"targetId": "${firewallPolicyId}",
"targetLink": "https://www.googleapis.com/compute/v1/locations/global/firewallPolicies/${firewallPolicyId}",
"user": "[email protected]"
}

Expand Down Expand Up @@ -195,13 +197,6 @@ X-Xss-Protection: 0
{
"error": {
"code": 400,
"errors": [
{
"domain": "global",
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000.",
"reason": "invalid"
}
],
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000."
}
}
Expand Down Expand Up @@ -525,13 +520,6 @@ X-Xss-Protection: 0
{
"error": {
"code": 400,
"errors": [
{
"domain": "global",
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000.",
"reason": "invalid"
}
],
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000."
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ X-Xss-Protection: 0
"selfLink": "https://www.googleapis.com/compute/v1/locations/global/operations/${operationID}",
"startTime": "2024-04-01T12:34:56.123456Z",
"status": "RUNNING",
"targetId": "${firewallPolicyId}",
"targetLink": "https://www.googleapis.com/compute/v1/locations/global/firewallPolicies/${firewallPolicyId}",
"user": "[email protected]"
}

Expand Down Expand Up @@ -304,7 +306,6 @@ X-Xss-Protection: 0
"name": "network-${uniqueId}",
"networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL",
"routingConfig": {
"bgpBestPathSelectionMode": "LEGACY",
"routingMode": "REGIONAL"
},
"selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/network-${uniqueId}",
Expand Down Expand Up @@ -418,13 +419,6 @@ X-Xss-Protection: 0
{
"error": {
"code": 400,
"errors": [
{
"domain": "global",
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000.",
"reason": "invalid"
}
],
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000."
}
}
Expand Down Expand Up @@ -552,7 +546,7 @@ X-Xss-Protection: 0
"priority": 9000,
"ruleTupleCount": 4,
"targetResources": [
"https://www.googleapis.com/compute/beta/projects/${projectId}/global/networks/network-${uniqueId}"
"https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/network-${uniqueId}"
],
"targetServiceAccounts": [
"projects/${projectId}/serviceAccounts/sa-${uniqueId}@${projectId}.iam.gserviceaccount.com"
Expand Down Expand Up @@ -644,13 +638,6 @@ X-Xss-Protection: 0
{
"error": {
"code": 400,
"errors": [
{
"domain": "global",
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000.",
"reason": "invalid"
}
],
"message": "Invalid value for field 'priority': '9000'. The firewall policy does not contain a rule at priority 9000."
}
}
Expand Down Expand Up @@ -723,7 +710,6 @@ X-Xss-Protection: 0
"name": "network-${uniqueId}",
"networkFirewallPolicyEnforcementOrder": "AFTER_CLASSIC_FIREWALL",
"routingConfig": {
"bgpBestPathSelectionMode": "LEGACY",
"routingMode": "REGIONAL"
},
"selfLink": "https://www.googleapis.com/compute/v1/projects/${projectId}/global/networks/network-${uniqueId}",
Expand Down

0 comments on commit b9e231f

Please sign in to comment.