Skip to content

Commit 80e9953

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 80e9953

11 files changed

+194
-2
lines changed

api/v1beta1/types.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,35 @@ 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 the default firewall rules created
113+
// by the controller. RulesManagement has no effect on user specified firewall rules.
114+
// "Managed": The controller will create and manage firewall rules.
115+
// "Unmanaged": The controller will not create or modify any firewall rules. If
116+
// the RulesManagement is changed from Managed to Unmanaged after the firewall rules
117+
// have been created, then the firewall rules will not be deleted.
118+
//
119+
// Defaults to "Managed".
120+
// +optional
121+
// +kubebuilder:default:="Managed"
122+
RulesManagement RulesManagementPolicy `json:"rulesManagement,omitempty"`
123+
}
124+
125+
// RulesManagementPolicy is a string enum type for managing firewall rules.
126+
// +kubebuilder:validation:Enum=Managed;Unmanaged
127+
type RulesManagementPolicy string
128+
129+
const (
130+
// RulesManagementManaged indicates that the controller should create and manage
131+
// firewall rules. This is the default behavior.
132+
RulesManagementManaged RulesManagementPolicy = "Managed"
133+
134+
// RulesManagementUnmanaged indicates that the controller should not create or manage
135+
// any firewall rules. If rules already exist, they will be left as-is.
136+
RulesManagementUnmanaged RulesManagementPolicy = "Unmanaged"
137+
)
138+
110139
// NetworkSpec encapsulates all things related to a GCP network.
111140
type NetworkSpec struct {
112141
// Name is the name of the network to be used.
@@ -137,6 +166,10 @@ type NetworkSpec struct {
137166
// +optional
138167
HostProject *string `json:"hostProject,omitempty"`
139168

169+
// Firewall configuration.
170+
// +optional
171+
Firewall FirewallSpec `json:"firewall,omitempty"`
172+
140173
// Mtu: Maximum Transmission Unit in bytes. The minimum value for this field is
141174
// 1300 and the maximum value is 8896. The suggested value is 1500, which is
142175
// 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: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,14 @@ 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. If the RulesManagement for the default firewall rules is
111+
// set to unmanaged or when the cluster will include a shared VPC, the default firewall
112+
// rule creation will be skipped.
113+
func (s *ClusterScope) SkipFirewallRuleCreation() bool {
114+
return (s.GCPCluster.Spec.Network.Firewall.RulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
115+
}
116+
109117
// IsSharedVpc returns true If sharedVPC used else , returns false.
110118
func (s *ClusterScope) IsSharedVpc() bool {
111119
return s.NetworkProject() != s.Project()

cloud/scope/managedcluster.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ 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. If the RulesManagement for the default firewall rules is
134+
// set to unmanaged or when the cluster will include a shared VPC, the default firewall
135+
// rule creation will be skipped.
136+
func (s *ManagedClusterScope) SkipFirewallRuleCreation() bool {
137+
return (s.GCPManagedCluster.Spec.Network.Firewall.RulesManagement == infrav1.RulesManagementUnmanaged) || s.IsSharedVpc()
138+
}
139+
132140
// IsSharedVpc returns true If sharedVPC used else , returns false.
133141
func (s *ManagedClusterScope) IsSharedVpc() bool {
134142
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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,25 @@ 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 the default firewall rules created
189+
by the controller. RulesManagement has no effect on user specified firewall rules.
190+
"Managed": The controller will create and manage firewall rules.
191+
"Unmanaged": The controller will not create or modify any firewall rules. If
192+
the RulesManagement is changed from Managed to Unmanaged after the firewall rules
193+
have been created, then the firewall rules will not be deleted.
194+
195+
Defaults to "Managed".
196+
enum:
197+
- Managed
198+
- Unmanaged
199+
type: string
200+
type: object
182201
hostProject:
183202
description: HostProject is the name of the project hosting the
184203
shared VPC network resources.

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,25 @@ 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 the default firewall rules created
208+
by the controller. RulesManagement has no effect on user specified firewall rules.
209+
"Managed": The controller will create and manage firewall rules.
210+
"Unmanaged": The controller will not create or modify any firewall rules. If
211+
the RulesManagement is changed from Managed to Unmanaged after the firewall rules
212+
have been created, then the firewall rules will not be deleted.
213+
214+
Defaults to "Managed".
215+
enum:
216+
- Managed
217+
- Unmanaged
218+
type: string
219+
type: object
201220
hostProject:
202221
description: HostProject is the name of the project hosting
203222
the shared VPC network resources.

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,25 @@ 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 the default firewall rules created
185+
by the controller. RulesManagement has no effect on user specified firewall rules.
186+
"Managed": The controller will create and manage firewall rules.
187+
"Unmanaged": The controller will not create or modify any firewall rules. If
188+
the RulesManagement is changed from Managed to Unmanaged after the firewall rules
189+
have been created, then the firewall rules will not be deleted.
190+
191+
Defaults to "Managed".
192+
enum:
193+
- Managed
194+
- Unmanaged
195+
type: string
196+
type: object
178197
hostProject:
179198
description: HostProject is the name of the project hosting the
180199
shared VPC network resources.

0 commit comments

Comments
 (0)