Skip to content

Commit 56d4280

Browse files
committed
CORS-4230: Add a firewall spec and the ability to manage or unmanaged firewall rule creation
api: Add API changes to Skip firewall rule creation. When unmanaged, the firewall rules will not be created. When this is the case, the firewall rules should exist prior to creating the network. This will allow ServiceAccounts to skip the rules: compute.firewalls.create cloud: Update the services and interfaces. The firewall service will no longer create firewall rules when the firewall policy is set to unmanaged OR when a shared vpc is used during installation and resource creation.
1 parent 5e0eb53 commit 56d4280

11 files changed

+180
-2
lines changed

api/v1beta1/types.go

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

110+
// FirewallSpec contains configuration for the firewall.
111+
type FirewallSpec struct {
112+
// RulesManagement determines the management policy for firewall rules.
113+
// "Managed": The controller will create and manage firewall rules.
114+
// "Unmanaged": The controller will not touch any firewall rules. If this is
115+
// changed to "Off" after rules have been created, they will not be
116+
// deleted.
117+
// Defaults to "Managed".
118+
// +optional
119+
// +kubebuilder:default:="Managed"
120+
RulesManagement RulesManagementPolicy `json:"rulesManagement,omitempty"`
121+
}
122+
123+
// RulesManagementPolicy is a string enum type for managing firewall rules.
124+
// +kubebuilder:validation:Enum=Managed;Unmanaged
125+
type RulesManagementPolicy string
126+
127+
const (
128+
// RulesManagementManaged indicates that the controller should create and manage
129+
// firewall rules. This is the default behavior.
130+
RulesManagementManaged RulesManagementPolicy = "Managed"
131+
132+
// RulesManagementUnmanaged indicates that the controller should not create or manage
133+
// any firewall rules. If rules already exist, they will be left as-is.
134+
RulesManagementUnmanaged RulesManagementPolicy = "Unmanaged"
135+
)
136+
110137
// NetworkSpec encapsulates all things related to a GCP network.
111138
type NetworkSpec struct {
112139
// Name is the name of the network to be used.
@@ -137,6 +164,10 @@ type NetworkSpec struct {
137164
// +optional
138165
HostProject *string `json:"hostProject,omitempty"`
139166

167+
// Firewall configuration.
168+
// +optional
169+
Firewall FirewallSpec `json:"firewall,omitempty"`
170+
140171
// Mtu: Maximum Transmission Unit in bytes. The minimum value for this field is
141172
// 1300 and the maximum value is 8896. The suggested value is 1500, which is
142173
// the default MTU used on the Internet, or 8896 if you want to use Jumbo

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cloud/interfaces.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type ClusterGetter interface {
5858
NetworkName() string
5959
NetworkProject() string
6060
IsSharedVpc() bool
61+
SkipFirewallRuleCreation() bool
6162
Network() *infrav1.Network
6263
AdditionalLabels() infrav1.Labels
6364
FailureDomains() clusterv1.FailureDomains

cloud/scope/cluster.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ func (s *ClusterScope) NetworkProject() string {
106106
return ptr.Deref(s.GCPCluster.Spec.Network.HostProject, s.Project())
107107
}
108108

109+
// SkipFirewallRuleCreation returns whether the spec indicates that firewall rules
110+
// should be created or not.
111+
func (s *ClusterScope) SkipFirewallRuleCreation() bool {
112+
return (s.GCPCluster.Spec.Network.Firewall.RulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
113+
}
114+
109115
// IsSharedVpc returns true If sharedVPC used else , returns false.
110116
func (s *ClusterScope) IsSharedVpc() bool {
111117
return s.NetworkProject() != s.Project()

cloud/scope/managedcluster.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,12 @@ func (s *ManagedClusterScope) NetworkProject() string {
129129
return ptr.Deref(s.GCPManagedCluster.Spec.Network.HostProject, s.Project())
130130
}
131131

132+
// SkipFirewallRuleCreation returns whether the spec indicates that firewall rules
133+
// should be created or not.
134+
func (s *ManagedClusterScope) SkipFirewallRuleCreation() bool {
135+
return (s.GCPManagedCluster.Spec.Network.Firewall.RulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
136+
}
137+
132138
// IsSharedVpc returns true If sharedVPC used else , returns false.
133139
func (s *ManagedClusterScope) IsSharedVpc() bool {
134140
return s.NetworkProject() != s.Project()

cloud/services/compute/firewalls/reconcile.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import (
2828
// Reconcile reconcile cluster firewall compoenents.
2929
func (s *Service) Reconcile(ctx context.Context) error {
3030
log := log.FromContext(ctx)
31-
if s.scope.IsSharedVpc() {
32-
log.V(2).Info("Shared VPC enabled. Ignore Reconciling firewall resources")
31+
if s.scope.SkipFirewallRuleCreation() {
32+
log.V(2).Info("Ignore Reconciling firewall resources")
3333
return nil
3434
}
3535
log.Info("Reconciling firewall resources")

cloud/services/compute/firewalls/reconcile_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,34 @@ var fakeGCPClusterSharedVPC = &infrav1.GCPCluster{
109109
},
110110
}
111111

112+
var fakeGCPClusterUnmanagedFirewalls = &infrav1.GCPCluster{
113+
ObjectMeta: metav1.ObjectMeta{
114+
Name: "my-cluster",
115+
Namespace: "default",
116+
},
117+
Spec: infrav1.GCPClusterSpec{
118+
Project: "my-proj",
119+
Region: "us-central1",
120+
Network: infrav1.NetworkSpec{
121+
Name: ptr.To("my-network"),
122+
Subnets: infrav1.Subnets{
123+
infrav1.SubnetSpec{
124+
Name: "workers",
125+
CidrBlock: "10.0.0.1/28",
126+
Region: "us-central1",
127+
Purpose: ptr.To[string]("INTERNAL_HTTPS_LOAD_BALANCER"),
128+
},
129+
},
130+
Firewall: infrav1.FirewallSpec{
131+
RulesManagement: infrav1.RulesManagementUnmanaged,
132+
},
133+
},
134+
},
135+
Status: infrav1.GCPClusterStatus{
136+
Network: infrav1.Network{},
137+
},
138+
}
139+
112140
type testCase struct {
113141
name string
114142
scope func() Scope
@@ -146,6 +174,18 @@ func TestService_Reconcile(t *testing.T) {
146174
t.Fatal(err)
147175
}
148176

177+
clusterScopeUnmanagedFirewalls, err := scope.NewClusterScope(context.TODO(), scope.ClusterScopeParams{
178+
Client: fakec,
179+
Cluster: fakeCluster,
180+
GCPCluster: fakeGCPClusterUnmanagedFirewalls,
181+
GCPServices: scope.GCPServices{
182+
Compute: &compute.Service{},
183+
},
184+
})
185+
if err != nil {
186+
t.Fatal(err)
187+
}
188+
149189
tests := []testCase{
150190
{
151191
name: "firewall rule does not exist successful create",
@@ -211,6 +251,16 @@ func TestService_Reconcile(t *testing.T) {
211251
},
212252
},
213253
},
254+
{
255+
name: "firewall return no error using unmanaged firewall settings",
256+
scope: func() Scope { return clusterScopeUnmanagedFirewalls },
257+
mockFirewalls: &cloud.MockFirewalls{
258+
ProjectRouter: &cloud.SingleProjectRouter{ID: "my-proj"},
259+
Objects: map[meta.Key]*cloud.MockFirewallsObj{
260+
*meta.GlobalKey(fmt.Sprintf("allow-%s-healthchecks", fakeGCPCluster.Name)): {},
261+
},
262+
},
263+
},
214264
}
215265
for _, tt := range tests {
216266
t.Run(tt.name, func(t *testing.T) {

config/crd/bases/infrastructure.cluster.x-k8s.io_gcpclusters.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,23 @@ spec:
179179
180180
Defaults to true.
181181
type: boolean
182+
firewall:
183+
description: Firewall configuration.
184+
properties:
185+
rulesManagement:
186+
default: Managed
187+
description: |-
188+
RulesManagement determines the management policy for firewall rules.
189+
"Managed": The controller will create and manage firewall rules.
190+
"Unmanaged": The controller will not touch any firewall rules. If this is
191+
changed to "Off" after rules have been created, they will not be
192+
deleted.
193+
Defaults to "Managed".
194+
enum:
195+
- Managed
196+
- Unmanaged
197+
type: string
198+
type: object
182199
hostProject:
183200
description: HostProject is the name of the project hosting the
184201
shared VPC network resources.

config/crd/bases/infrastructure.cluster.x-k8s.io_gcpclustertemplates.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,23 @@ spec:
198198
199199
Defaults to true.
200200
type: boolean
201+
firewall:
202+
description: Firewall configuration.
203+
properties:
204+
rulesManagement:
205+
default: Managed
206+
description: |-
207+
RulesManagement determines the management policy for firewall rules.
208+
"Managed": The controller will create and manage firewall rules.
209+
"Unmanaged": The controller will not touch any firewall rules. If this is
210+
changed to "Off" after rules have been created, they will not be
211+
deleted.
212+
Defaults to "Managed".
213+
enum:
214+
- Managed
215+
- Unmanaged
216+
type: string
217+
type: object
201218
hostProject:
202219
description: HostProject is the name of the project hosting
203220
the shared VPC network resources.

config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedclusters.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,23 @@ spec:
175175
176176
Defaults to true.
177177
type: boolean
178+
firewall:
179+
description: Firewall configuration.
180+
properties:
181+
rulesManagement:
182+
default: Managed
183+
description: |-
184+
RulesManagement determines the management policy for firewall rules.
185+
"Managed": The controller will create and manage firewall rules.
186+
"Unmanaged": The controller will not touch any firewall rules. If this is
187+
changed to "Off" after rules have been created, they will not be
188+
deleted.
189+
Defaults to "Managed".
190+
enum:
191+
- Managed
192+
- Unmanaged
193+
type: string
194+
type: object
178195
hostProject:
179196
description: HostProject is the name of the project hosting the
180197
shared VPC network resources.

0 commit comments

Comments
 (0)