Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 130 additions & 2 deletions api/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,118 @@ type Network struct {
APIInternalForwardingRule *string `json:"apiInternalForwardingRule,omitempty"`
}

// FirewallDescriptor describes a GCP firewall rule.
type FirewallDescriptor struct {
// IPProtocol: The IP protocol to which this rule applies. The protocol type is
// required when creating a firewall rule. This value can either be one of the
// following well known protocol strings (tcp, udp, icmp, esp, ah, ipip, sctp)
// or the IP protocol number.
IPProtocol string `json:"IPProtocol,omitempty"`
// Ports: An optional list of ports to which this rule applies. This field is
// only applicable for the UDP or TCP protocol. Each entry must be either an
// integer or a range. If not specified, this rule applies to connections
// through any port. Example inputs include: ["22"], ["80","443"], and
// ["12345-12349"].
Ports []string `json:"ports,omitempty"`
}

// FirewallRule describes a GCP firewall rule.
type FirewallRule struct {
// Allowed: The list of ALLOW rules specified by this firewall. Each rule
// specifies a protocol and port-range tuple that describes a permitted
// connection.
Allowed []*FirewallDescriptor `json:"allowed,omitempty"`
// Denied: The list of DENY rules specified by this firewall. Each rule
// specifies a protocol and port-range tuple that describes a denied
// connection.
Denied []*FirewallDescriptor `json:"denied,omitempty"`
// Description: An optional description of this resource. Provide this field
// when you create the resource.
Description *string `json:"description,omitempty"`
// DestinationRanges: If destination ranges are specified, the firewall rule
// applies only to traffic that has destination IP address in these ranges.
// These ranges must be expressed in CIDR format. Both IPv4 and IPv6 are
// supported.
DestinationRanges []string `json:"destinationRanges,omitempty"`
// Direction: Direction of traffic to which this firewall applies, either
// `INGRESS` or `EGRESS`. The default is `INGRESS`. For `EGRESS` traffic, you
// cannot specify the sourceTags fields.
//
// Possible values:
// "EGRESS" - Indicates that firewall should apply to outgoing traffic.
// "INGRESS" - Indicates that firewall should apply to incoming traffic.
// +kubebuilder:validation:Enum=INGRESS;EGRESS
// +kubebuilder:default=INGRESS
// +optional
Direction *FirewallRuleDirection `json:"direction,omitempty"`
// Disabled: Denotes whether the firewall rule is disabled. When set to true,
// the firewall rule is not enforced and the network behaves as if it did not
// exist. If this is unspecified, the firewall rule will be enabled.
Disabled *bool `json:"disabled,omitempty"`
// Name: Name of the resource; provided by the client when the resource is
// created. The name must be 1-63 characters long, and comply with RFC1035.
// Specifically, the name must be 1-63 characters long and match the regular
// expression `[a-z]([-a-z0-9]*[a-z0-9])?`. The first character must be a
// lowercase letter, and all following characters (except for the last
// character) must be a dash, lowercase letter, or digit. The last character
// must be a lowercase letter or digit.
Name *string `json:"name,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about collisions here - should we use this as a suffix with the cluster name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What collision are you thinking @justinsb ? This should be nested so name collision shouldn't really matter and the hard part with nesting names is the max of 63 characters. Cluster names can get quite large too.

// Priority: Priority for this rule. This is an integer between `0` and
// `65535`, both inclusive. The default value is `1000`. Relative priorities
// determine which rule takes effect if multiple rules apply. Lower values
// indicate higher priority. For example, a rule with priority `0` has higher
// precedence than a rule with priority `1`. DENY rules take precedence over
// ALLOW rules if they have equal priority. Note that VPC networks have implied
// rules with a priority of `65535`. To avoid conflicts with the implied rules,
// use a priority number less than `65535`.
Priority *int64 `json:"priority,omitempty"`
// SourceRanges: If source ranges are specified, the firewall rule applies only
// to traffic that has a source IP address in these ranges. These ranges must
// be expressed in CIDR format. One or both of sourceRanges and sourceTags may
// be set. If both fields are set, the rule applies to traffic that has a
// source IP address within sourceRanges OR a source IP from a resource with a
// matching tag listed in the sourceTags field. The connection does not need to
// match both fields for the rule to apply. Both IPv4 and IPv6 are supported.
SourceRanges []string `json:"sourceRanges,omitempty"`
// SourceServiceAccounts: If source service accounts are specified, the
// firewall rules apply only to traffic originating from an instance with a
// service account in this list. Source service accounts cannot be used to
// control traffic to an instance's external IP address because service
// accounts are associated with an instance, not an IP address. sourceRanges
// can be set at the same time as sourceServiceAccounts. If both are set, the
// firewall applies to traffic that has a source IP address within the
// sourceRanges OR a source IP that belongs to an instance with service account
// listed in sourceServiceAccount. The connection does not need to match both
// fields for the firewall to apply. sourceServiceAccounts cannot be used at
// the same time as sourceTags or targetTags.
SourceServiceAccounts []string `json:"sourceServiceAccounts,omitempty"`
// SourceTags: If source tags are specified, the firewall rule applies only to
// traffic with source IPs that match the primary network interfaces of VM
// instances that have the tag and are in the same VPC network. Source tags
// cannot be used to control traffic to an instance's external IP address, it
// only applies to traffic between instances in the same virtual network.
// Because tags are associated with instances, not IP addresses. One or both of
// sourceRanges and sourceTags may be set. If both fields are set, the firewall
// applies to traffic that has a source IP address within sourceRanges OR a
// source IP from a resource with a matching tag listed in the sourceTags
// field. The connection does not need to match both fields for the firewall to
// apply.
SourceTags []string `json:"sourceTags,omitempty"`
// TargetServiceAccounts: A list of service accounts indicating sets of
// instances located in the network that may make network connections as
// specified in allowed[]. targetServiceAccounts cannot be used at the same
// time as targetTags or sourceTags. If neither targetServiceAccounts nor
// targetTags are specified, the firewall rule applies to all instances on the
// specified network.
TargetServiceAccounts []string `json:"targetServiceAccounts,omitempty"`
// TargetTags: A list of tags that controls which instances the firewall rule
// applies to. If targetTags are specified, then the firewall rule applies only
// to instances in the VPC network that have one of those tags. If no
// targetTags are specified, the firewall rule applies to all instances on the
// specified network.
TargetTags []string `json:"targetTags,omitempty"`
}

// FirewallSpec contains configuration for the firewall.
type FirewallSpec struct {
// DefaultRulesManagement determines the management policy for the default firewall rules
Expand All @@ -121,8 +233,24 @@ type FirewallSpec struct {
// +optional
// +kubebuilder:default:="Managed"
DefaultRulesManagement RulesManagementPolicy `json:"defaultRulesManagement,omitempty"`

// FirewallRules is a list of additional firewall rules to create.
// +optional
FirewallRules []FirewallRule `json:"firewallRules,omitempty"`
}

// FirewallRuleDirection is a string enum type for the direction of a firewall rule.
// +kubebuilder:validation:Enum=INGRESS;EGRESS
type FirewallRuleDirection string

const (
// FirewallRuleDirectionIngress indicates that the firewall rule applies to incoming traffic.
FirewallRuleDirectionIngress FirewallRuleDirection = "INGRESS"

// FirewallRuleDirectionEgress indicates that the firewall rule applies to outgoing traffic.
FirewallRuleDirectionEgress FirewallRuleDirection = "EGRESS"
)

// RulesManagementPolicy is a string enum type for managing firewall rules.
// +kubebuilder:validation:Enum=Managed;Unmanaged
type RulesManagementPolicy string
Expand Down Expand Up @@ -167,9 +295,9 @@ type NetworkSpec struct {
// +optional
HostProject *string `json:"hostProject,omitempty"`

// Firewall configuration.
// FirewallSpec contains the firewall configuration associated with this network.
// +optional
Firewall FirewallSpec `json:"firewall,omitempty,omitzero"`
FirewallSpec FirewallSpec `json:"firewall,omitempty,omitzero"`

// Mtu: Maximum Transmission Unit in bytes. The minimum value for this field is
// 1300 and the maximum value is 8896. The suggested value is 1500, which is
Expand Down
121 changes: 120 additions & 1 deletion api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 36 additions & 1 deletion cloud/scope/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"strconv"
"strings"
"time"

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

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

// Add user defined firewall rules.
for _, rule := range s.GCPCluster.Spec.Network.FirewallSpec.FirewallRules {
allowed := []*compute.FirewallAllowed{}
for _, a := range rule.Allowed {
allowed = append(allowed, &compute.FirewallAllowed{
IPProtocol: a.IPProtocol,
Ports: a.Ports,
})
}

denied := []*compute.FirewallDenied{}
for _, d := range rule.Denied {
denied = append(denied, &compute.FirewallDenied{
IPProtocol: d.IPProtocol,
Ports: d.Ports,
})
}

direction := string(ptr.Deref(rule.Direction, infrav1.FirewallRuleDirectionIngress))
firewallRules = append(firewallRules, &compute.Firewall{
Name: ptr.Deref(rule.Name, fmt.Sprintf("%s-%s", s.Name(), strings.ToLower(direction))),
Description: ptr.Deref(rule.Description, fmt.Sprintf("Firewall rule %s is created by Cluster API GCP Provider.", s.Name())),
Network: s.NetworkLink(),
Allowed: allowed,
Denied: denied,
Direction: direction,
Priority: ptr.Deref(rule.Priority, int64(1000)),
Disabled: ptr.Deref(rule.Disabled, false),
SourceRanges: rule.SourceRanges,
TargetTags: rule.TargetTags,
SourceTags: rule.SourceTags,
})
}

return firewallRules
}

Expand Down
Loading