Skip to content

Commit f04ec02

Browse files
committed
Adding the ability for users to specify what firewall rules should be created.
** Currently the basic/default/required firewall rules are created by CAPG. Users should be given the ability to create the firewall rules associated with VPC that CAPG will create.
1 parent 32a907c commit f04ec02

9 files changed

+1087
-10
lines changed

api/v1beta1/types.go

Lines changed: 109 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,97 @@ type Network struct {
107107
APIInternalForwardingRule *string `json:"apiInternalForwardingRule,omitempty"`
108108
}
109109

110+
// FirewallDescriptor describes a GCP firewall rule.
111+
type FirewallDescriptor struct {
112+
// IPProtocol is the IP protocol to which this rule applies. The protocol type is
113+
// required when creating a firewall rule. This value can either be one of the
114+
// following well known protocol strings (tcp, udp, icmp, esp, ah, ipip, sctp)
115+
// or the IP protocol number.
116+
IPProtocol string `json:"IPProtocol,omitempty"`
117+
// Ports is an optional list of ports to which this rule applies. This field is
118+
// only applicable for the UDP or TCP protocol. Each entry must be either an
119+
// integer or a range. If not specified, this rule applies to connections
120+
// through any port. Example inputs include: ["22"], ["80","443"], and
121+
// ["12345-12349"].
122+
Ports []string `json:"ports,omitempty"`
123+
}
124+
125+
// FirewallRule describes a GCP firewall rule.
126+
type FirewallRule struct {
127+
// Allowed is the list of ALLOW rules specified by this firewall. Each rule
128+
// specifies a protocol and port-range tuple that describes a permitted
129+
// connection.
130+
Allowed []*FirewallDescriptor `json:"allowed,omitempty"`
131+
// Denied is the list of DENY rules specified by this firewall. Each rule
132+
// specifies a protocol and port-range tuple that describes a denied
133+
// connection.
134+
Denied []*FirewallDescriptor `json:"denied,omitempty"`
135+
// Description is an optional description of this resource. Provide this field
136+
// when you create the resource.
137+
Description *string `json:"description,omitempty"`
138+
// DestinationRanges is the list of IP addresses where traffic applies. An empty
139+
// list means all destinations. These ranges must be expressed in CIDR format.
140+
// Both IPv4 and IPv6 are supported.
141+
DestinationRanges []string `json:"destinationRanges,omitempty"`
142+
// Direction is the direction of traffic to which this firewall applies, either
143+
// `INGRESS` or `EGRESS`. The default is `INGRESS`. For `EGRESS` traffic, you
144+
// cannot specify the sourceTags fields.
145+
//
146+
// Possible values:
147+
// "EGRESS" - Indicates that firewall should apply to outgoing traffic.
148+
// "INGRESS" - Indicates that firewall should apply to incoming traffic.
149+
// +kubebuilder:validation:Enum=INGRESS;EGRESS
150+
// +kubebuilder:default=INGRESS
151+
// +optional
152+
Direction *FirewallRuleDirection `json:"direction,omitempty"`
153+
// Disabled denotes whether the firewall rule is disabled. When set to true,
154+
// the firewall rule is not enforced and the network behaves as if it did not
155+
// exist. If this is unspecified, the firewall rule will be enabled.
156+
Disabled *bool `json:"disabled,omitempty"`
157+
// Name is the name of the resource; provided by the client when the resource is
158+
// created. The name must be 1-63 characters long, and comply with RFC1035.
159+
// Specifically, the name must be 1-63 characters long and match the regular
160+
// expression `[a-z]([-a-z0-9]*[a-z0-9])?`. The first character must be a
161+
// lowercase letter, and all following characters (except for the last
162+
// character) must be a dash, lowercase letter, or digit. The last character
163+
// must be a lowercase letter or digit.
164+
Name *string `json:"name,omitempty"`
165+
// Priority is the priority for this rule. This is an integer between `0` and
166+
// `65535`, both inclusive. The default value is `1000`. Relative priorities
167+
// determine which rule takes effect if multiple rules apply. Lower values
168+
// indicate higher priority. For example, a rule with priority `0` has higher
169+
// precedence than a rule with priority `1`. DENY rules take precedence over
170+
// ALLOW rules if they have equal priority. Note that VPC networks have implied
171+
// rules with a priority of `65535`. To avoid conflicts with the implied rules,
172+
// use a priority number less than `65535`.
173+
Priority *int64 `json:"priority,omitempty"`
174+
// SourceRanges: If source ranges are specified, the firewall rule applies only
175+
// to traffic that has a source IP address in these ranges. These ranges must
176+
// be expressed in CIDR format. One or both of sourceRanges and sourceTags may
177+
// be set. If both fields are set, the rule applies to traffic that has a
178+
// source IP address within sourceRanges OR a source IP from a resource with a
179+
// matching tag listed in the sourceTags field. The connection does not need to
180+
// match both fields for the rule to apply. Both IPv4 and IPv6 are supported.
181+
SourceRanges []string `json:"sourceRanges,omitempty"`
182+
// SourceTags are the rules applies only to traffic with source IPs that
183+
// match the primary network interfaces of VM instances that have the tag and
184+
// are in the same VPC network. Source tags cannot be used to control traffic
185+
// to an instance's external IP address, it only applies to traffic between
186+
// instances in the same virtual network. Because tags are associated with
187+
// instances, not IP addresses. One or both of sourceRanges and sourceTags may be
188+
// set. If both fields are set, the firewall applies to traffic that has a source
189+
// IP address within sourceRanges OR a source IP from a resource with a matching
190+
// tag listed in the sourceTags field. The connection does not need to match both
191+
// fields for the firewall to apply.
192+
SourceTags []string `json:"sourceTags,omitempty"`
193+
// TargetTags is a list of tags that controls which instances the firewall rule
194+
// applies to. If targetTags are specified, then the firewall rule applies only
195+
// to instances in the VPC network that have one of those tags. If no
196+
// targetTags are specified, the firewall rule applies to all instances on the
197+
// specified network.
198+
TargetTags []string `json:"targetTags,omitempty"`
199+
}
200+
110201
// FirewallSpec contains configuration for the firewall.
111202
type FirewallSpec struct {
112203
// DefaultRulesManagement determines the management policy for the default firewall rules
@@ -121,8 +212,24 @@ type FirewallSpec struct {
121212
// +optional
122213
// +kubebuilder:default:="Managed"
123214
DefaultRulesManagement RulesManagementPolicy `json:"defaultRulesManagement,omitempty"`
215+
216+
// FirewallRules is a list of additional firewall rules to create.
217+
// +optional
218+
FirewallRules []FirewallRule `json:"firewallRules,omitempty"`
124219
}
125220

221+
// FirewallRuleDirection is a string enum type for the direction of a firewall rule.
222+
// +kubebuilder:validation:Enum=INGRESS;EGRESS
223+
type FirewallRuleDirection string
224+
225+
const (
226+
// FirewallRuleDirectionIngress indicates that the firewall rule applies to incoming traffic.
227+
FirewallRuleDirectionIngress FirewallRuleDirection = "INGRESS"
228+
229+
// FirewallRuleDirectionEgress indicates that the firewall rule applies to outgoing traffic.
230+
FirewallRuleDirectionEgress FirewallRuleDirection = "EGRESS"
231+
)
232+
126233
// RulesManagementPolicy is a string enum type for managing firewall rules.
127234
// +kubebuilder:validation:Enum=Managed;Unmanaged
128235
type RulesManagementPolicy string
@@ -167,9 +274,9 @@ type NetworkSpec struct {
167274
// +optional
168275
HostProject *string `json:"hostProject,omitempty"`
169276

170-
// Firewall configuration.
277+
// FirewallSpec contains the firewall configuration associated with this network.
171278
// +optional
172-
Firewall FirewallSpec `json:"firewall,omitempty,omitzero"`
279+
FirewallSpec FirewallSpec `json:"firewall,omitempty,omitzero"`
173280

174281
// Mtu: Maximum Transmission Unit in bytes. The minimum value for this field is
175282
// 1300 and the maximum value is 8896. The suggested value is 1500, which is

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 110 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cloud/scope/cluster.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"strconv"
23+
"strings"
2324
"time"
2425

2526
"github.com/pkg/errors"
@@ -111,7 +112,7 @@ func (s *ClusterScope) NetworkProject() string {
111112
// set to unmanaged or when the cluster will include a shared VPC, the default firewall
112113
// rule creation will be skipped.
113114
func (s *ClusterScope) SkipFirewallRuleCreation() bool {
114-
return (s.GCPCluster.Spec.Network.Firewall.DefaultRulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
115+
return (s.GCPCluster.Spec.Network.FirewallSpec.DefaultRulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
115116
}
116117

117118
// IsSharedVpc returns true If sharedVPC used else , returns false.
@@ -324,6 +325,40 @@ func (s *ClusterScope) FirewallRulesSpec() []*compute.Firewall {
324325
},
325326
}
326327

328+
// Add user defined firewall rules.
329+
for _, rule := range s.GCPCluster.Spec.Network.FirewallSpec.FirewallRules {
330+
allowed := []*compute.FirewallAllowed{}
331+
for _, a := range rule.Allowed {
332+
allowed = append(allowed, &compute.FirewallAllowed{
333+
IPProtocol: a.IPProtocol,
334+
Ports: a.Ports,
335+
})
336+
}
337+
338+
denied := []*compute.FirewallDenied{}
339+
for _, d := range rule.Denied {
340+
denied = append(denied, &compute.FirewallDenied{
341+
IPProtocol: d.IPProtocol,
342+
Ports: d.Ports,
343+
})
344+
}
345+
346+
direction := string(ptr.Deref(rule.Direction, infrav1.FirewallRuleDirectionIngress))
347+
firewallRules = append(firewallRules, &compute.Firewall{
348+
Name: ptr.Deref(rule.Name, fmt.Sprintf("%s-%s", s.Name(), strings.ToLower(direction))),
349+
Description: ptr.Deref(rule.Description, fmt.Sprintf("Firewall rule %s is created by Cluster API GCP Provider.", s.Name())),
350+
Network: s.NetworkLink(),
351+
Allowed: allowed,
352+
Denied: denied,
353+
Direction: direction,
354+
Priority: ptr.Deref(rule.Priority, int64(1000)),
355+
Disabled: ptr.Deref(rule.Disabled, false),
356+
SourceRanges: rule.SourceRanges,
357+
TargetTags: rule.TargetTags,
358+
SourceTags: rule.SourceTags,
359+
})
360+
}
361+
327362
return firewallRules
328363
}
329364

cloud/scope/managedcluster.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"strconv"
23+
"strings"
2324

2425
"github.com/pkg/errors"
2526
"google.golang.org/api/compute/v1"
@@ -134,7 +135,7 @@ func (s *ManagedClusterScope) NetworkProject() string {
134135
// set to unmanaged or when the cluster will include a shared VPC, the default firewall
135136
// rule creation will be skipped.
136137
func (s *ManagedClusterScope) SkipFirewallRuleCreation() bool {
137-
return (s.GCPManagedCluster.Spec.Network.Firewall.DefaultRulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
138+
return (s.GCPManagedCluster.Spec.Network.FirewallSpec.DefaultRulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
138139
}
139140

140141
// IsSharedVpc returns true If sharedVPC used else , returns false.
@@ -308,6 +309,40 @@ func (s *ManagedClusterScope) FirewallRulesSpec() []*compute.Firewall {
308309
},
309310
}
310311

312+
// Add user defined firewall rules.
313+
for _, rule := range s.GCPManagedCluster.Spec.Network.FirewallSpec.FirewallRules {
314+
allowed := []*compute.FirewallAllowed{}
315+
for _, a := range rule.Allowed {
316+
allowed = append(allowed, &compute.FirewallAllowed{
317+
IPProtocol: a.IPProtocol,
318+
Ports: a.Ports,
319+
})
320+
}
321+
322+
denied := []*compute.FirewallDenied{}
323+
for _, d := range rule.Denied {
324+
denied = append(denied, &compute.FirewallDenied{
325+
IPProtocol: d.IPProtocol,
326+
Ports: d.Ports,
327+
})
328+
}
329+
330+
direction := string(ptr.Deref(rule.Direction, infrav1.FirewallRuleDirectionIngress))
331+
firewallRules = append(firewallRules, &compute.Firewall{
332+
Name: ptr.Deref(rule.Name, fmt.Sprintf("%s-%s", s.Name(), strings.ToLower(direction))),
333+
Description: ptr.Deref(rule.Description, fmt.Sprintf("Firewall rule %s is created by Cluster API GCP Provider.", s.Name())),
334+
Network: s.NetworkLink(),
335+
Allowed: allowed,
336+
Denied: denied,
337+
Direction: direction,
338+
Priority: ptr.Deref(rule.Priority, int64(1000)),
339+
Disabled: ptr.Deref(rule.Disabled, false),
340+
SourceRanges: rule.SourceRanges,
341+
TargetTags: rule.TargetTags,
342+
SourceTags: rule.SourceTags,
343+
})
344+
}
345+
311346
return firewallRules
312347
}
313348

0 commit comments

Comments
 (0)