Skip to content

Commit fa22fb8

Browse files
Fix merge strategy for NSG/Subnet and remove usage of ID for NSG seclist reconciliation (#116)
1 parent 64f0980 commit fa22fb8

File tree

7 files changed

+124
-158
lines changed

7 files changed

+124
-158
lines changed

api/v1beta1/types.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,16 @@ type IngressSecurityRule struct {
147147
type IngressSecurityRuleForNSG struct {
148148
//IngressSecurityRule ID for NSG.
149149
// +optional
150+
// Deprecated: this field is not populated and used during reconciliation
150151
ID *string `json:"id,omitempty"`
151152
IngressSecurityRule `json:"ingressRule,omitempty"`
152153
}
153154

154155
// EgressSecurityRuleForNSG is EgressSecurityRule for NSG.
155156
type EgressSecurityRuleForNSG struct {
156-
//EgressSecurityRule ID for NSG.
157+
// EgressSecurityRule ID for NSG.
157158
// +optional
159+
// Deprecated: this field is not populated and used during reconciliation
158160
ID *string `json:"id,omitempty"`
159161
EgressSecurityRule `json:"egressRule,omitempty"`
160162
}
@@ -251,7 +253,6 @@ type Subnet struct {
251253
// +optional
252254
ID *string `json:"id,omitempty"`
253255
// Subnet Name.
254-
// +optional
255256
Name string `json:"name"`
256257
// Subnet CIDR.
257258
// +optional
@@ -271,7 +272,6 @@ type NSG struct {
271272
// +optional
272273
ID *string `json:"id,omitempty"`
273274
// NSG Name.
274-
// +optional
275275
Name string `json:"name"`
276276
// Role defines the NSG role (eg. control-plane, control-plane-endpoint, service-lb, worker).
277277
Role Role `json:"role,omitempty"`
@@ -318,10 +318,14 @@ type VCN struct {
318318

319319
// Subnets is the configuration for subnets required in the VCN.
320320
// +optional
321+
// +listType=map
322+
// +listMapKey=name
321323
Subnets []*Subnet `json:"subnets,omitempty"`
322324

323325
// NetworkSecurityGroups is the configuration for the Network Security Groups required in the VCN.
324326
// +optional
327+
// +listType=map
328+
// +listMapKey=name
325329
NetworkSecurityGroups []*NSG `json:"networkSecurityGroups,omitempty"`
326330
}
327331

cloud/scope/nsg_reconciler.go

Lines changed: 56 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,10 @@ func (s *ClusterScope) ReconcileNSG(ctx context.Context) error {
4949
}
5050
s.Logger.Info("Successfully updated network security list", "nsg", nsgOCID)
5151
}
52-
ingressRules, egressRules, isNSGUpdated, err := s.UpdateNSGSecurityRulesIfNeeded(ctx, *desiredNSG, nsg)
52+
isNSGUpdated, err := s.UpdateNSGSecurityRulesIfNeeded(ctx, *desiredNSG, nsg)
5353
if err != nil {
5454
return err
5555
}
56-
desiredNSG.IngressRules = ingressRules
57-
desiredNSG.EgressRules = egressRules
5856
if !isNSGUpdated {
5957
s.Logger.Info("No Reconciliation Required for Network Security Group", "nsg", *desiredNSG.ID)
6058
}
@@ -67,12 +65,10 @@ func (s *ClusterScope) ReconcileNSG(ctx context.Context) error {
6765
}
6866
s.Logger.Info("Created the nsg", "nsg", nsgID)
6967
desiredNSG.ID = nsgID
70-
ingressRules, egressRules, err := s.AddNSGSecurityRules(ctx, desiredNSG.ID, desiredNSG.IngressRules, desiredNSG.EgressRules)
68+
err = s.AddNSGSecurityRules(ctx, desiredNSG.ID, desiredNSG.IngressRules, desiredNSG.EgressRules)
7169
if err != nil {
7270
return err
7371
}
74-
desiredNSG.IngressRules = ingressRules
75-
desiredNSG.EgressRules = egressRules
7672
}
7773
return nil
7874
}
@@ -184,102 +180,101 @@ func (s *ClusterScope) IsNSGExitsByRole(role infrastructurev1beta1.Role) bool {
184180
return false
185181
}
186182

183+
// IsNSGEqual compares the actual and desired NSG using name/freeform tags and defined tags.
187184
func (s *ClusterScope) IsNSGEqual(actual *core.NetworkSecurityGroup, desired infrastructurev1beta1.NSG) bool {
188185
if *actual.DisplayName != desired.Name {
189186
return false
190187
}
191188
return s.IsTagsEqual(actual.FreeformTags, actual.DefinedTags)
192189
}
193190

191+
// UpdateNSGSecurityRulesIfNeeded updates NSG rules if required by comparing actual and desired.
194192
func (s *ClusterScope) UpdateNSGSecurityRulesIfNeeded(ctx context.Context, desired infrastructurev1beta1.NSG,
195-
actual *core.NetworkSecurityGroup) ([]infrastructurev1beta1.IngressSecurityRuleForNSG, []infrastructurev1beta1.EgressSecurityRuleForNSG, bool, error) {
196-
var ingressRulesToAdd, ingressRulesToUpdate, finalIngressRules []infrastructurev1beta1.IngressSecurityRuleForNSG
197-
var egressRulesToAdd, egressRulesToUpdate, finalEgressRules []infrastructurev1beta1.EgressSecurityRuleForNSG
193+
actual *core.NetworkSecurityGroup) (bool, error) {
194+
var ingressRulesToAdd []infrastructurev1beta1.IngressSecurityRuleForNSG
195+
var egressRulesToAdd []infrastructurev1beta1.EgressSecurityRuleForNSG
198196
var securityRulesToRemove []string
199197
var isNSGUpdated bool
200198
listSecurityRulesResponse, err := s.VCNClient.ListNetworkSecurityGroupSecurityRules(ctx, core.ListNetworkSecurityGroupSecurityRulesRequest{
201199
NetworkSecurityGroupId: actual.Id,
202200
})
203201
if err != nil {
204202
s.Logger.Error(err, "failed to reconcile the network security group, failed to list security rules")
205-
return nil, nil, isNSGUpdated, errors.Wrap(err, "failed to reconcile the network security group, failed to list security rules")
203+
return isNSGUpdated, errors.Wrap(err, "failed to reconcile the network security group, failed to list security rules")
206204
}
207205
ingressRules, egressRules := generateSpecFromSecurityRules(listSecurityRulesResponse.Items)
208206

209207
for i, ingressRule := range desired.IngressRules {
210-
if ingressRule.ID == nil {
211-
ingressRulesToAdd = append(ingressRulesToAdd, ingressRule)
212-
}
213208
if ingressRule.IsStateless == nil {
214209
desired.IngressRules[i].IsStateless = common.Bool(false)
215210
}
216211
}
217212
for i, egressRule := range desired.EgressRules {
218-
if egressRule.ID == nil {
219-
egressRulesToAdd = append(egressRulesToAdd, egressRule)
220-
}
221213
if egressRule.IsStateless == nil {
222214
desired.EgressRules[i].IsStateless = common.Bool(false)
223215
}
224216
}
225217

226-
for _, actualRule := range ingressRules {
218+
for _, desiredRule := range desired.IngressRules {
219+
found := false
220+
for _, actualRule := range ingressRules {
221+
if reflect.DeepEqual(desiredRule, actualRule) {
222+
found = true
223+
break
224+
}
225+
}
226+
if !found {
227+
ingressRulesToAdd = append(ingressRulesToAdd, desiredRule)
228+
}
229+
}
230+
231+
for id, actualRule := range ingressRules {
227232
found := false
228233
for _, desiredRule := range desired.IngressRules {
229-
if (desiredRule.ID != nil) && (*actualRule.ID == *desiredRule.ID) {
234+
if reflect.DeepEqual(desiredRule, actualRule) {
230235
found = true
231-
if !reflect.DeepEqual(desiredRule, actualRule) {
232-
ingressRulesToUpdate = append(ingressRulesToUpdate, desiredRule)
233-
}
234-
finalIngressRules = append(finalIngressRules, desiredRule)
235236
break
236237
}
237238
}
238239
if !found {
239-
securityRulesToRemove = append(securityRulesToRemove, *actualRule.ID)
240+
securityRulesToRemove = append(securityRulesToRemove, id)
240241
}
241242
}
242-
for _, actualRule := range egressRules {
243+
244+
for _, desiredRule := range desired.EgressRules {
245+
found := false
246+
for _, actualRule := range egressRules {
247+
if reflect.DeepEqual(desiredRule, actualRule) {
248+
found = true
249+
break
250+
}
251+
}
252+
if !found {
253+
egressRulesToAdd = append(egressRulesToAdd, desiredRule)
254+
}
255+
}
256+
257+
for id, actualRule := range egressRules {
243258
found := false
244259
for _, desiredRule := range desired.EgressRules {
245-
if (desiredRule.ID != nil) && (*actualRule.ID == *desiredRule.ID) {
260+
if reflect.DeepEqual(desiredRule, actualRule) {
246261
found = true
247-
if !reflect.DeepEqual(desiredRule, actualRule) {
248-
egressRulesToUpdate = append(egressRulesToUpdate, desiredRule)
249-
}
250-
finalEgressRules = append(finalEgressRules, desiredRule)
251262
break
252263
}
253264
}
254265
if !found {
255-
securityRulesToRemove = append(securityRulesToRemove, *actualRule.ID)
266+
securityRulesToRemove = append(securityRulesToRemove, id)
256267
}
257268
}
269+
258270
if len(ingressRulesToAdd) > 0 || len(egressRulesToAdd) > 0 {
259271
isNSGUpdated = true
260-
ingress, egress, err := s.AddNSGSecurityRules(ctx, desired.ID, ingressRulesToAdd, egressRulesToAdd)
272+
err := s.AddNSGSecurityRules(ctx, desired.ID, ingressRulesToAdd, egressRulesToAdd)
261273
if err != nil {
262274
s.Logger.Error(err, "failed to reconcile the network security group, failed to add security rules")
263-
return nil, nil, isNSGUpdated, err
275+
return isNSGUpdated, err
264276
}
265277
s.Logger.Info("Successfully added missing rules in NSG", "nsg", *actual.Id)
266-
finalEgressRules = append(finalEgressRules, egress...)
267-
finalIngressRules = append(finalIngressRules, ingress...)
268-
}
269-
if len(ingressRulesToUpdate) > 0 || len(egressRulesToUpdate) > 0 {
270-
isNSGUpdated = true
271-
securityRules := generateUpdateSecurityRuleFromSpec(ingressRulesToUpdate, egressRulesToUpdate)
272-
_, err := s.VCNClient.UpdateNetworkSecurityGroupSecurityRules(ctx, core.UpdateNetworkSecurityGroupSecurityRulesRequest{
273-
NetworkSecurityGroupId: desired.ID,
274-
UpdateNetworkSecurityGroupSecurityRulesDetails: core.UpdateNetworkSecurityGroupSecurityRulesDetails{
275-
SecurityRules: securityRules,
276-
},
277-
})
278-
if err != nil {
279-
s.Logger.Error(err, "failed to reconcile the network security group, failed to update security rules")
280-
return nil, nil, isNSGUpdated, err
281-
}
282-
s.Logger.Info("Successfully updated rules in NSG", "nsg", *actual.Id)
283278
}
284279
if len(securityRulesToRemove) > 0 {
285280
isNSGUpdated = true
@@ -291,12 +286,11 @@ func (s *ClusterScope) UpdateNSGSecurityRulesIfNeeded(ctx context.Context, desir
291286
})
292287
if err != nil {
293288
s.Logger.Error(err, "failed to reconcile the network security group, failed to remove security rules")
294-
return nil, nil, isNSGUpdated, err
289+
return isNSGUpdated, err
295290
}
296291
s.Logger.Info("Successfully deleted rules in NSG", "nsg", *actual.Id)
297292
}
298-
s.Logger.Info("No Reconciliation Required for Network Security List rules", "nsg", desired.ID)
299-
return finalIngressRules, finalEgressRules, isNSGUpdated, nil
293+
return isNSGUpdated, nil
300294
}
301295

302296
func (s *ClusterScope) UpdateNSG(ctx context.Context, nsgSpec infrastructurev1beta1.NSG) error {
@@ -365,58 +359,9 @@ func generateAddSecurityRuleFromSpec(ingressRules []infrastructurev1beta1.Ingres
365359
return securityRules
366360
}
367361

368-
func generateUpdateSecurityRuleFromSpec(ingressRules []infrastructurev1beta1.IngressSecurityRuleForNSG,
369-
egressRules []infrastructurev1beta1.EgressSecurityRuleForNSG) []core.UpdateSecurityRuleDetails {
370-
var securityRules []core.UpdateSecurityRuleDetails
371-
var icmpOptions *core.IcmpOptions
372-
var tcpOptions *core.TcpOptions
373-
var udpOptions *core.UdpOptions
374-
var stateless *bool
375-
for _, ingressRule := range ingressRules {
376-
icmpOptions, tcpOptions, udpOptions = getProtocolOptions(ingressRule.IcmpOptions, ingressRule.TcpOptions, ingressRule.UdpOptions)
377-
// while comparing values, the boolean value has to be always set
378-
stateless = ingressRule.IsStateless
379-
if stateless == nil {
380-
stateless = common.Bool(false)
381-
}
382-
securityRules = append(securityRules, core.UpdateSecurityRuleDetails{
383-
Direction: core.UpdateSecurityRuleDetailsDirectionIngress,
384-
Id: ingressRule.ID,
385-
Protocol: ingressRule.Protocol,
386-
Description: ingressRule.Description,
387-
IcmpOptions: icmpOptions,
388-
IsStateless: stateless,
389-
Source: ingressRule.Source,
390-
SourceType: core.UpdateSecurityRuleDetailsSourceTypeEnum(ingressRule.SourceType),
391-
TcpOptions: tcpOptions,
392-
UdpOptions: udpOptions,
393-
})
394-
}
395-
for _, egressRule := range egressRules {
396-
icmpOptions, tcpOptions, udpOptions = getProtocolOptions(egressRule.IcmpOptions, egressRule.TcpOptions, egressRule.UdpOptions)
397-
stateless = egressRule.IsStateless
398-
if stateless == nil {
399-
stateless = common.Bool(false)
400-
}
401-
securityRules = append(securityRules, core.UpdateSecurityRuleDetails{
402-
Direction: core.UpdateSecurityRuleDetailsDirectionEgress,
403-
Protocol: egressRule.Protocol,
404-
Description: egressRule.Description,
405-
IcmpOptions: icmpOptions,
406-
IsStateless: stateless,
407-
Destination: egressRule.Destination,
408-
DestinationType: core.UpdateSecurityRuleDetailsDestinationTypeEnum(egressRule.DestinationType),
409-
TcpOptions: tcpOptions,
410-
UdpOptions: udpOptions,
411-
Id: egressRule.ID,
412-
})
413-
}
414-
return securityRules
415-
}
416-
417-
func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev1beta1.IngressSecurityRuleForNSG, []infrastructurev1beta1.EgressSecurityRuleForNSG) {
418-
var ingressRules []infrastructurev1beta1.IngressSecurityRuleForNSG
419-
var egressRules []infrastructurev1beta1.EgressSecurityRuleForNSG
362+
func generateSpecFromSecurityRules(rules []core.SecurityRule) (map[string]infrastructurev1beta1.IngressSecurityRuleForNSG, map[string]infrastructurev1beta1.EgressSecurityRuleForNSG) {
363+
var ingressRules = make(map[string]infrastructurev1beta1.IngressSecurityRuleForNSG)
364+
var egressRules = make(map[string]infrastructurev1beta1.EgressSecurityRuleForNSG)
420365
var stateless *bool
421366
for _, rule := range rules {
422367

@@ -428,7 +373,6 @@ func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev
428373
switch rule.Direction {
429374
case core.SecurityRuleDirectionIngress:
430375
ingressRule := infrastructurev1beta1.IngressSecurityRuleForNSG{
431-
ID: rule.Id,
432376
IngressSecurityRule: infrastructurev1beta1.IngressSecurityRule{
433377
Protocol: rule.Protocol,
434378
Source: rule.Source,
@@ -440,10 +384,9 @@ func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev
440384
Description: rule.Description,
441385
},
442386
}
443-
ingressRules = append(ingressRules, ingressRule)
387+
ingressRules[*rule.Id] = ingressRule
444388
case core.SecurityRuleDirectionEgress:
445389
egressRule := infrastructurev1beta1.EgressSecurityRuleForNSG{
446-
ID: rule.Id,
447390
EgressSecurityRule: infrastructurev1beta1.EgressSecurityRule{
448391
Destination: rule.Destination,
449392
Protocol: rule.Protocol,
@@ -455,30 +398,28 @@ func generateSpecFromSecurityRules(rules []core.SecurityRule) ([]infrastructurev
455398
Description: rule.Description,
456399
},
457400
}
458-
egressRules = append(egressRules, egressRule)
401+
egressRules[*rule.Id] = egressRule
459402
}
460403
}
461404
return ingressRules, egressRules
462405

463406
}
464407

465408
func (s *ClusterScope) AddNSGSecurityRules(ctx context.Context, nsgID *string, ingress []infrastructurev1beta1.IngressSecurityRuleForNSG,
466-
egress []infrastructurev1beta1.EgressSecurityRuleForNSG) ([]infrastructurev1beta1.IngressSecurityRuleForNSG, []infrastructurev1beta1.EgressSecurityRuleForNSG, error) {
409+
egress []infrastructurev1beta1.EgressSecurityRuleForNSG) error {
467410
securityRules := generateAddSecurityRuleFromSpec(ingress, egress)
468411

469-
addNetworkSecurityGroupSecurityRulesResponse, err := s.VCNClient.AddNetworkSecurityGroupSecurityRules(ctx, core.AddNetworkSecurityGroupSecurityRulesRequest{
412+
_, err := s.VCNClient.AddNetworkSecurityGroupSecurityRules(ctx, core.AddNetworkSecurityGroupSecurityRulesRequest{
470413
NetworkSecurityGroupId: nsgID,
471414
AddNetworkSecurityGroupSecurityRulesDetails: core.AddNetworkSecurityGroupSecurityRulesDetails{
472415
SecurityRules: securityRules,
473416
},
474417
})
475418
if err != nil {
476419
s.Logger.Error(err, "failed add nsg security rules")
477-
return nil, nil, errors.Wrap(err, "failed add nsg security rules")
420+
return errors.Wrap(err, "failed add nsg security rules")
478421
}
479-
ingressRules, egressRules := generateSpecFromSecurityRules(addNetworkSecurityGroupSecurityRulesResponse.SecurityRules)
480-
s.Logger.Info("successfully added nsg rules", "nsg", *nsgID)
481-
return ingressRules, egressRules, nil
422+
return nil
482423
}
483424

484425
func (s *ClusterScope) CreateNSG(ctx context.Context, nsg infrastructurev1beta1.NSG) (*string, error) {
@@ -925,7 +866,7 @@ func getProtocolOptionsForSpec(icmp *core.IcmpOptions, tcp *core.TcpOptions, udp
925866
if icmp != nil {
926867
icmpOptions = &infrastructurev1beta1.IcmpOptions{
927868
Type: icmp.Type,
928-
Code: icmp.Type,
869+
Code: icmp.Code,
929870
}
930871
}
931872
if tcp != nil {

0 commit comments

Comments
 (0)