From 8ae319332b7336f86a23e5f199d064fbe4efaaa9 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 5 Aug 2024 19:01:47 +0300 Subject: [PATCH 01/79] updated subcmds --- cmd/subcmds/optimize.go | 21 +++++++++++++++++++++ cmd/subcmds/optimizeACL.go | 22 ++++++++++++++++++++++ cmd/subcmds/optimizeSG.go | 22 ++++++++++++++++++++++ cmd/subcmds/{format.go => outputFormat.go} | 0 cmd/subcmds/root.go | 6 ++---- cmd/subcmds/{synthesis.go => synth.go} | 17 +++++++++++++++++ cmd/subcmds/{acl.go => synthACL.go} | 2 +- cmd/subcmds/{sg.go => synthSG.go} | 2 +- 8 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 cmd/subcmds/optimize.go create mode 100644 cmd/subcmds/optimizeACL.go create mode 100644 cmd/subcmds/optimizeSG.go rename cmd/subcmds/{format.go => outputFormat.go} (100%) rename cmd/subcmds/{synthesis.go => synth.go} (56%) rename cmd/subcmds/{acl.go => synthACL.go} (93%) rename cmd/subcmds/{sg.go => synthSG.go} (92%) diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go new file mode 100644 index 00000000..cf8ec17e --- /dev/null +++ b/cmd/subcmds/optimize.go @@ -0,0 +1,21 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package subcmds + +import "github.com/spf13/cobra" + +func NewOptimizeCommand(args *inArgs) *cobra.Command { + cmd := &cobra.Command{ + Use: "optimize", + Short: "Optimize is not supported yet", + Long: `Optimize is not supported yet`, + } + + cmd.AddCommand(NewOptimizeACLCommand(args)) + cmd.AddCommand(NewOptimizeSGCommand(args)) + + return cmd +} diff --git a/cmd/subcmds/optimizeACL.go b/cmd/subcmds/optimizeACL.go new file mode 100644 index 00000000..beb8e09b --- /dev/null +++ b/cmd/subcmds/optimizeACL.go @@ -0,0 +1,22 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package subcmds + +import "github.com/spf13/cobra" + +func NewOptimizeACLCommand(args *inArgs) *cobra.Command { + cmd := &cobra.Command{ + Use: "acl", + Short: "OptimizeACL is not supported yet", + Long: `OptimizeACL is not supported yet`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + return nil + }, + } + + return cmd +} diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go new file mode 100644 index 00000000..1c903f83 --- /dev/null +++ b/cmd/subcmds/optimizeSG.go @@ -0,0 +1,22 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package subcmds + +import "github.com/spf13/cobra" + +func NewOptimizeSGCommand(args *inArgs) *cobra.Command { + cmd := &cobra.Command{ + Use: "sg", + Short: "OptimizeSG is not supported yet", + Long: `OptimizeSG is not supported yet`, + Args: cobra.NoArgs, + RunE: func(cmd *cobra.Command, _ []string) error { + return nil + }, + } + + return cmd +} diff --git a/cmd/subcmds/format.go b/cmd/subcmds/outputFormat.go similarity index 100% rename from cmd/subcmds/format.go rename to cmd/subcmds/outputFormat.go diff --git a/cmd/subcmds/root.go b/cmd/subcmds/root.go index c4da0da6..6b01f6c1 100644 --- a/cmd/subcmds/root.go +++ b/cmd/subcmds/root.go @@ -55,12 +55,10 @@ func NewRootCommand() *cobra.Command { rootCmd.PersistentFlags().SortFlags = false _ = rootCmd.MarkPersistentFlagRequired(configFlag) - _ = rootCmd.MarkPersistentFlagRequired(specFlag) - rootCmd.MarkFlagsMutuallyExclusive(outputFileFlag, outputDirFlag) - rootCmd.AddCommand(NewACLCommand(args)) - rootCmd.AddCommand(NewSGCommand(args)) + rootCmd.AddCommand(NewSynthCommand(args)) + // Todo: add optimize command rootCmd.CompletionOptions.HiddenDefaultCmd = true rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) // disable help command. should use --help flag instead diff --git a/cmd/subcmds/synthesis.go b/cmd/subcmds/synth.go similarity index 56% rename from cmd/subcmds/synthesis.go rename to cmd/subcmds/synth.go index 8b60ac0f..f9240623 100644 --- a/cmd/subcmds/synthesis.go +++ b/cmd/subcmds/synth.go @@ -12,6 +12,23 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/synth" ) +func NewSynthCommand(args *inArgs) *cobra.Command { + cmd := &cobra.Command{ + Use: "synth", + Short: "generate a SG/nACL collection", + Long: `Generate nACLS or Security Groups to only allow the specified connectivity. + should give spec and defs blah blah blah`, + } + + cmd.PersistentFlags().StringVarP(&args.specFile, specFlag, "s", "", "JSON file containing spec file") + _ = cmd.MarkPersistentFlagRequired(specFlag) + + cmd.AddCommand(NewSynthACLCommand(args)) + cmd.AddCommand(NewSynthSGCommand(args)) + + return cmd +} + func synthesis(cmd *cobra.Command, args *inArgs, newSynthesizer func(*ir.Spec, bool) synth.Synthesizer, single bool) error { cmd.SilenceUsage = true // if we got this far, flags are syntactically correct, so no need to print usage spec, err := unmarshal(args) diff --git a/cmd/subcmds/acl.go b/cmd/subcmds/synthACL.go similarity index 93% rename from cmd/subcmds/acl.go rename to cmd/subcmds/synthACL.go index 8c2a9800..4aee4040 100644 --- a/cmd/subcmds/acl.go +++ b/cmd/subcmds/synthACL.go @@ -11,7 +11,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/synth" ) -func NewACLCommand(args *inArgs) *cobra.Command { +func NewSynthACLCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "acl", Short: "Generate Networks ACLs from connectivity specification", diff --git a/cmd/subcmds/sg.go b/cmd/subcmds/synthSG.go similarity index 92% rename from cmd/subcmds/sg.go rename to cmd/subcmds/synthSG.go index e173e39f..88bb4a56 100644 --- a/cmd/subcmds/sg.go +++ b/cmd/subcmds/synthSG.go @@ -11,7 +11,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/synth" ) -func NewSGCommand(args *inArgs) *cobra.Command { +func NewSynthSGCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "sg", Short: "Generate Security Groups from connectivity specification", From 218781609790f9c69511419838d48dd470764b43 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 5 Aug 2024 19:35:26 +0300 Subject: [PATCH 02/79] readme --- README.md | 10 +++++----- cmd/subcmds/root.go | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 09c282dc..382add3f 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ Multi-vpc input is supported. Required connections cannot cross vpc boundaries. ## Usage Use the `vpcgen` CLI tool with one of the following commands to specify the type of network resources to generate. -* `vpcgen sg` - generate Security Groups. -* `vpcgen acl` - generate an nACL for each subnet separately. -* `vpcgen acl --single` - generate a single nACL for all subnets in the same VPC. +* `vpcgen synth sg` - generate Security Groups. +* `vpcgen synth acl` - generate an nACL for each subnet separately. +* `vpcgen synth acl --single` - generate a single nACL for all subnets in the same VPC. ### nACLs Generation Specifying the `--single` flag results in generating a single nACL for all subnets in the same VPC. Otherwise, an nACL is generated for each subnet separately. @@ -55,9 +55,9 @@ make build ## Run an example ```commandline -bin/vpcgen acl -c test/data/acl_testing5/config_object.json -s test/data/acl_testing5/conn_spec.json +bin/vpcgen synth acl -c test/data/acl_testing5/config_object.json -s test/data/acl_testing5/conn_spec.json -bin/vpcgen sg -c test/data/sg_testing3/config_object.json -s test/data/sg_testing3/conn_spec.json +bin/vpcgen synth sg -c test/data/sg_testing3/config_object.json -s test/data/sg_testing3/conn_spec.json ``` **Note**: Windows environment users should replace all `/` with `\`. \ No newline at end of file diff --git a/cmd/subcmds/root.go b/cmd/subcmds/root.go index 6b01f6c1..8c1b6dc5 100644 --- a/cmd/subcmds/root.go +++ b/cmd/subcmds/root.go @@ -44,7 +44,6 @@ func NewRootCommand() *cobra.Command { } rootCmd.PersistentFlags().StringVarP(&args.configFile, configFlag, "c", "", "JSON file containing config spec") - rootCmd.PersistentFlags().StringVarP(&args.specFile, specFlag, "s", "", "JSON file containing spec file") rootCmd.PersistentFlags().StringVarP(&args.outputFmt, outputFmtFlag, "f", "", "Output format; "+mustBeOneOf(outputFormats)) rootCmd.PersistentFlags().StringVarP(&args.outputFile, outputFileFlag, "o", "", "Write all generated resources to the specified file.") rootCmd.PersistentFlags().StringVarP(&args.outputDir, outputDirFlag, "d", "", From 851e02caf6317876d27a41cfa67ce88fcd0fcfac Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 6 Aug 2024 17:17:46 +0300 Subject: [PATCH 03/79] generic --- go.mod | 8 ++ go.sum | 4 +- pkg/io/confio/acl.go | 11 +- pkg/io/confio/conversions.go | 25 +++-- pkg/io/confio/read_defs.go | 14 +-- pkg/io/confio/sg.go | 13 ++- pkg/io/csvio/acl.go | 22 ++-- pkg/io/csvio/common.go | 24 ++-- pkg/io/csvio/sg.go | 26 +++-- pkg/io/jsonio/unmarshal.go | 32 +++--- pkg/io/mdio/acl.go | 22 ++-- pkg/io/mdio/common.go | 24 ++-- pkg/io/mdio/sg.go | 26 +++-- pkg/io/tfio/acl.go | 17 +-- pkg/io/tfio/common.go | 15 ++- pkg/io/tfio/sg.go | 20 ++-- pkg/ir/acl.go | 11 +- pkg/ir/common.go | 9 -- pkg/ir/icmp.go | 105 ------------------ pkg/ir/packet.go | 33 +++--- pkg/ir/sg.go | 6 +- pkg/ir/spec.go | 54 +++++---- pkg/ir/tcpudp.go | 51 --------- pkg/synth/acl.go | 14 +-- pkg/synth/common.go | 4 +- test/data/acl_nif/nacl_expected.tf | 4 - test/data/acl_testing5/nacl_expected.csv | 16 +-- test/data/acl_testing5/nacl_expected.json | 8 -- test/data/acl_testing5/nacl_expected.tf | 8 -- .../acl_testing5/nacl_single_expected.csv | 16 +-- .../acl_testing5/nacl_single_expected.json | 8 -- .../data/acl_testing5/nacl_single_expected.tf | 8 -- test/data/acl_tg_multiple/nacl_expected.json | 8 -- test/data/acl_tg_multiple/nacl_expected.tf | 8 -- .../acl_tg_multiple/nacl_single_expected.tf | 8 -- test/data/acl_tg_multiple/single_test-vpc0.tf | 4 - test/data/acl_tg_multiple/single_test-vpc1.tf | 4 - test/data/acl_tg_multiple/test-vpc0.tf | 4 - test/data/acl_tg_multiple/test-vpc1.tf | 4 - test/data/sg_testing3/sg_expected.csv | 4 +- test/data/sg_tg_multiple/sg_expected.csv | 4 +- test/data/sg_tg_multiple/test-vpc2.csv | 4 +- 42 files changed, 257 insertions(+), 453 deletions(-) delete mode 100644 pkg/ir/icmp.go delete mode 100644 pkg/ir/tcpudp.go diff --git a/go.mod b/go.mod index 4b80005f..25ea19a4 100644 --- a/go.mod +++ b/go.mod @@ -36,3 +36,11 @@ require ( golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) + +// Todo: +// (1) delete the following line when np-guard/models#33 is merged. +// (2) replace lines 137 and 138 in go.sum with +// github.com/np-guard/models v0.3.4 h1:HOhVi6wyGvo+KmYBnQ5Km5HYCF+/PQlDs1v7mL1v05g= +// github.com/np-guard/models v0.3.4/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= +//nolint:gomoddirectives // this line is temporary +replace github.com/np-guard/models => github.com/np-guard/models v0.3.5-0.20240708150421-8d8e4354057d \ No newline at end of file diff --git a/go.sum b/go.sum index de492d00..fd6bc3e4 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/np-guard/cloud-resource-collector v0.13.0 h1:gjfeGsVYNfWxbsSvkVq4QVtLlrD7ekNUzmb1o7uautw= github.com/np-guard/cloud-resource-collector v0.13.0/go.mod h1:80MUWGvDwN+wt154xgJOAEOGEC12AFJJrlXMvvQwRHw= -github.com/np-guard/models v0.3.4 h1:HOhVi6wyGvo+KmYBnQ5Km5HYCF+/PQlDs1v7mL1v05g= -github.com/np-guard/models v0.3.4/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= +github.com/np-guard/models v0.3.5-0.20240708150421-8d8e4354057d h1:yAmG3W8kUl0GC84dRWcgRK9lBWRkwJkwLnUtwoh1lIY= +github.com/np-guard/models v0.3.5-0.20240708150421-8d8e4354057d/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/pkg/io/confio/acl.go b/pkg/io/confio/acl.go index 095647eb..20f06d1a 100644 --- a/pkg/io/confio/acl.go +++ b/pkg/io/confio/acl.go @@ -12,13 +12,14 @@ import ( "github.com/IBM/vpc-go-sdk/vpcv1" configModel "github.com/np-guard/cloud-resource-collector/pkg/ibm/datamodel" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) -func cidr(address *ipblock.IPBlock) *string { +func cidr(address *netset.IPBlock) *string { return utils.Ptr(address.ToCidrListString()) } @@ -30,7 +31,7 @@ func makeACLRuleItem(rule *ir.ACLRule, current, source := cidr(rule.Source) destination := cidr(rule.Destination) switch p := rule.Protocol.(type) { - case ir.TCPUDP: + case netp.TCPUDP: data := tcpudp(p) result := &vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolTcpudp{ Href: current.Href, @@ -50,7 +51,7 @@ func makeACLRuleItem(rule *ir.ACLRule, current, DestinationPortMax: data.DestinationPortMax, } return result - case ir.ICMP: + case netp.ICMP: data := icmp(p) result := &vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolIcmp{ Href: current.Href, @@ -68,7 +69,7 @@ func makeACLRuleItem(rule *ir.ACLRule, current, Code: data.Code, } return result - case ir.AnyProtocol: + case netp.AnyProtocol: data := all() result := &vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolAll{ Href: current.Href, diff --git a/pkg/io/confio/conversions.go b/pkg/io/confio/conversions.go index 9a617c25..6ef6733b 100644 --- a/pkg/io/confio/conversions.go +++ b/pkg/io/confio/conversions.go @@ -11,6 +11,9 @@ import ( "github.com/IBM/vpc-go-sdk/vpcv1" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) @@ -62,12 +65,12 @@ func direction(d ir.Direction) *string { return nil } -func minPort(r ir.PortRange) *int64 { - return utils.Ptr(int64(r.Min)) +func minPort(r interval.Interval) *int64 { + return utils.Ptr(r.Start()) } -func maxPort(r ir.PortRange) *int64 { - return utils.Ptr(int64(r.Max)) +func maxPort(r interval.Interval) *int64 { + return utils.Ptr(r.End()) } type tcpudpData struct { @@ -102,10 +105,10 @@ type allData struct { Protocol *string } -func tcpudp(p ir.TCPUDP) tcpudpData { +func tcpudp(p netp.TCPUDP) tcpudpData { r := p.PortRangePair res := tcpudpData{ - Protocol: utils.Ptr(strings.ToLower(string(p.Protocol))), + Protocol: utils.Ptr(strings.ToLower(string(p.ProtocolString()))), SourcePortMin: minPort(r.SrcPort), SourcePortMax: maxPort(r.SrcPort), DestinationPortMin: minPort(r.DstPort), @@ -114,13 +117,15 @@ func tcpudp(p ir.TCPUDP) tcpudpData { return res } -func icmp(p ir.ICMP) icmpData { +func icmp(p netp.ICMP) icmpData { res := icmpData{ Protocol: utils.Ptr(icmpConst), - Type: utils.Ptr(int64(p.Type)), } - if p.Code != nil { - res.Code = utils.Ptr(int64(*p.Code)) + if p.TypeCode != nil { + res.Type = utils.Ptr(int64(p.TypeCode.Type)) + if p.TypeCode.Code != nil { + res.Code = utils.Ptr(int64(*p.TypeCode.Code)) + } } return res } diff --git a/pkg/io/confio/read_defs.go b/pkg/io/confio/read_defs.go index 5c1c580d..c2fc03b8 100644 --- a/pkg/io/confio/read_defs.go +++ b/pkg/io/confio/read_defs.go @@ -14,7 +14,7 @@ import ( configModel "github.com/np-guard/cloud-resource-collector/pkg/ibm/datamodel" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -74,9 +74,9 @@ func ReadDefs(filename string) (*ir.ConfigDefs, error) { func parseVPCs(config *configModel.ResourcesContainerModel) (map[ir.ID]*ir.VPCDetails, error) { VPCs := make(map[ir.ID]*ir.VPCDetails, len(config.VpcList)) for _, vpc := range config.VpcList { - addressPrefixes := ipblock.New() + addressPrefixes := netset.NewIPBlock() for _, addressPrefix := range vpc.AddressPrefixes { - address, err := ipblock.FromCidr(*addressPrefix.CIDR) + address, err := netset.IPBlockFromCidr(*addressPrefix.CIDR) if err != nil { return nil, err } @@ -91,7 +91,7 @@ func parseSubnets(config *configModel.ResourcesContainerModel) (map[ir.ID]*ir.Su subnets := make(map[ir.ID]*ir.SubnetDetails, len(config.SubnetList)) for _, subnet := range config.SubnetList { uniqueName := ScopingString(*subnet.VPC.Name, *subnet.Name) - cidr, err := ipblock.FromCidr(*subnet.Ipv4CIDRBlock) + cidr, err := netset.IPBlockFromCidr(*subnet.Ipv4CIDRBlock) if err != nil { return nil, err } @@ -114,7 +114,7 @@ func parseInstancesNifs(config *configModel.ResourcesContainerModel) (instances instanceNifs := make([]ir.ID, len(instance.NetworkInterfaces)) for i := range instance.NetworkInterfaces { nifUniqueName := ScopingString(instanceUniqueName, *instance.NetworkInterfaces[i].Name) - nifIP, err := ipblock.FromIPAddress(*instance.NetworkInterfaces[i].PrimaryIP.Address) + nifIP, err := netset.IPBlockFromIPAddress(*instance.NetworkInterfaces[i].PrimaryIP.Address) if err != nil { return nil, nil, err } @@ -164,7 +164,7 @@ func parseVPEs(config *configModel.ResourcesContainerModel) (vpes map[ir.ID]*ir. VPEName := ScopingString(*subnet.VPC.Name, *t.Name) subnetName := ScopingString(*subnet.VPC.Name, *subnet.Name) uniqueVpeReservedIPName := ScopingString(VPEName, *r.Name) - vpeIP, err := ipblock.FromIPAddress(*r.Address) + vpeIP, err := netset.IPBlockFromIPAddress(*r.Address) if err != nil { return nil, nil, err } @@ -190,7 +190,7 @@ func validateVpcs(vpcs map[ir.ID]*ir.VPCDetails) error { if vpcName1 >= vpcName2 { continue } - if vpcDetails1.AddressPrefixes.Overlap(vpcDetails2.AddressPrefixes) { + if ir.Overlap(vpcDetails1.AddressPrefixes, vpcDetails2.AddressPrefixes) { return fmt.Errorf("vpcs %s and %s have overlapping IP address spaces", vpcName1, vpcName2) } } diff --git a/pkg/io/confio/sg.go b/pkg/io/confio/sg.go index fdd4b561..d9157cb2 100644 --- a/pkg/io/confio/sg.go +++ b/pkg/io/confio/sg.go @@ -12,7 +12,8 @@ import ( "github.com/IBM/vpc-go-sdk/vpcv1" configModel "github.com/np-guard/cloud-resource-collector/pkg/ibm/datamodel" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" @@ -51,7 +52,7 @@ func sgRemote(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteSecurit rule *ir.SGRule) vpcv1.SecurityGroupRuleRemoteIntf { st := rule.Remote.String() switch t := rule.Remote.(type) { - case *ipblock.IPBlock: + case *netset.IPBlock: if ir.IsIPAddress(t) { return &vpcv1.SecurityGroupRuleRemoteIP{ Address: &st, @@ -70,7 +71,7 @@ func makeSGRuleItem(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteS rule *ir.SGRule, i int) vpcv1.SecurityGroupRuleIntf { iPVersion := utils.Ptr(ipv4Const) direction := direction(rule.Direction) - cidrAll := ipblock.CidrAll + cidrAll := netset.CidrAll local := &vpcv1.SecurityGroupRuleLocal{ CIDRBlock: &cidrAll, } @@ -78,7 +79,7 @@ func makeSGRuleItem(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteS remote := sgRemote(nameToSGRemoteRef, rule) switch p := rule.Protocol.(type) { - case ir.TCPUDP: + case netp.TCPUDP: data := tcpudp(p) return &vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp{ Direction: direction, @@ -91,7 +92,7 @@ func makeSGRuleItem(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteS PortMin: data.remotePortMin(rule.Direction), PortMax: data.remotePortMax(rule.Direction), } - case ir.ICMP: + case netp.ICMP: data := icmp(p) return &vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp{ Direction: direction, @@ -104,7 +105,7 @@ func makeSGRuleItem(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteS Type: data.Type, Code: data.Code, } - case ir.AnyProtocol: + case netp.AnyProtocol: data := all() return &vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll{ Direction: direction, diff --git a/pkg/io/csvio/acl.go b/pkg/io/csvio/acl.go index 728caf9f..792f943e 100644 --- a/pkg/io/csvio/acl.go +++ b/pkg/io/csvio/acl.go @@ -10,7 +10,9 @@ import ( "log" "strconv" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -24,12 +26,12 @@ func makeACLTable(t *ir.ACL, subnet string) [][]string { return rows } -func ACLPort(p ir.PortRange) string { +func ACLPort(p interval.Interval) string { switch { - case p.Min == ir.DefaultMinPort && p.Max == ir.DefaultMaxPort: + case p.Start() == netp.MinPort && p.End() == netp.MaxPort: return "any port" //nolint:goconst // independent decision for SG and ACL default: - return fmt.Sprintf("ports %v-%v", p.Min, p.Max) + return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) } } @@ -84,23 +86,23 @@ func makeACLRow(priority int, rule *ir.ACLRule, aclName, subnet string) []string } } -func printIP(ip *ipblock.IPBlock, protocol ir.Protocol, isSource bool) string { +func printIP(ip *netset.IPBlock, protocol netp.Protocol, isSource bool) string { ipString := ip.String() - if ip.Equal(ipblock.GetCidrAll()) { + if ip.Equal(netset.GetCidrAll()) { ipString = "Any IP" //nolint:goconst // independent decision for SG and ACL } switch p := protocol.(type) { - case ir.ICMP: + case netp.ICMP: return ipString - case ir.TCPUDP: - var r ir.PortRange + case netp.TCPUDP: + var r interval.Interval if isSource { r = p.PortRangePair.SrcPort } else { r = p.PortRangePair.DstPort } return fmt.Sprintf("%v, %v", ipString, ACLPort(r)) - case ir.AnyProtocol: + case netp.AnyProtocol: return ipString default: log.Panicf("Impossible protocol %v", p) diff --git a/pkg/io/csvio/common.go b/pkg/io/csvio/common.go index 4302526c..41cd664d 100644 --- a/pkg/io/csvio/common.go +++ b/pkg/io/csvio/common.go @@ -13,6 +13,8 @@ import ( "strconv" "strings" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -38,29 +40,29 @@ func direction(d ir.Direction) string { return "Outbound" } -func printICMPTypeCode(protocol ir.Protocol) string { - p, ok := protocol.(ir.ICMP) +func printICMPTypeCode(protocol netp.Protocol) string { + p, ok := protocol.(netp.ICMP) if !ok { return nonIcmp } icmpType := anyIcmpValue icmpCode := anyIcmpValue - if p.ICMPCodeType != nil { - icmpType = strconv.Itoa(p.Type) - if p.Code != nil { - icmpCode = strconv.Itoa(*p.Code) + if typeCode := p.ICMPTypeCode(); typeCode != nil { + icmpType = strconv.Itoa(typeCode.Type) + if typeCode.Code != nil { + icmpCode = strconv.Itoa(*typeCode.Code) } } return fmt.Sprintf("Type: %v, Code: %v", icmpType, icmpCode) } -func printProtocolName(protocol ir.Protocol) string { +func printProtocolName(protocol netp.Protocol) string { switch p := protocol.(type) { - case ir.ICMP: + case netp.ICMP: return "ICMP" - case ir.TCPUDP: - return strings.ToUpper(string(p.Protocol)) - case ir.AnyProtocol: + case netp.TCPUDP: + return strings.ToUpper(string(p.ProtocolString())) + case netp.AnyProtocol: return anyProtocol } return "" diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index a83ab41d..2e438ec1 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -9,7 +9,9 @@ import ( "fmt" "log" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -60,18 +62,18 @@ func makeSGTable(t *ir.SG, sgName ir.SGName) [][]string { return rows } -func sGPort(p ir.PortRange) string { +func sGPort(p interval.Interval) string { switch { - case p.Min == ir.DefaultMinPort && p.Max == ir.DefaultMaxPort: + case p.Start() == netp.MinPort && p.End() == netp.MaxPort: return "any port" default: - return fmt.Sprintf("Ports %v-%v", p.Min, p.Max) + return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) } } func sGRemoteType(t ir.RemoteType) string { switch tr := t.(type) { - case *ipblock.IPBlock: + case *netset.IPBlock: if ir.IsIPAddress(tr) { return "IP address" } @@ -85,9 +87,9 @@ func sGRemoteType(t ir.RemoteType) string { func sgRemote(r ir.RemoteType) string { switch tr := r.(type) { - case *ipblock.IPBlock: + case *netset.IPBlock: s := tr.String() - if s == ipblock.CidrAll { + if s == netset.CidrAll { return "Any IP" } return s @@ -99,19 +101,19 @@ func sgRemote(r ir.RemoteType) string { return "" } -func printProtocolParams(protocol ir.Protocol, isSource bool) string { +func printProtocolParams(protocol netp.Protocol, isSource bool) string { switch p := protocol.(type) { - case ir.ICMP: + case netp.ICMP: return printICMPTypeCode(protocol) - case ir.TCPUDP: - var r ir.PortRange + case netp.TCPUDP: + var r interval.Interval if isSource { r = p.PortRangePair.SrcPort } else { r = p.PortRangePair.DstPort } return sGPort(r) - case ir.AnyProtocol: + case netp.AnyProtocol: return "" default: log.Panicf("Impossible protocol %v", p) diff --git a/pkg/io/jsonio/unmarshal.go b/pkg/io/jsonio/unmarshal.go index 7422e7a4..87a843cc 100644 --- a/pkg/io/jsonio/unmarshal.go +++ b/pkg/io/jsonio/unmarshal.go @@ -11,7 +11,9 @@ import ( "fmt" "os" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/models/pkg/spec" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" @@ -109,9 +111,9 @@ func parseCidrSegments(jsonSegments spec.SpecSegments, configDefs *ir.ConfigDefs result := make(map[ir.ID]*ir.CidrSegmentDetails) for segmentName, segment := range cidrSegments { // each cidr saves the contained subnets - segmentMap := make(map[*ipblock.IPBlock]ir.CIDRDetails) + segmentMap := make(map[*netset.IPBlock]ir.CIDRDetails) for _, cidr := range segment { - c, err := ipblock.FromCidr(cidr) + c, err := netset.IPBlockFromCidr(cidr) if err != nil { return nil, err } @@ -137,7 +139,7 @@ func parseCidrSegments(jsonSegments spec.SpecSegments, configDefs *ir.ConfigDefs func translateExternals(m map[string]string) (map[ir.ID]*ir.ExternalDetails, error) { result := make(map[ir.ID]*ir.ExternalDetails) for k, v := range m { - address, err := ipblock.FromCidrOrAddress(v) + address, err := netset.IPBlockFromCidrOrAddress(v) if err != nil { return nil, err } @@ -261,26 +263,26 @@ func translateProtocols(protocols spec.ProtocolList) ([]ir.TrackedProtocol, erro if len(protocols) != 1 { return nil, fmt.Errorf("when allowing any protocol, no more protocols can be defined") } - result[i].Protocol = ir.AnyProtocol{} + result[i].Protocol = netp.AnyProtocol{} case spec.Icmp: if p.Type == nil { if p.Code != nil { return nil, fmt.Errorf("defining ICMP code for unspecified ICMP type is not allowed") } - result[i].Protocol = ir.TrackedProtocol{Protocol: ir.ICMP{}} + result[i].Protocol = ir.TrackedProtocol{Protocol: netp.ICMP{}} } else { - err := ir.ValidateICMP(*p.Type, *p.Code) + icmp, err := netp.ICMPFromTypeAndCode(p.Type, p.Code) if err != nil { return nil, err } - result[i].Protocol = ir.ICMP{ICMPCodeType: &ir.ICMPCodeType{Type: *p.Type, Code: p.Code}} + result[i].Protocol = icmp } case spec.TcpUdp: - result[i].Protocol = ir.TCPUDP{ - Protocol: ir.TransportLayerProtocolName(p.Protocol), - PortRangePair: ir.PortRangePair{ - SrcPort: ir.PortRange{Min: p.MinSourcePort, Max: p.MaxSourcePort}, - DstPort: ir.PortRange{Min: p.MinDestinationPort, Max: p.MaxDestinationPort}, + result[i].Protocol = netp.TCPUDP{ + IsTCP: p.Protocol == spec.TcpUdpProtocolTCP, + PortRangePair: netp.PortRangePair{ + SrcPort: interval.New(int64(p.MinSourcePort), int64(p.MaxSourcePort)), + DstPort: interval.New(int64(p.MinDestinationPort), int64(p.MaxDestinationPort)), }, } default: @@ -356,10 +358,10 @@ func unmarshal(filename string) (*spec.Spec, error) { return jsonSpec, err } -func parseOverlappingVpcs(cidr *ipblock.IPBlock, vpcs map[ir.ID]*ir.VPCDetails) []ir.ID { +func parseOverlappingVpcs(cidr *netset.IPBlock, vpcs map[ir.ID]*ir.VPCDetails) []ir.ID { result := make([]ir.ID, 0) for vpcName, vpcDetails := range vpcs { - if vpcDetails.AddressPrefixes.Overlap(cidr) { + if ir.Overlap(vpcDetails.AddressPrefixes, cidr) { result = append(result, vpcName) } } diff --git a/pkg/io/mdio/acl.go b/pkg/io/mdio/acl.go index 11f693c6..18c010e7 100644 --- a/pkg/io/mdio/acl.go +++ b/pkg/io/mdio/acl.go @@ -10,7 +10,9 @@ import ( "log" "strconv" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -24,12 +26,12 @@ func makeACLTable(t *ir.ACL, subnet string) [][]string { return rows } -func ACLPort(p ir.PortRange) string { +func ACLPort(p interval.Interval) string { switch { - case p.Min == ir.DefaultMinPort && p.Max == ir.DefaultMaxPort: + case p.Start() == netp.MinPort && p.End() == netp.MaxPort: return "any port" //nolint:goconst // independent decision for SG and ACL default: - return fmt.Sprintf("ports %v-%v", p.Min, p.Max) + return fmt.Sprintf("ports %v", p) } } @@ -101,23 +103,23 @@ func makeACLRow(priority int, rule *ir.ACLRule, aclName, subnet string) []string } } -func printIP(ip *ipblock.IPBlock, protocol ir.Protocol, isSource bool) string { +func printIP(ip *netset.IPBlock, protocol netp.Protocol, isSource bool) string { ipString := ip.String() - if ip.Equal(ipblock.GetCidrAll()) { + if ip.Equal(netset.GetCidrAll()) { ipString = "Any IP" //nolint:goconst // independent decision for SG and ACL } switch p := protocol.(type) { - case ir.ICMP: + case netp.ICMP: return ipString - case ir.TCPUDP: - var r ir.PortRange + case netp.TCPUDP: + var r interval.Interval if isSource { r = p.PortRangePair.SrcPort } else { r = p.PortRangePair.DstPort } return fmt.Sprintf("%v, %v", ipString, ACLPort(r)) - case ir.AnyProtocol: + case netp.AnyProtocol: return ipString default: log.Panicf("Impossible protocol %v", p) diff --git a/pkg/io/mdio/common.go b/pkg/io/mdio/common.go index 5aa6aa41..abfb24a8 100644 --- a/pkg/io/mdio/common.go +++ b/pkg/io/mdio/common.go @@ -13,6 +13,8 @@ import ( "strconv" "strings" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -51,29 +53,29 @@ func direction(d ir.Direction) string { return "Outbound" } -func printICMPTypeCode(protocol ir.Protocol) string { - p, ok := protocol.(ir.ICMP) +func printICMPTypeCode(protocol netp.Protocol) string { + p, ok := protocol.(netp.ICMP) if !ok { return nonIcmp } icmpType := anyIcmpValue icmpCode := anyIcmpValue - if p.ICMPCodeType != nil { - icmpType = strconv.Itoa(p.Type) - if p.Code != nil { - icmpCode = strconv.Itoa(*p.Code) + if typeCode := p.ICMPTypeCode(); typeCode != nil { + icmpType = strconv.Itoa(typeCode.Type) + if typeCode.Code != nil { + icmpCode = strconv.Itoa(*typeCode.Code) } } return fmt.Sprintf("Type: %v, Code: %v", icmpType, icmpCode) } -func printProtocolName(protocol ir.Protocol) string { +func printProtocolName(protocol netp.Protocol) string { switch p := protocol.(type) { - case ir.ICMP: + case netp.ICMP: return "ICMP" - case ir.TCPUDP: - return strings.ToUpper(string(p.Protocol)) - case ir.AnyProtocol: + case netp.TCPUDP: + return strings.ToUpper(string(p.ProtocolString())) + case netp.AnyProtocol: return anyProtocol } return "" diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index 5a59c3fd..aea44185 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -9,7 +9,9 @@ import ( "fmt" "log" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -74,18 +76,18 @@ func makeSGTable(t *ir.SG, sgName ir.SGName) [][]string { return rows } -func sGPort(p ir.PortRange) string { +func sGPort(p interval.Interval) string { switch { - case p.Min == ir.DefaultMinPort && p.Max == ir.DefaultMaxPort: + case p.Start() == netp.MinPort && p.End() == netp.MaxPort: return "any port" default: - return fmt.Sprintf("Ports %v-%v", p.Min, p.Max) + return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) } } func sGRemoteType(t ir.RemoteType) string { switch tr := t.(type) { - case *ipblock.IPBlock: + case *netset.IPBlock: if ir.IsIPAddress(tr) { return "IP address" } @@ -99,9 +101,9 @@ func sGRemoteType(t ir.RemoteType) string { func sgRemote(r ir.RemoteType) string { switch tr := r.(type) { - case *ipblock.IPBlock: + case *netset.IPBlock: s := tr.String() - if s == ipblock.CidrAll { + if s == netset.CidrAll { return "Any IP" } return s @@ -113,19 +115,19 @@ func sgRemote(r ir.RemoteType) string { return "" } -func printProtocolParams(protocol ir.Protocol, isSource bool) string { +func printProtocolParams(protocol netp.Protocol, isSource bool) string { switch p := protocol.(type) { - case ir.ICMP: + case netp.ICMP: return printICMPTypeCode(protocol) - case ir.TCPUDP: - var r ir.PortRange + case netp.TCPUDP: + var r interval.Interval if isSource { r = p.PortRangePair.SrcPort } else { r = p.PortRangePair.DstPort } return sGPort(r) - case ir.AnyProtocol: + case netp.AnyProtocol: return "" default: log.Panicf("Impossible protocol %v", p) diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index 9106f392..e3427b1c 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -10,7 +10,8 @@ import ( "fmt" "strings" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio/tf" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" @@ -27,22 +28,22 @@ func (w *Writer) WriteACL(c *ir.ACLCollection, vpc string) error { return err } -func aclProtocol(t ir.Protocol) []tf.Block { +func aclProtocol(t netp.Protocol) []tf.Block { switch p := t.(type) { - case ir.TCPUDP: + case netp.TCPUDP: return []tf.Block{{ - Name: strings.ToLower(string(p.Protocol)), + Name: strings.ToLower(string(p.ProtocolString())), Arguments: append( portRange(p.PortRangePair.DstPort, "port"), portRange(p.PortRangePair.SrcPort, "source_port")..., ), }} - case ir.ICMP: + case netp.ICMP: return []tf.Block{{ Name: "icmp", - Arguments: codeTypeArguments(p.ICMPCodeType), + Arguments: codeTypeArguments(p.ICMPTypeCode()), }} - case ir.AnyProtocol: + case netp.AnyProtocol: return []tf.Block{} } return nil @@ -102,7 +103,7 @@ func aclCollection(t *ir.ACLCollection, vpc string) *tf.ConfigFile { } } -func subnetCidr(acl *ir.ACL) *ipblock.IPBlock { +func subnetCidr(acl *ir.ACL) *netset.IPBlock { if len(acl.Internal) > 0 { return acl.Internal[0].Target() } diff --git a/pkg/io/tfio/common.go b/pkg/io/tfio/common.go index 42a0dcfd..00b9d2b7 100644 --- a/pkg/io/tfio/common.go +++ b/pkg/io/tfio/common.go @@ -14,6 +14,9 @@ import ( "regexp" "strconv" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio/tf" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -27,18 +30,18 @@ func NewWriter(w io.Writer) *Writer { return &Writer{w: bufio.NewWriter(w)} } -func portRange(r ir.PortRange, prefix string) []tf.Argument { +func portRange(r interval.Interval, prefix string) []tf.Argument { var arguments []tf.Argument - if r.Min != ir.DefaultMinPort { - arguments = append(arguments, tf.Argument{Name: prefix + "_min", Value: strconv.Itoa(r.Min)}) + if r.Start() != netp.MinPort { + arguments = append(arguments, tf.Argument{Name: prefix + "_min", Value: strconv.Itoa(int(r.Start()))}) } - if r.Max != ir.DefaultMaxPort { - arguments = append(arguments, tf.Argument{Name: prefix + "_max", Value: strconv.Itoa(r.Max)}) + if r.End() != netp.MaxPort { + arguments = append(arguments, tf.Argument{Name: prefix + "_max", Value: strconv.Itoa(int(r.End()))}) } return arguments } -func codeTypeArguments(ct *ir.ICMPCodeType) []tf.Argument { +func codeTypeArguments(ct *netp.ICMPTypeCode) []tf.Argument { var arguments []tf.Argument if ct != nil { arguments = append(arguments, tf.Argument{Name: "type", Value: strconv.Itoa(ct.Type)}) diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index b23df0e1..7ad0aa29 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -10,7 +10,9 @@ import ( "log" "strings" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio/tf" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" @@ -29,7 +31,7 @@ func (w *Writer) WriteSG(c *ir.SGCollection, vpc string) error { func value(x interface{}) string { switch v := x.(type) { - case *ipblock.IPBlock: + case *netset.IPBlock: return quote(v.String()) case ir.SGName: return ir.ChangeScoping(fmt.Sprintf("ibm_is_security_group.%v.id", v)) @@ -39,25 +41,25 @@ func value(x interface{}) string { return "" } -func sgProtocol(t ir.Protocol, d ir.Direction) []tf.Block { +func sgProtocol(t netp.Protocol, d ir.Direction) []tf.Block { switch p := t.(type) { - case ir.TCPUDP: - var remotePort ir.PortRange + case netp.TCPUDP: + var remotePort interval.Interval if d == ir.Inbound { remotePort = p.PortRangePair.SrcPort } else { remotePort = p.PortRangePair.DstPort } return []tf.Block{{ - Name: strings.ToLower(string(p.Protocol)), + Name: strings.ToLower(string(p.ProtocolString())), Arguments: portRange(remotePort, "port"), }} - case ir.ICMP: + case netp.ICMP: return []tf.Block{{ Name: "icmp", - Arguments: codeTypeArguments(p.ICMPCodeType), + Arguments: codeTypeArguments(p.ICMPTypeCode()), }} - case ir.AnyProtocol: + case netp.AnyProtocol: return []tf.Block{} } return nil diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 7b2de229..cf6ed062 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -9,7 +9,8 @@ import ( "fmt" "reflect" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) @@ -24,9 +25,9 @@ const ( type ACLRule struct { Action Action Direction Direction - Source *ipblock.IPBlock - Destination *ipblock.IPBlock - Protocol Protocol + Source *netset.IPBlock + Destination *netset.IPBlock + Protocol netp.Protocol Explanation string } @@ -61,7 +62,7 @@ func (r *ACLRule) mustSupersede(other *ACLRule) bool { return res } -func (r *ACLRule) Target() *ipblock.IPBlock { +func (r *ACLRule) Target() *netset.IPBlock { if r.Direction == Inbound { return r.Destination } diff --git a/pkg/ir/common.go b/pkg/ir/common.go index 64ac7072..e10b1265 100644 --- a/pkg/ir/common.go +++ b/pkg/ir/common.go @@ -12,15 +12,6 @@ const ( Inbound Direction = "inbound" ) -type Protocol interface { - // InverseDirection returns the response expected for a request made using this protocol - InverseDirection() Protocol -} - -type AnyProtocol struct{} - -func (t AnyProtocol) InverseDirection() Protocol { return AnyProtocol{} } - type Writer interface { ACLWriter SGWriter diff --git a/pkg/ir/icmp.go b/pkg/ir/icmp.go deleted file mode 100644 index 903538bc..00000000 --- a/pkg/ir/icmp.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package ir - -import ( - "fmt" - "log" - "slices" -) - -type ICMPCodeType struct { - // ICMP type allowed. - Type int - - // ICMP code allowed. If omitted, any code is allowed - Code *int -} - -type ICMP struct { - *ICMPCodeType -} - -func (t ICMP) InverseDirection() Protocol { - if t.ICMPCodeType == nil { - return nil - } - - if invType := inverseICMPType(t.Type); invType != undefinedICMP { - return ICMP{ICMPCodeType: &ICMPCodeType{Type: invType, Code: t.Code}} - } - return nil -} - -// Based on https://datatracker.ietf.org/doc/html/rfc792 - -const ( - echoReply = 0 - destinationUnreachable = 3 - sourceQuench = 4 - redirect = 5 - echo = 8 - timeExceeded = 11 - parameterProblem = 12 - timestamp = 13 - timestampReply = 14 - informationRequest = 15 - informationReply = 16 - - undefinedICMP = -2 -) - -// inverseICMPType returns the reply type for request type and vice versa. -// When there is no inverse, returns undefinedICMP -func inverseICMPType(t int) int { - switch t { - case echo: - return echoReply - case echoReply: - return echo - - case timestamp: - return timestampReply - case timestampReply: - return timestamp - - case informationRequest: - return informationReply - case informationReply: - return informationRequest - - case destinationUnreachable, sourceQuench, redirect, timeExceeded, parameterProblem: - return undefinedICMP - default: - log.Panicf("Impossible ICMP type: %v", t) - } - return undefinedICMP -} - -//nolint:revive // magic numbers are fine here -func ValidateICMP(t, c int) error { - possibleCodes := map[int][]int{ - echoReply: {0}, - destinationUnreachable: {0, 1, 2, 3, 4, 5}, - sourceQuench: {0}, - redirect: {0, 1, 2, 3}, - echo: {0}, - timeExceeded: {0, 1}, - parameterProblem: {0}, - timestamp: {0}, - timestampReply: {0}, - informationRequest: {0}, - informationReply: {0}, - } - options, ok := possibleCodes[t] - if !ok { - return fmt.Errorf("invalid ICMP type %v", t) - } - if !slices.Contains(options, c) { - return fmt.Errorf("ICMP code %v is invalid for ICMP type %v", c, t) - } - return nil -} diff --git a/pkg/ir/packet.go b/pkg/ir/packet.go index 818fa2f3..1d70ed69 100644 --- a/pkg/ir/packet.go +++ b/pkg/ir/packet.go @@ -9,12 +9,13 @@ import ( "fmt" "log" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" ) type Packet struct { - Src, Dst *ipblock.IPBlock - Protocol Protocol + Src, Dst *netset.IPBlock + Protocol netp.Protocol Explanation string } @@ -39,42 +40,42 @@ func packetACLRule(packet *Packet, direction Direction, action Action) *ACLRule // makeDenyInternal prevents allowing external communications from accidentally allowing internal communications too func makeDenyInternal() []ACLRule { - cidr1, err := ipblock.FromCidr("10.0.0.0/8") + cidr1, err := netset.IPBlockFromCidr("10.0.0.0/8") if err != nil { log.Fatal(err) } - cidr2, err := ipblock.FromCidr("172.16.0.0/12") + cidr2, err := netset.IPBlockFromCidr("172.16.0.0/12") if err != nil { log.Fatal(err) } - cidr3, err := ipblock.FromCidr("192.168.0.0/16") + cidr3, err := netset.IPBlockFromCidr("192.168.0.0/16") if err != nil { log.Fatal(err) } - localCidrs := []*ipblock.IPBlock{cidr1, cidr2, cidr3} // https://datatracker.ietf.org/doc/html/rfc1918#section-3 + localCidrs := []*netset.IPBlock{cidr1, cidr2, cidr3} // https://datatracker.ietf.org/doc/html/rfc1918#section-3 var denyInternal []ACLRule - for i, anyLocalCidrSrc := range localCidrs { - for j, anyLocalCidrDst := range localCidrs { + for i, localSrc := range localCidrs { + for j, localDst := range localCidrs { explanation := fmt.Sprintf("Deny other internal communication; see rfc1918#3; item %v,%v", i, j) denyInternal = append(denyInternal, - *packetACLRule(&Packet{Src: anyLocalCidrSrc, Dst: anyLocalCidrDst, Protocol: AnyProtocol{}, Explanation: explanation}, Outbound, Deny), - *packetACLRule(&Packet{Src: anyLocalCidrDst, Dst: anyLocalCidrSrc, Protocol: AnyProtocol{}, Explanation: explanation}, Inbound, Deny), + *packetACLRule(&Packet{Src: localSrc, Dst: localDst, Protocol: netp.AnyProtocol{}, Explanation: explanation}, Outbound, Deny), + *packetACLRule(&Packet{Src: localDst, Dst: localSrc, Protocol: netp.AnyProtocol{}, Explanation: explanation}, Inbound, Deny), ) } } return denyInternal } -func DenyAllSend(subnetName ID, cidr *ipblock.IPBlock) *ACLRule { +func DenyAllSend(subnetName ID, cidr *netset.IPBlock) *ACLRule { explanation := DenyAllExplanation(subnetName, cidr) - return packetACLRule(&Packet{Src: cidr, Dst: ipblock.GetCidrAll(), Protocol: AnyProtocol{}, Explanation: explanation}, Outbound, Deny) + return packetACLRule(&Packet{Src: cidr, Dst: netset.GetCidrAll(), Protocol: netp.AnyProtocol{}, Explanation: explanation}, Outbound, Deny) } -func DenyAllReceive(subnetName ID, cidr *ipblock.IPBlock) *ACLRule { +func DenyAllReceive(subnetName ID, cidr *netset.IPBlock) *ACLRule { explanation := DenyAllExplanation(subnetName, cidr) - return packetACLRule(&Packet{Src: ipblock.GetCidrAll(), Dst: cidr, Protocol: AnyProtocol{}, Explanation: explanation}, Inbound, Deny) + return packetACLRule(&Packet{Src: netset.GetCidrAll(), Dst: cidr, Protocol: netp.AnyProtocol{}, Explanation: explanation}, Inbound, Deny) } -func DenyAllExplanation(subnetName ID, cidr *ipblock.IPBlock) string { +func DenyAllExplanation(subnetName ID, cidr *netset.IPBlock) string { return fmt.Sprintf("Deny all communication; subnet %s[%s] does not have required connections", subnetName, cidr.String()) } diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 56617a11..4035ea69 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -9,6 +9,8 @@ import ( "fmt" "reflect" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) @@ -31,13 +33,13 @@ func (s SGName) String() string { type RemoteType interface { fmt.Stringer - // *ipblock.IPBlock | SGName + // *netset.IPBlock | SGName } type SGRule struct { Direction Direction Remote RemoteType - Protocol Protocol + Protocol netp.Protocol Explanation string } diff --git a/pkg/ir/spec.go b/pkg/ir/spec.go index 2ca236d6..6e3c58aa 100644 --- a/pkg/ir/spec.go +++ b/pkg/ir/spec.go @@ -12,7 +12,8 @@ import ( "sort" "strings" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" ) const MaximalIPv4PrefixLength = 32 @@ -47,14 +48,14 @@ type ( Name string // list of CIDR / Ip addresses. - IPAddrs []*ipblock.IPBlock + IPAddrs []*netset.IPBlock // Type of resource Type ResourceType } TrackedProtocol struct { - Protocol + netp.Protocol Origin fmt.Stringer } @@ -88,20 +89,20 @@ type ( } VPCDetails struct { - AddressPrefixes *ipblock.IPBlock + AddressPrefixes *netset.IPBlock // tg // lb } SubnetDetails struct { NamedEntity - CIDR *ipblock.IPBlock + CIDR *netset.IPBlock VPC ID } NifDetails struct { NamedEntity - IP *ipblock.IPBlock + IP *netset.IPBlock VPC ID Instance ID Subnet ID @@ -115,7 +116,7 @@ type ( VPEReservedIPsDetails struct { NamedEntity - IP *ipblock.IPBlock + IP *netset.IPBlock VPEName ID Subnet ID VPC ID @@ -133,7 +134,7 @@ type ( } CidrSegmentDetails struct { - Cidrs map[*ipblock.IPBlock]CIDRDetails + Cidrs map[*netset.IPBlock]CIDRDetails } CIDRDetails struct { @@ -142,7 +143,7 @@ type ( } ExternalDetails struct { - ExternalAddrs *ipblock.IPBlock + ExternalAddrs *netset.IPBlock } Named interface { @@ -150,7 +151,7 @@ type ( } NWResource interface { - Address() *ipblock.IPBlock + Address() *netset.IPBlock } ResourceVpc interface { @@ -162,19 +163,19 @@ func (n *NamedEntity) Name() string { return string(*n) } -func (s *SubnetDetails) Address() *ipblock.IPBlock { +func (s *SubnetDetails) Address() *netset.IPBlock { return s.CIDR } -func (n *NifDetails) Address() *ipblock.IPBlock { +func (n *NifDetails) Address() *netset.IPBlock { return n.IP } -func (v *VPEReservedIPsDetails) Address() *ipblock.IPBlock { +func (v *VPEReservedIPsDetails) Address() *netset.IPBlock { return v.IP } -func (e *ExternalDetails) Address() *ipblock.IPBlock { +func (e *ExternalDetails) Address() *netset.IPBlock { return e.ExternalAddrs } @@ -225,14 +226,14 @@ func getResourceVPCs[T ResourceVpc](m map[ID]T, name string) []ID { func lookupSingle[T NWResource](m map[ID]T, name string, t ResourceType) (Resource, error) { if details, ok := m[name]; ok { - return Resource{name, []*ipblock.IPBlock{details.Address()}, t}, nil + return Resource{name, []*netset.IPBlock{details.Address()}, t}, nil } return Resource{}, resourceNotFoundError(name, t) } func (s *Definitions) lookupInstance(name string) (Resource, error) { if instanceDetails, ok := s.Instances[name]; ok { - ips := make([]*ipblock.IPBlock, len(instanceDetails.Nifs)) + ips := make([]*netset.IPBlock, len(instanceDetails.Nifs)) for i, elemName := range instanceDetails.Nifs { nif, err := s.Lookup(ResourceTypeNIF, elemName) if err != nil { @@ -251,7 +252,7 @@ func (s *Definitions) lookupVPE(name string) (Resource, error) { if !ok { return Resource{}, resourceNotFoundError(name, ResourceTypeVPE) } - ips := make([]*ipblock.IPBlock, len(VPEDetails.VPEReservedIPs)) + ips := make([]*netset.IPBlock, len(VPEDetails.VPEReservedIPs)) for i, vpeEndPoint := range VPEDetails.VPEReservedIPs { ips[i] = s.VPEReservedIPs[vpeEndPoint].IP } @@ -260,7 +261,7 @@ func (s *Definitions) lookupVPE(name string) (Resource, error) { func (s *Definitions) lookupSubnetSegment(name string) (Resource, error) { if subnetSegmentDetails, ok := s.SubnetSegments[name]; ok { - cidrs := make([]*ipblock.IPBlock, len(subnetSegmentDetails.Subnets)) + cidrs := make([]*netset.IPBlock, len(subnetSegmentDetails.Subnets)) for i, subnetName := range subnetSegmentDetails.Subnets { subnet, err := s.Lookup(ResourceTypeSubnet, subnetName) if err != nil { @@ -279,7 +280,7 @@ func (s *Definitions) lookupCidrSegment(name string) (Resource, error) { if !ok { return Resource{}, containerNotFoundError(name, ResourceTypeSegment) } - cidrs := make([]*ipblock.IPBlock, len(cidrSegmentDetails.Cidrs)) + cidrs := make([]*netset.IPBlock, len(cidrSegmentDetails.Cidrs)) i := 0 for cidr := range cidrSegmentDetails.Cidrs { cidrs[i] = cidr @@ -348,7 +349,7 @@ func (s *Definitions) ValidateConnection(srcVPCs, dstVPCs []ID) error { return nil } -func inverseLookup[T NWResource](m map[ID]T, address *ipblock.IPBlock) (result string, ok bool) { +func inverseLookup[T NWResource](m map[ID]T, address *netset.IPBlock) (result string, ok bool) { for name, details := range m { if details.Address().Equal(address) { return name, true @@ -357,7 +358,7 @@ func inverseLookup[T NWResource](m map[ID]T, address *ipblock.IPBlock) (result s return "", false } -func (s *ConfigDefs) NIFFromIP(ip *ipblock.IPBlock) (string, bool) { +func (s *ConfigDefs) NIFFromIP(ip *netset.IPBlock) (string, bool) { return inverseLookup(s.NIFs, ip) } @@ -365,10 +366,10 @@ type Reader interface { ReadSpec(filename string, defs *ConfigDefs) (*Spec, error) } -func (s *ConfigDefs) SubnetsContainedInCidr(cidr ipblock.IPBlock) ([]ID, error) { +func (s *ConfigDefs) SubnetsContainedInCidr(cidr netset.IPBlock) ([]ID, error) { var containedSubnets []string for subnet, subnetDetails := range s.Subnets { - if subnetDetails.CIDR.ContainedIn(&cidr) { + if subnetDetails.CIDR.IsSubset(&cidr) { containedSubnets = append(containedSubnets, subnet) } } @@ -406,7 +407,7 @@ func VpcFromScopedResource(resource ID) ID { return ScopingComponents(resource)[0] } -func IsIPAddress(address *ipblock.IPBlock) bool { +func IsIPAddress(address *netset.IPBlock) bool { prefixLength, err := address.PrefixLength() if err != nil { log.Fatal(err) @@ -417,3 +418,8 @@ func IsIPAddress(address *ipblock.IPBlock) bool { func ChangeScoping(s string) string { return strings.ReplaceAll(s, "/", "--") } + +// Todo: move this function to models repo (as a method) +func Overlap(a, b *netset.IPBlock) bool { + return !a.Intersect(b).IsEmpty() +} diff --git a/pkg/ir/tcpudp.go b/pkg/ir/tcpudp.go deleted file mode 100644 index a9a74180..00000000 --- a/pkg/ir/tcpudp.go +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package ir - -import "log" - -type TransportLayerProtocolName string - -const ( - TCP TransportLayerProtocolName = "TCP" - UDP TransportLayerProtocolName = "UDP" -) - -const DefaultMinPort = 1 -const DefaultMaxPort = 65535 - -type PortRange struct { - // Minimal port; default is DefaultMinPort - Min int - - // Maximal port; default is DefaultMaxPort - Max int -} - -type PortRangePair struct { - SrcPort PortRange - DstPort PortRange -} - -type TCPUDP struct { - Protocol TransportLayerProtocolName - PortRangePair PortRangePair -} - -func (t TCPUDP) InverseDirection() Protocol { - switch t.Protocol { - case TCP: - return TCPUDP{ - Protocol: TCP, - PortRangePair: PortRangePair{SrcPort: t.PortRangePair.DstPort, DstPort: t.PortRangePair.SrcPort}, - } - case UDP: - return nil - default: - log.Panicf("Impossible protocol: %v", t.Protocol) - } - return nil -} diff --git a/pkg/synth/acl.go b/pkg/synth/acl.go index 352f43e2..46201f1e 100644 --- a/pkg/synth/acl.go +++ b/pkg/synth/acl.go @@ -10,7 +10,7 @@ import ( "fmt" "log" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -78,7 +78,7 @@ func (a *ACLSynthesizer) generateACLRulesFromConnection(conn *ir.Connection) { // if the src in internal, rule(s) will be created to allow traffic. // if the protocol allows response, more rules will be created. func (a *ACLSynthesizer) allowConnectionFromSrc(conn *ir.Connection, trackedProtocol ir.TrackedProtocol, - srcSubnets []*namedAddrs, dstCidr *ipblock.IPBlock) { + srcSubnets []*namedAddrs, dstCidr *netset.IPBlock) { internalSrc, _, internal := internalConn(conn) if !internalSrc { @@ -101,7 +101,7 @@ func (a *ACLSynthesizer) allowConnectionFromSrc(conn *ir.Connection, trackedProt // if the dst in internal, rule(s) will be created to allow traffic. // if the protocol allows response, more rules will be created. func (a *ACLSynthesizer) allowConnectionToDst(conn *ir.Connection, trackedProtocol ir.TrackedProtocol, - dstSubnets []*namedAddrs, srcCidr *ipblock.IPBlock) { + dstSubnets []*namedAddrs, srcCidr *netset.IPBlock) { _, internalDst, internal := internalConn(conn) if !internalDst { @@ -134,7 +134,7 @@ func (a *ACLSynthesizer) generateACLRulesForBlockedSubnets() { // convert src and dst resources to namedAddrs slices to make it more convenient to go through the addrs and add // the rule to the relevant acl. Note: in case where the resource in a nif, src/dst will be updated to be its subnet. -func adjustResource(s *ir.Definitions, addrs *ipblock.IPBlock, resource ir.Resource) ([]*namedAddrs, *ipblock.IPBlock) { +func adjustResource(s *ir.Definitions, addrs *netset.IPBlock, resource ir.Resource) ([]*namedAddrs, *netset.IPBlock) { switch resource.Type { case ir.ResourceTypeSubnet: return adjustSubnet(s, addrs, resource.Name), addrs @@ -149,7 +149,7 @@ func adjustResource(s *ir.Definitions, addrs *ipblock.IPBlock, resource ir.Resou return []*namedAddrs{}, nil // shouldn't happen } -func adjustSubnet(s *ir.Definitions, addrs *ipblock.IPBlock, resourceName string) []*namedAddrs { +func adjustSubnet(s *ir.Definitions, addrs *netset.IPBlock, resourceName string) []*namedAddrs { // Todo: Handle the case where there is a subnet and a subnetSegment with the same name if subnetDetails, ok := s.Subnets[resourceName]; ok { // resource is a subnet return []*namedAddrs{{Name: resourceName, Addrs: subnetDetails.Address()}} @@ -163,7 +163,7 @@ func adjustSubnet(s *ir.Definitions, addrs *ipblock.IPBlock, resourceName string return []*namedAddrs{} // shouldn't happen } -func adjustCidrSegment(s *ir.Definitions, cidr *ipblock.IPBlock, resourceName string) []*namedAddrs { +func adjustCidrSegment(s *ir.Definitions, cidr *netset.IPBlock, resourceName string) []*namedAddrs { cidrSegmentDetails := s.CidrSegments[resourceName] cidrDetails := cidrSegmentDetails.Cidrs[cidr] result := make([]*namedAddrs, len(cidrDetails.ContainedSubnets)) @@ -173,7 +173,7 @@ func adjustCidrSegment(s *ir.Definitions, cidr *ipblock.IPBlock, resourceName st return result } -func expandNifToSubnet(s *ir.Definitions, addr *ipblock.IPBlock) []*namedAddrs { +func expandNifToSubnet(s *ir.Definitions, addr *netset.IPBlock) []*namedAddrs { nifName, _ := s.NIFFromIP(addr) // already checked before (Lookup function) that the NIF exists subnetName := s.NIFs[nifName].Subnet subnetCidr := s.Subnets[subnetName].Address() diff --git a/pkg/synth/common.go b/pkg/synth/common.go index 01faf137..9833c121 100644 --- a/pkg/synth/common.go +++ b/pkg/synth/common.go @@ -8,7 +8,7 @@ package synth import ( "fmt" - "github.com/np-guard/models/pkg/ipblock" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -20,7 +20,7 @@ type ( namedAddrs struct { Name ir.ID - Addrs *ipblock.IPBlock + Addrs *netset.IPBlock } explanation struct { diff --git a/test/data/acl_nif/nacl_expected.tf b/test/data/acl_nif/nacl_expected.tf index 28738340..5d999aac 100644 --- a/test/data/acl_nif/nacl_expected.tf +++ b/test/data/acl_nif/nacl_expected.tf @@ -12,7 +12,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { destination = "10.240.0.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] @@ -24,7 +23,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } } @@ -116,7 +114,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { destination = "10.240.0.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] @@ -128,7 +125,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] diff --git a/test/data/acl_testing5/nacl_expected.csv b/test/data/acl_testing5/nacl_expected.csv index f3f0f5fa..0ccc67b6 100644 --- a/test/data/acl_testing5/nacl_expected.csv +++ b/test/data/acl_testing5/nacl_expected.csv @@ -1,8 +1,8 @@ Acl,Subnet,Direction,Rule priority,Allow or deny,Protocol,Source,Destination,Value,Description acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Outbound,1,Allow,ALL,10.240.1.0/24,10.240.64.0/24,-,Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Inbound,2,Allow,ALL,10.240.64.0/24,10.240.1.0/24,-,Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] -acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Outbound,3,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Inbound,4,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Outbound,3,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Inbound,4,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Outbound,5,Allow,TCP,"10.240.1.0/24, any port","10.240.2.0/24, any port",-,Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Inbound,6,Allow,TCP,"10.240.2.0/24, any port","10.240.1.0/24, any port",-,Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] acl-testacl5-vpc/sub1-1,testacl5-vpc/sub1-1,Outbound,7,Allow,TCP,"10.240.1.0/24, any port","10.240.3.0/24, any port",-,Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] @@ -36,8 +36,8 @@ acl-testacl5-vpc/sub1-3,testacl5-vpc/sub1-3,Inbound,3,Allow,TCP,"10.240.2.0/24, acl-testacl5-vpc/sub1-3,testacl5-vpc/sub1-3,Outbound,4,Allow,TCP,"10.240.3.0/24, any port","10.240.2.0/24, any port",-,Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Inbound,1,Allow,ALL,10.240.1.0/24,10.240.64.0/24,-,Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Outbound,2,Allow,ALL,10.240.64.0/24,10.240.1.0/24,-,Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] -acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Outbound,3,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Inbound,4,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Outbound,3,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Inbound,4,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Outbound,5,Allow,ALL,10.240.64.0/24,10.240.65.0/24,-,Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Inbound,6,Allow,ALL,10.240.65.0/24,10.240.64.0/24,-,Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Inbound,7,Allow,TCP,"10.240.128.0/24, any port","10.240.64.0/24, ports 443-443",-,Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] @@ -63,9 +63,9 @@ acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Inbound,26,Deny,ALL,192.168.0.0/16,1 acl-testacl5-vpc/sub2-1,testacl5-vpc/sub2-1,Outbound,27,Allow,UDP,"10.240.64.0/24, any port","8.8.8.8, ports 53-53",-,External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] acl-testacl5-vpc/sub2-2,testacl5-vpc/sub2-2,Inbound,1,Allow,ALL,10.240.64.0/24,10.240.65.0/24,-,Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] acl-testacl5-vpc/sub2-2,testacl5-vpc/sub2-2,Outbound,2,Allow,ALL,10.240.65.0/24,10.240.64.0/24,-,Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] -acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Inbound,1,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Outbound,2,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Inbound,3,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Outbound,4,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Inbound,1,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Outbound,2,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Inbound,3,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Outbound,4,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Outbound,5,Allow,TCP,"10.240.128.0/24, any port","10.240.64.0/24, ports 443-443",-,Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] acl-testacl5-vpc/sub3-1,testacl5-vpc/sub3-1,Inbound,6,Allow,TCP,"10.240.64.0/24, ports 443-443","10.240.128.0/24, any port",-,Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] diff --git a/test/data/acl_testing5/nacl_expected.json b/test/data/acl_testing5/nacl_expected.json index 22f73491..92a4c2ae 100644 --- a/test/data/acl_testing5/nacl_expected.json +++ b/test/data/acl_testing5/nacl_expected.json @@ -1758,7 +1758,6 @@ "ip_version": "ipv4", "name": "rule2", "source": "10.240.1.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -1777,7 +1776,6 @@ "ip_version": "ipv4", "name": "rule3", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, @@ -2267,7 +2265,6 @@ "ip_version": "ipv4", "name": "rule2", "source": "10.240.64.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -2286,7 +2283,6 @@ "ip_version": "ipv4", "name": "rule3", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, @@ -2904,7 +2900,6 @@ "ip_version": "ipv4", "name": "rule0", "source": "10.240.1.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -2923,7 +2918,6 @@ "ip_version": "ipv4", "name": "rule1", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, @@ -2942,7 +2936,6 @@ "ip_version": "ipv4", "name": "rule2", "source": "10.240.64.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -2961,7 +2954,6 @@ "ip_version": "ipv4", "name": "rule3", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, diff --git a/test/data/acl_testing5/nacl_expected.tf b/test/data/acl_testing5/nacl_expected.tf index 869e03f2..69925897 100644 --- a/test/data/acl_testing5/nacl_expected.tf +++ b/test/data/acl_testing5/nacl_expected.tf @@ -28,7 +28,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -40,7 +39,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { destination = "10.240.1.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] @@ -365,7 +363,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -377,7 +374,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] @@ -615,7 +611,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -627,7 +622,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { destination = "10.240.1.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -639,7 +633,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -651,7 +644,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] diff --git a/test/data/acl_testing5/nacl_single_expected.csv b/test/data/acl_testing5/nacl_single_expected.csv index f988c39d..8ce037d1 100644 --- a/test/data/acl_testing5/nacl_single_expected.csv +++ b/test/data/acl_testing5/nacl_single_expected.csv @@ -3,14 +3,14 @@ acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,1,Allow,ALL,10.240.1. acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,2,Allow,ALL,10.240.64.0/24,10.240.1.0/24,-,Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,3,Allow,ALL,10.240.1.0/24,10.240.64.0/24,-,Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,4,Allow,ALL,10.240.64.0/24,10.240.1.0/24,-,Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,5,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,6,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,7,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,8,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,9,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,10,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,11,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: 0",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] -acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,12,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: 0",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,5,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,6,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,7,Allow,ICMP,10.240.1.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,8,Allow,ICMP,10.240.128.0/24,10.240.1.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,9,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,10,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,11,Allow,ICMP,10.240.64.0/24,10.240.128.0/24,"Type: 0, Code: Any",Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] +acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,12,Allow,ICMP,10.240.128.0/24,10.240.64.0/24,"Type: 8, Code: Any",Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Outbound,13,Allow,TCP,"10.240.1.0/24, any port","10.240.2.0/24, any port",-,Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,14,Allow,TCP,"10.240.2.0/24, any port","10.240.1.0/24, any port",-,Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] acl-testacl5-vpc/singleACL,testacl5-vpc/singleACL,Inbound,15,Allow,TCP,"10.240.1.0/24, any port","10.240.2.0/24, any port",-,Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] diff --git a/test/data/acl_testing5/nacl_single_expected.json b/test/data/acl_testing5/nacl_single_expected.json index 446037d3..c60b8d79 100644 --- a/test/data/acl_testing5/nacl_single_expected.json +++ b/test/data/acl_testing5/nacl_single_expected.json @@ -1682,7 +1682,6 @@ "ip_version": "ipv4", "name": "rule4", "source": "10.240.1.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -1701,7 +1700,6 @@ "ip_version": "ipv4", "name": "rule5", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, @@ -1720,7 +1718,6 @@ "ip_version": "ipv4", "name": "rule6", "source": "10.240.1.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -1739,7 +1736,6 @@ "ip_version": "ipv4", "name": "rule7", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, @@ -1758,7 +1754,6 @@ "ip_version": "ipv4", "name": "rule8", "source": "10.240.64.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -1777,7 +1772,6 @@ "ip_version": "ipv4", "name": "rule9", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, @@ -1796,7 +1790,6 @@ "ip_version": "ipv4", "name": "rule10", "source": "10.240.64.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -1815,7 +1808,6 @@ "ip_version": "ipv4", "name": "rule11", "source": "10.240.128.0/24", - "code": 0, "protocol": "icmp", "type": 8 }, diff --git a/test/data/acl_testing5/nacl_single_expected.tf b/test/data/acl_testing5/nacl_single_expected.tf index 1a9f0301..5e3a1e07 100644 --- a/test/data/acl_testing5/nacl_single_expected.tf +++ b/test/data/acl_testing5/nacl_single_expected.tf @@ -43,7 +43,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -55,7 +54,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.1.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -67,7 +65,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -79,7 +76,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.1.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -91,7 +87,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -103,7 +98,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -115,7 +109,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.128.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] @@ -127,7 +120,6 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] diff --git a/test/data/acl_tg_multiple/nacl_expected.json b/test/data/acl_tg_multiple/nacl_expected.json index 97dc909e..bccff41e 100644 --- a/test/data/acl_tg_multiple/nacl_expected.json +++ b/test/data/acl_tg_multiple/nacl_expected.json @@ -2500,7 +2500,6 @@ "ip_version": "ipv4", "name": "rule0", "source": "10.240.8.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -2514,7 +2513,6 @@ "ip_version": "ipv4", "name": "rule1", "source": "10.240.9.0/24", - "code": 0, "protocol": "icmp", "type": 8 } @@ -2713,7 +2711,6 @@ "ip_version": "ipv4", "name": "rule0", "source": "10.240.64.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -2727,7 +2724,6 @@ "ip_version": "ipv4", "name": "rule1", "source": "10.240.80.0/24", - "code": 0, "protocol": "icmp", "type": 8 } @@ -2858,7 +2854,6 @@ "ip_version": "ipv4", "name": "rule0", "source": "10.240.64.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -2872,7 +2867,6 @@ "ip_version": "ipv4", "name": "rule1", "source": "10.240.80.0/24", - "code": 0, "protocol": "icmp", "type": 8 } @@ -3102,7 +3096,6 @@ "ip_version": "ipv4", "name": "rule0", "source": "10.240.8.0/24", - "code": 0, "protocol": "icmp", "type": 0 }, @@ -3116,7 +3109,6 @@ "ip_version": "ipv4", "name": "rule1", "source": "10.240.9.0/24", - "code": 0, "protocol": "icmp", "type": 8 } diff --git a/test/data/acl_tg_multiple/nacl_expected.tf b/test/data/acl_tg_multiple/nacl_expected.tf index 0fa5cc1d..3f3a8fd5 100644 --- a/test/data/acl_tg_multiple/nacl_expected.tf +++ b/test/data/acl_tg_multiple/nacl_expected.tf @@ -136,7 +136,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -148,7 +147,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } } @@ -167,7 +165,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -179,7 +176,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } } @@ -198,7 +194,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -210,7 +205,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } } @@ -229,7 +223,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -241,7 +234,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } } diff --git a/test/data/acl_tg_multiple/nacl_single_expected.tf b/test/data/acl_tg_multiple/nacl_single_expected.tf index 046a8f41..09a80278 100644 --- a/test/data/acl_tg_multiple/nacl_single_expected.tf +++ b/test/data/acl_tg_multiple/nacl_single_expected.tf @@ -92,7 +92,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -104,7 +103,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -116,7 +114,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -128,7 +125,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections @@ -163,7 +159,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -175,7 +170,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -187,7 +181,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -199,7 +192,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } } diff --git a/test/data/acl_tg_multiple/single_test-vpc0.tf b/test/data/acl_tg_multiple/single_test-vpc0.tf index 3850c1f2..c9ea8d01 100644 --- a/test/data/acl_tg_multiple/single_test-vpc0.tf +++ b/test/data/acl_tg_multiple/single_test-vpc0.tf @@ -91,7 +91,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -103,7 +102,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -115,7 +113,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -127,7 +124,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections diff --git a/test/data/acl_tg_multiple/single_test-vpc1.tf b/test/data/acl_tg_multiple/single_test-vpc1.tf index 340977f5..c8303eee 100644 --- a/test/data/acl_tg_multiple/single_test-vpc1.tf +++ b/test/data/acl_tg_multiple/single_test-vpc1.tf @@ -11,7 +11,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -23,7 +22,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -35,7 +33,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -47,7 +44,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } } diff --git a/test/data/acl_tg_multiple/test-vpc0.tf b/test/data/acl_tg_multiple/test-vpc0.tf index e8d70969..2a26d9dd 100644 --- a/test/data/acl_tg_multiple/test-vpc0.tf +++ b/test/data/acl_tg_multiple/test-vpc0.tf @@ -136,7 +136,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -148,7 +147,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } } @@ -167,7 +165,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { destination = "10.240.9.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] @@ -179,7 +176,6 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { destination = "10.240.8.0/24" icmp { type = 8 - code = 0 } } } diff --git a/test/data/acl_tg_multiple/test-vpc1.tf b/test/data/acl_tg_multiple/test-vpc1.tf index 29667206..62ada153 100644 --- a/test/data/acl_tg_multiple/test-vpc1.tf +++ b/test/data/acl_tg_multiple/test-vpc1.tf @@ -12,7 +12,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -24,7 +23,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } } @@ -43,7 +41,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { destination = "10.240.80.0/24" icmp { type = 0 - code = 0 } } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] @@ -55,7 +52,6 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { destination = "10.240.64.0/24" icmp { type = 8 - code = 0 } } } diff --git a/test/data/sg_testing3/sg_expected.csv b/test/data/sg_testing3/sg_expected.csv index 95afca81..73c2c2b8 100644 --- a/test/data/sg_testing3/sg_expected.csv +++ b/test/data/sg_testing3/sg_expected.csv @@ -2,11 +2,11 @@ SG,Direction,Remote type,Remote,Protocol,Protocol params,Description test-vpc/be,Inbound,Security group,test-vpc/fe,TCP,any port,Internal. required-connections[2]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] test-vpc/be,Outbound,Security group,test-vpc/opa,ALL,,Internal. required-connections[3]: (instance test-vpc/be)->(instance test-vpc/opa); allowed-protocols[0] test-vpc/be,Outbound,Security group,test-vpc/policydb-endpoint-gateway,ALL,,Internal. required-connections[4]: (instance test-vpc/be)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] -test-vpc/fe,Inbound,Security group,test-vpc/proxy,TCP,Ports 9000-9000,Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] +test-vpc/fe,Inbound,Security group,test-vpc/proxy,TCP,ports 9000-9000,Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] test-vpc/fe,Outbound,Security group,test-vpc/be,TCP,any port,Internal. required-connections[2]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] test-vpc/opa,Inbound,Security group,test-vpc/be,ALL,,Internal. required-connections[3]: (instance test-vpc/be)->(instance test-vpc/opa); allowed-protocols[0] test-vpc/opa,Outbound,Security group,test-vpc/policydb-endpoint-gateway,ALL,,Internal. required-connections[5]: (instance test-vpc/opa)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] test-vpc/policydb-endpoint-gateway,Inbound,Security group,test-vpc/be,ALL,,Internal. required-connections[4]: (instance test-vpc/be)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] test-vpc/policydb-endpoint-gateway,Inbound,Security group,test-vpc/opa,ALL,,Internal. required-connections[5]: (instance test-vpc/opa)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] test-vpc/proxy,Inbound,CIDR block,Any IP,ALL,,External. required-connections[0]: (external public internet)->(instance test-vpc/proxy); allowed-protocols[0] -test-vpc/proxy,Outbound,Security group,test-vpc/fe,TCP,Ports 9000-9000,Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] +test-vpc/proxy,Outbound,Security group,test-vpc/fe,TCP,ports 9000-9000,Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] diff --git a/test/data/sg_tg_multiple/sg_expected.csv b/test/data/sg_tg_multiple/sg_expected.csv index 56d977fb..90127d5d 100644 --- a/test/data/sg_tg_multiple/sg_expected.csv +++ b/test/data/sg_tg_multiple/sg_expected.csv @@ -3,5 +3,5 @@ test-vpc0/vsi0-subnet0,Outbound,Security group,test-vpc0/vsi1-subnet4,ALL,,Inter test-vpc0/vsi1-subnet4,Inbound,Security group,test-vpc0/vsi0-subnet0,ALL,,Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi1-subnet4); allowed-protocols[0] test-vpc1/vsi0-subnet10,Outbound,Security group,test-vpc1/vsi0-subnet11,TCP,any port,Internal. required-connections[2]: (instance test-vpc1/vsi0-subnet10)->(instance test-vpc1/vsi0-subnet11); allowed-protocols[0] test-vpc1/vsi0-subnet11,Inbound,Security group,test-vpc1/vsi0-subnet10,TCP,any port,Internal. required-connections[2]: (instance test-vpc1/vsi0-subnet10)->(instance test-vpc1/vsi0-subnet11); allowed-protocols[0] -test-vpc2/vsi0-subnet20,Outbound,Security group,test-vpc2/vsi2-subnet20,TCP,Ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] -test-vpc2/vsi2-subnet20,Inbound,Security group,test-vpc2/vsi0-subnet20,TCP,Ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] +test-vpc2/vsi0-subnet20,Outbound,Security group,test-vpc2/vsi2-subnet20,TCP,ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] +test-vpc2/vsi2-subnet20,Inbound,Security group,test-vpc2/vsi0-subnet20,TCP,ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] diff --git a/test/data/sg_tg_multiple/test-vpc2.csv b/test/data/sg_tg_multiple/test-vpc2.csv index bc3f05dd..ec9047cf 100644 --- a/test/data/sg_tg_multiple/test-vpc2.csv +++ b/test/data/sg_tg_multiple/test-vpc2.csv @@ -1,3 +1,3 @@ SG,Direction,Remote type,Remote,Protocol,Protocol params,Description -test-vpc2/vsi0-subnet20,Outbound,Security group,test-vpc2/vsi2-subnet20,TCP,Ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] -test-vpc2/vsi2-subnet20,Inbound,Security group,test-vpc2/vsi0-subnet20,TCP,Ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] +test-vpc2/vsi0-subnet20,Outbound,Security group,test-vpc2/vsi2-subnet20,TCP,ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] +test-vpc2/vsi2-subnet20,Inbound,Security group,test-vpc2/vsi0-subnet20,TCP,ports 53-53,Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] From 4aeaef5820f8c115407875861cdb96871cddc9a1 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 18 Aug 2024 16:27:10 +0300 Subject: [PATCH 04/79] updated --- go.mod | 6 +++--- go.sum | 4 ++-- pkg/io/confio/conversions.go | 20 ++++++-------------- pkg/io/confio/read_defs.go | 2 +- pkg/io/csvio/acl.go | 4 ++-- pkg/io/csvio/sg.go | 4 ++-- pkg/io/jsonio/unmarshal.go | 29 ++++++++++------------------- pkg/io/mdio/acl.go | 4 ++-- pkg/io/mdio/sg.go | 4 ++-- pkg/io/tfio/acl.go | 4 ++-- pkg/io/tfio/sg.go | 4 ++-- pkg/ir/spec.go | 5 ----- 12 files changed, 34 insertions(+), 56 deletions(-) diff --git a/go.mod b/go.mod index 41c8b9f7..67a05b1b 100644 --- a/go.mod +++ b/go.mod @@ -37,10 +37,10 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect ) -// Todo: +// Todo: // (1) delete the following line when np-guard/models#33 is merged. -// (2) replace lines 137 and 138 in go.sum with +// (2) replace lines 137 and 138 in go.sum with // github.com/np-guard/models v0.3.4 h1:HOhVi6wyGvo+KmYBnQ5Km5HYCF+/PQlDs1v7mL1v05g= // github.com/np-guard/models v0.3.4/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= //nolint:gomoddirectives // this line is temporary -replace github.com/np-guard/models => github.com/np-guard/models v0.3.5-0.20240708150421-8d8e4354057d \ No newline at end of file +replace github.com/np-guard/models => github.com/np-guard/models v0.3.5-0.20240818081750-bb83d7f53d64 diff --git a/go.sum b/go.sum index dce9b4ea..31405b5e 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/np-guard/cloud-resource-collector v0.14.0 h1:MBPtPBYVCQoMfUkn/wODpF7SRpJ9TlOfMszO8N0PePo= github.com/np-guard/cloud-resource-collector v0.14.0/go.mod h1:klCHnNnuuVcCtGQHA7R1a8fqnvfMCk/5Jdld6V7sN2A= -github.com/np-guard/models v0.3.5-0.20240708150421-8d8e4354057d h1:yAmG3W8kUl0GC84dRWcgRK9lBWRkwJkwLnUtwoh1lIY= -github.com/np-guard/models v0.3.5-0.20240708150421-8d8e4354057d/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= +github.com/np-guard/models v0.3.5-0.20240818081750-bb83d7f53d64 h1:e3Fljv3NXu8UogaS4mq8TVqzfga/AuHElL8j0EQLrXw= +github.com/np-guard/models v0.3.5-0.20240818081750-bb83d7f53d64/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/pkg/io/confio/conversions.go b/pkg/io/confio/conversions.go index 6ef6733b..d1788e2f 100644 --- a/pkg/io/confio/conversions.go +++ b/pkg/io/confio/conversions.go @@ -11,7 +11,6 @@ import ( "github.com/IBM/vpc-go-sdk/vpcv1" - "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" @@ -65,14 +64,6 @@ func direction(d ir.Direction) *string { return nil } -func minPort(r interval.Interval) *int64 { - return utils.Ptr(r.Start()) -} - -func maxPort(r interval.Interval) *int64 { - return utils.Ptr(r.End()) -} - type tcpudpData struct { Protocol *string SourcePortMin *int64 @@ -106,13 +97,14 @@ type allData struct { } func tcpudp(p netp.TCPUDP) tcpudpData { - r := p.PortRangePair + srcPorts := p.SrcPorts() + dstPorts := p.DstPorts() res := tcpudpData{ Protocol: utils.Ptr(strings.ToLower(string(p.ProtocolString()))), - SourcePortMin: minPort(r.SrcPort), - SourcePortMax: maxPort(r.SrcPort), - DestinationPortMin: minPort(r.DstPort), - DestinationPortMax: maxPort(r.DstPort), + SourcePortMin: utils.Ptr(srcPorts.Start()), + SourcePortMax: utils.Ptr(srcPorts.End()), + DestinationPortMin: utils.Ptr(dstPorts.Start()), + DestinationPortMax: utils.Ptr(dstPorts.End()), } return res } diff --git a/pkg/io/confio/read_defs.go b/pkg/io/confio/read_defs.go index c2fc03b8..6c1d68b6 100644 --- a/pkg/io/confio/read_defs.go +++ b/pkg/io/confio/read_defs.go @@ -190,7 +190,7 @@ func validateVpcs(vpcs map[ir.ID]*ir.VPCDetails) error { if vpcName1 >= vpcName2 { continue } - if ir.Overlap(vpcDetails1.AddressPrefixes, vpcDetails2.AddressPrefixes) { + if vpcDetails1.AddressPrefixes.Overlap(vpcDetails2.AddressPrefixes) { return fmt.Errorf("vpcs %s and %s have overlapping IP address spaces", vpcName1, vpcName2) } } diff --git a/pkg/io/csvio/acl.go b/pkg/io/csvio/acl.go index 792f943e..a5e9c00e 100644 --- a/pkg/io/csvio/acl.go +++ b/pkg/io/csvio/acl.go @@ -97,9 +97,9 @@ func printIP(ip *netset.IPBlock, protocol netp.Protocol, isSource bool) string { case netp.TCPUDP: var r interval.Interval if isSource { - r = p.PortRangePair.SrcPort + r = p.SrcPorts() } else { - r = p.PortRangePair.DstPort + r = p.DstPorts() } return fmt.Sprintf("%v, %v", ipString, ACLPort(r)) case netp.AnyProtocol: diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index 2e438ec1..7c8993fc 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -108,9 +108,9 @@ func printProtocolParams(protocol netp.Protocol, isSource bool) string { case netp.TCPUDP: var r interval.Interval if isSource { - r = p.PortRangePair.SrcPort + r = p.SrcPorts() } else { - r = p.PortRangePair.DstPort + r = p.DstPorts() } return sGPort(r) case netp.AnyProtocol: diff --git a/pkg/io/jsonio/unmarshal.go b/pkg/io/jsonio/unmarshal.go index 87a843cc..689073ee 100644 --- a/pkg/io/jsonio/unmarshal.go +++ b/pkg/io/jsonio/unmarshal.go @@ -11,7 +11,6 @@ import ( "fmt" "os" - "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" "github.com/np-guard/models/pkg/spec" @@ -265,26 +264,18 @@ func translateProtocols(protocols spec.ProtocolList) ([]ir.TrackedProtocol, erro } result[i].Protocol = netp.AnyProtocol{} case spec.Icmp: - if p.Type == nil { - if p.Code != nil { - return nil, fmt.Errorf("defining ICMP code for unspecified ICMP type is not allowed") - } - result[i].Protocol = ir.TrackedProtocol{Protocol: netp.ICMP{}} - } else { - icmp, err := netp.ICMPFromTypeAndCode(p.Type, p.Code) - if err != nil { - return nil, err - } - result[i].Protocol = icmp + icmp, err := netp.ICMPFromTypeAndCode(p.Type, p.Code) + if err != nil { + return nil, err } + result[i].Protocol = icmp case spec.TcpUdp: - result[i].Protocol = netp.TCPUDP{ - IsTCP: p.Protocol == spec.TcpUdpProtocolTCP, - PortRangePair: netp.PortRangePair{ - SrcPort: interval.New(int64(p.MinSourcePort), int64(p.MaxSourcePort)), - DstPort: interval.New(int64(p.MinDestinationPort), int64(p.MaxDestinationPort)), - }, + tcpudp, err := netp.NewTCPUDP(p.Protocol == spec.TcpUdpProtocolTCP, p.MinSourcePort, p.MaxSourcePort, + p.MinDestinationPort, p.MaxDestinationPort) + if err != nil { + return nil, err } + result[i].Protocol = tcpudp default: return nil, fmt.Errorf("impossible protocol: %v", p) } @@ -361,7 +352,7 @@ func unmarshal(filename string) (*spec.Spec, error) { func parseOverlappingVpcs(cidr *netset.IPBlock, vpcs map[ir.ID]*ir.VPCDetails) []ir.ID { result := make([]ir.ID, 0) for vpcName, vpcDetails := range vpcs { - if ir.Overlap(vpcDetails.AddressPrefixes, cidr) { + if vpcDetails.AddressPrefixes.Overlap(cidr) { result = append(result, vpcName) } } diff --git a/pkg/io/mdio/acl.go b/pkg/io/mdio/acl.go index 18c010e7..e593de0e 100644 --- a/pkg/io/mdio/acl.go +++ b/pkg/io/mdio/acl.go @@ -114,9 +114,9 @@ func printIP(ip *netset.IPBlock, protocol netp.Protocol, isSource bool) string { case netp.TCPUDP: var r interval.Interval if isSource { - r = p.PortRangePair.SrcPort + r = p.SrcPorts() } else { - r = p.PortRangePair.DstPort + r = p.DstPorts() } return fmt.Sprintf("%v, %v", ipString, ACLPort(r)) case netp.AnyProtocol: diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index aea44185..c8ee6f77 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -122,9 +122,9 @@ func printProtocolParams(protocol netp.Protocol, isSource bool) string { case netp.TCPUDP: var r interval.Interval if isSource { - r = p.PortRangePair.SrcPort + r = p.SrcPorts() } else { - r = p.PortRangePair.DstPort + r = p.DstPorts() } return sGPort(r) case netp.AnyProtocol: diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index e3427b1c..e6d36637 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -34,8 +34,8 @@ func aclProtocol(t netp.Protocol) []tf.Block { return []tf.Block{{ Name: strings.ToLower(string(p.ProtocolString())), Arguments: append( - portRange(p.PortRangePair.DstPort, "port"), - portRange(p.PortRangePair.SrcPort, "source_port")..., + portRange(p.DstPorts(), "port"), + portRange(p.SrcPorts(), "source_port")..., ), }} case netp.ICMP: diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 7ad0aa29..74e796fb 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -46,9 +46,9 @@ func sgProtocol(t netp.Protocol, d ir.Direction) []tf.Block { case netp.TCPUDP: var remotePort interval.Interval if d == ir.Inbound { - remotePort = p.PortRangePair.SrcPort + remotePort = p.SrcPorts() } else { - remotePort = p.PortRangePair.DstPort + remotePort = p.DstPorts() } return []tf.Block{{ Name: strings.ToLower(string(p.ProtocolString())), diff --git a/pkg/ir/spec.go b/pkg/ir/spec.go index 6e3c58aa..a72cba91 100644 --- a/pkg/ir/spec.go +++ b/pkg/ir/spec.go @@ -418,8 +418,3 @@ func IsIPAddress(address *netset.IPBlock) bool { func ChangeScoping(s string) string { return strings.ReplaceAll(s, "/", "--") } - -// Todo: move this function to models repo (as a method) -func Overlap(a, b *netset.IPBlock) bool { - return !a.Intersect(b).IsEmpty() -} From cec430ec7602fdb9bc095c6d71b529f75d372136 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 11:56:18 +0300 Subject: [PATCH 05/79] use ipblock size --- pkg/io/confio/sg.go | 2 +- pkg/io/csvio/sg.go | 4 ++-- pkg/io/mdio/sg.go | 4 ++-- pkg/ir/spec.go | 11 ----------- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/pkg/io/confio/sg.go b/pkg/io/confio/sg.go index df0ed02b..ee551214 100644 --- a/pkg/io/confio/sg.go +++ b/pkg/io/confio/sg.go @@ -53,7 +53,7 @@ func sgRemote(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteSecurit st := rule.Remote.String() switch t := rule.Remote.(type) { case *netset.IPBlock: - if ir.IsIPAddress(t) { + if t.Size() == 1 { // single IP address return &vpcv1.SecurityGroupRuleRemoteIP{ Address: &st, } diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index 1f6b194c..a10dc8db 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -72,9 +72,9 @@ func sGPort(p interval.Interval) string { } func sGRemoteType(t ir.RemoteType) string { - switch tr := t.(type) { + switch t := t.(type) { case *netset.IPBlock: - if ir.IsIPAddress(tr) { + if t.Size() == 1 { return "IP address" } return "CIDR block" diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index 7f8d5b26..044ddbca 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -86,9 +86,9 @@ func sGPort(p interval.Interval) string { } func sGRemoteType(t ir.RemoteType) string { - switch tr := t.(type) { + switch t := t.(type) { case *netset.IPBlock: - if ir.IsIPAddress(tr) { + if t.Size() == 1 { return "IP address" } return "CIDR block" diff --git a/pkg/ir/spec.go b/pkg/ir/spec.go index a72cba91..472b7b10 100644 --- a/pkg/ir/spec.go +++ b/pkg/ir/spec.go @@ -8,7 +8,6 @@ package ir import ( "fmt" - "log" "sort" "strings" @@ -16,8 +15,6 @@ import ( "github.com/np-guard/models/pkg/netset" ) -const MaximalIPv4PrefixLength = 32 - type ( ID = string NamedEntity string @@ -407,14 +404,6 @@ func VpcFromScopedResource(resource ID) ID { return ScopingComponents(resource)[0] } -func IsIPAddress(address *netset.IPBlock) bool { - prefixLength, err := address.PrefixLength() - if err != nil { - log.Fatal(err) - } - return prefixLength == MaximalIPv4PrefixLength -} - func ChangeScoping(s string) string { return strings.ReplaceAll(s, "/", "--") } From b8ee61b569febf4d23d5f412692b092f9cb48e0e Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 12:08:54 +0300 Subject: [PATCH 06/79] minor changes --- cmd/subcmds/optimize.go | 5 ++--- cmd/subcmds/optimizeSG.go | 4 ++-- pkg/io/confio/parse_defs.go | 6 +----- pkg/synth/sg.go | 2 +- 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index cf8ec17e..877662a9 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -10,11 +10,10 @@ import "github.com/spf13/cobra" func NewOptimizeCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "optimize", - Short: "Optimize is not supported yet", - Long: `Optimize is not supported yet`, + Short: "optimization of existing SG (nACLS are not supported yet)", + Long: `optimization of existing SG (nACLS are not supported yet)`, } - cmd.AddCommand(NewOptimizeACLCommand(args)) cmd.AddCommand(NewOptimizeSGCommand(args)) return cmd diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index 1c903f83..cc0e1e23 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -10,8 +10,8 @@ import "github.com/spf13/cobra" func NewOptimizeSGCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "sg", - Short: "OptimizeSG is not supported yet", - Long: `OptimizeSG is not supported yet`, + Short: "OptimizeSG attempts to reduce the number of security group rules in a SG without changing the semantic.", + Long: `OptimizeSG attempts to reduce the number of security group rules in a SG without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { return nil diff --git a/pkg/io/confio/parse_defs.go b/pkg/io/confio/parse_defs.go index 3b2705d9..86ba8a95 100644 --- a/pkg/io/confio/parse_defs.go +++ b/pkg/io/confio/parse_defs.go @@ -41,10 +41,6 @@ func ReadDefs(filename string) (*ir.ConfigDefs, error) { if err != nil { return nil, err } - err = validateVpcs(vpcs) - if err != nil { - return nil, err - } return &ir.ConfigDefs{ VPCs: vpcs, @@ -69,7 +65,7 @@ func parseVPCs(config *configModel.ResourcesContainerModel) (map[ir.ID]*ir.VPCDe } VPCs[*vpc.Name] = &ir.VPCDetails{AddressPrefixes: addressPrefixes} } - return VPCs, nil + return VPCs, validateVpcs(VPCs) } func parseSubnets(config *configModel.ResourcesContainerModel) (map[ir.ID]*ir.SubnetDetails, error) { diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index d829d68d..054171cf 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -93,7 +93,7 @@ func (s *SGSynthesizer) allowConnectionFromSrc(conn *ir.Connection, trackedProto sgSrc.Add(rule) } -// if the dst in internal, a rule will be created to allow traffic. +// if the dst is internal, a rule will be created to allow traffic. func (s *SGSynthesizer) allowConnectionToDst(conn *ir.Connection, trackedProtocol ir.TrackedProtocol, srcEndpoint, dstEndpoint *namedAddrs) { _, internalDst, internal := internalConn(conn) From c1179412cf8930f6a1e1cb52fcd411af4599db4d Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 12:39:00 +0300 Subject: [PATCH 07/79] template --- cmd/subcmds/optimizeOutput.go | 14 ++++++++++++++ cmd/subcmds/optimizeSG.go | 24 +++++++++++++++++++++++- cmd/subcmds/root.go | 2 ++ pkg/io/confio/parse_sgs.go | 12 ++++++++++++ pkg/optimize.go/sg.go | 14 ++++++++++++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 cmd/subcmds/optimizeOutput.go create mode 100644 pkg/io/confio/parse_sgs.go create mode 100644 pkg/optimize.go/sg.go diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go new file mode 100644 index 00000000..dfeddc37 --- /dev/null +++ b/cmd/subcmds/optimizeOutput.go @@ -0,0 +1,14 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package subcmds + +import ( + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +func writeOptimizeOutput(args *inArgs, sgs map[ir.SGName]*ir.SG) error { + return nil +} diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index cc0e1e23..8cdeec92 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -5,7 +5,14 @@ SPDX-License-Identifier: Apache-2.0 package subcmds -import "github.com/spf13/cobra" +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize.go" +) func NewOptimizeSGCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ @@ -18,5 +25,20 @@ func NewOptimizeSGCommand(args *inArgs) *cobra.Command { }, } + cmd.Flags().StringVarP(&args.sgName, sgNameFlag, "s", "", "which SG to optimize") + _ = cmd.MarkFlagRequired(sgNameFlag) // Todo: delete this line. if sgName flag is not supplied - optimize all SGs + return cmd } + +func optimization(cmd *cobra.Command, args *inArgs) error { + cmd.SilenceUsage = true // if we got this far, flags are syntactically correct, so no need to print usage + sgs, err := confio.ReadSGs(args.configFile) + if err != nil { + return fmt.Errorf("could not parse config file %v: %w", args.configFile, err) + } + if optimize.ReduceSGRules(sgs, args.sgName) != nil { + return err + } + return writeOptimizeOutput(args, sgs) +} diff --git a/cmd/subcmds/root.go b/cmd/subcmds/root.go index 281c66b5..471b55d5 100644 --- a/cmd/subcmds/root.go +++ b/cmd/subcmds/root.go @@ -19,6 +19,7 @@ const ( outputFileFlag = "output-file" outputDirFlag = "output-dir" prefixFlag = "prefix" + sgNameFlag = "sg-name" singleACLFlag = "single" localsFlag = "locals" ) @@ -30,6 +31,7 @@ type inArgs struct { outputFile string outputDir string prefix string + sgName string singleacl bool locals bool } diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go new file mode 100644 index 00000000..fa6f7685 --- /dev/null +++ b/pkg/io/confio/parse_sgs.go @@ -0,0 +1,12 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package confio + +import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + +func ReadSGs(filename string) (map[ir.SGName]*ir.SG, error) { + return map[ir.SGName]*ir.SG{}, nil +} diff --git a/pkg/optimize.go/sg.go b/pkg/optimize.go/sg.go new file mode 100644 index 00000000..897c76f8 --- /dev/null +++ b/pkg/optimize.go/sg.go @@ -0,0 +1,14 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import ( + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +func ReduceSGRules(sgs map[ir.SGName]*ir.SG, sgName string) error { + return nil +} From 7e70c95d8dfa34965b0bc820097faf1736d01cb5 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 12:40:46 +0300 Subject: [PATCH 08/79] fixed --- pkg/io/confio/parse_sgs.go | 161 ++++++++++++++++++++++++++++++++++++- pkg/ir/sg.go | 2 + pkg/utils/utils.go | 16 ++++ 3 files changed, 177 insertions(+), 2 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index fa6f7685..96d5038d 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -5,8 +5,165 @@ SPDX-License-Identifier: Apache-2.0 package confio -import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +import ( + "fmt" + "reflect" + vpc1 "github.com/IBM/vpc-go-sdk/vpcv1" + + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" +) + +// ReadSG translates SGs from a config_object file to map[ir.SGName]*SG func ReadSGs(filename string) (map[ir.SGName]*ir.SG, error) { - return map[ir.SGName]*ir.SG{}, nil + config, err := readModel(filename) + if err != nil { + return nil, err + } + result := make(map[ir.SGName]*ir.SG, len(config.SecurityGroupList)) + + for _, sg := range config.SecurityGroupList { + inbound, outbound, err := translateSGRules(&sg.SecurityGroup) + if err != nil { + return nil, err + } + if sg.Name != nil { + result[ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} + } + } + return result, nil +} + +// parse security rules, splitted into ingress and egress rules +func translateSGRules(sg *vpc1.SecurityGroup) (ingressRules, egressRules []ir.SGRule, err error) { + ingressRules = []ir.SGRule{} + egressRules = []ir.SGRule{} + for index := range sg.Rules { + rule, err := translateSGRule(sg, index) + if err != nil { + return nil, nil, err + } + if rule.Direction == ir.Inbound { + ingressRules = append(ingressRules, rule) + } else { + egressRules = append(egressRules, rule) + } + } + return ingressRules, egressRules, nil +} + +// translateSGRule translates a security group rule to ir.SGRule +func translateSGRule(sg *vpc1.SecurityGroup, index int) (sgRule ir.SGRule, err error) { + fmt.Printf("Type of sgRule[%d]: %s \n", index, reflect.TypeOf(sg.Rules[index])) + switch r := sg.Rules[index].(type) { + case *vpc1.SecurityGroupRuleSecurityGroupRuleProtocolAll: + return translateSGRuleProtocolAll(r) + case *vpc1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp: + return translateSGRuleProtocolTCPUDP(r) + case *vpc1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp: + return translateSGRuleProtocolIcmp(r) + } + return ir.SGRule{}, fmt.Errorf("error parsing rule number %d in %s sg", index, *sg.Name) +} + +func translateSGRuleProtocolAll(rule *vpc1.SecurityGroupRuleSecurityGroupRuleProtocolAll) (sgRule ir.SGRule, err error) { + direction, err := translateDirection(*rule.Direction) + if err != nil { + return ir.SGRule{}, err + } + remote, err := translateRemote(rule.Remote) + if err != nil { + return ir.SGRule{}, err + } + local, err := translateLocal(rule.Local) + if err != nil { + return ir.SGRule{}, err + } + return ir.SGRule{Direction: direction, Remote: remote, Protocol: netp.AnyProtocol{}, Local: local}, nil +} + +func translateSGRuleProtocolTCPUDP(rule *vpc1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (sgRule ir.SGRule, err error) { + direction, err := translateDirection(*rule.Direction) + if err != nil { + return ir.SGRule{}, err + } + remote, err := translateRemote(rule.Remote) + if err != nil { + return ir.SGRule{}, err + } + local, err := translateLocal(rule.Local) + if err != nil { + return ir.SGRule{}, err + } + protocol, err := translateProtocolTCPUDP(rule) + if err != nil { + return ir.SGRule{}, err + } + return ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil +} + +func translateSGRuleProtocolIcmp(rule *vpc1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp) (sgRule ir.SGRule, err error) { + direction, err := translateDirection(*rule.Direction) + if err != nil { + return ir.SGRule{}, err + } + remote, err := translateRemote(rule.Remote) + if err != nil { + return ir.SGRule{}, err + } + local, err := translateLocal(rule.Local) + if err != nil { + return ir.SGRule{}, err + } + protocol, err := netp.ICMPFromTypeAndCode64(rule.Type, rule.Code) + if err != nil { + return ir.SGRule{}, err + } + return ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil +} + +func translateDirection(direction string) (ir.Direction, error) { + if direction == "inbound" { + return ir.Inbound, nil + } else if direction == "outbound" { + return ir.Outbound, nil + } + return ir.Inbound, fmt.Errorf("a SG rule direction must be either inbound or outbound") +} + +func translateRemote(remote vpc1.SecurityGroupRuleRemoteIntf) (ir.RemoteType, error) { + if r, ok := remote.(*vpc1.SecurityGroupRuleRemote); ok { + switch { + case r.CIDRBlock != nil: + return netset.IPBlockFromCidr(*r.CIDRBlock) + case r.Address != nil: + return netset.IPBlockFromIPAddress(*r.Address) + case r.Name != nil: + return ir.SGName(*r.Name), nil + } + } + return nil, fmt.Errorf("unexpected SG rule remote") +} + +func translateLocal(local vpc1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, error) { + if l, ok := local.(*vpc1.SecurityGroupRuleLocal); ok { + if l.CIDRBlock != nil { + return netset.IPBlockFromCidr(*l.CIDRBlock) + } + if l.Address != nil { + return netset.IPBlockFromIPAddress(*l.CIDRBlock) + } + } + return nil, fmt.Errorf("error parsing Local field") +} + +func translateProtocolTCPUDP(rule *vpc1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (netp.Protocol, error) { + isTCP := *rule.Protocol == string(netp.ProtocolStringTCP) + minDstPort := utils.GetProperty(rule.PortMin, netp.MinPort) + maxDstPort := utils.GetProperty(rule.PortMax, netp.MaxPort) + return netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(minDstPort), int(maxDstPort)) } diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 7c42fe01..5cf895ec 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -10,6 +10,7 @@ import ( "reflect" "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) @@ -40,6 +41,7 @@ type SGRule struct { Direction Direction Remote RemoteType Protocol netp.Protocol + Local *netset.IPBlock Explanation string } diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index acf9e3d2..ede1bb67 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -31,3 +31,19 @@ func SortedAllInnerMapsKeys[T, K cmp.Ordered, V any](m map[K]map[T]V) []T { slices.Sort(keys) return keys } + +// GetProperty returns pointer p if it is valid, else it returns the provided default value +// used to get min/max port or icmp type +func GetProperty(p *int64, defaultP int64) int64 { + if p == nil { + return defaultP + } + return *p +} + +func Int64PointerToIntPointer(v *int64) *int { + if v == nil { + return nil + } + return Ptr(int(*v)) +} From 19123f98c2a850278ee832c61f548c5aa81d54c3 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 12:44:49 +0300 Subject: [PATCH 09/79] minor change --- pkg/io/confio/parse_sgs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index 96d5038d..daf044cc 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -24,8 +24,8 @@ func ReadSGs(filename string) (map[ir.SGName]*ir.SG, error) { if err != nil { return nil, err } - result := make(map[ir.SGName]*ir.SG, len(config.SecurityGroupList)) + result := make(map[ir.SGName]*ir.SG, len(config.SecurityGroupList)) for _, sg := range config.SecurityGroupList { inbound, outbound, err := translateSGRules(&sg.SecurityGroup) if err != nil { From 067edfe6abbdcabcc200d8d0d89b3753c8ebaf84 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 12:59:00 +0300 Subject: [PATCH 10/79] another change --- cmd/subcmds/optimizeOutput.go | 2 +- pkg/optimize.go/sg.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go index dfeddc37..9ac7f8ce 100644 --- a/cmd/subcmds/optimizeOutput.go +++ b/cmd/subcmds/optimizeOutput.go @@ -9,6 +9,6 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func writeOptimizeOutput(args *inArgs, sgs map[ir.SGName]*ir.SG) error { +func writeOptimizeOutput(_ *inArgs, _ map[ir.SGName]*ir.SG) error { return nil } diff --git a/pkg/optimize.go/sg.go b/pkg/optimize.go/sg.go index 897c76f8..cc4ddbb2 100644 --- a/pkg/optimize.go/sg.go +++ b/pkg/optimize.go/sg.go @@ -9,6 +9,6 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func ReduceSGRules(sgs map[ir.SGName]*ir.SG, sgName string) error { +func ReduceSGRules(_ map[ir.SGName]*ir.SG, _ string) error { return nil } From 2b7f244db852b6c29894752d91b4cd3e1cf5fc4c Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 14:29:32 +0300 Subject: [PATCH 11/79] added synth prefix --- cmd/subcmds/{output.go => synthOutput.go} | 2 +- pkg/io/confio/acl.go | 2 +- pkg/io/confio/sg.go | 2 +- pkg/io/csvio/acl.go | 2 +- pkg/io/csvio/common.go | 2 +- pkg/io/csvio/sg.go | 2 +- pkg/io/mdio/acl.go | 2 +- pkg/io/mdio/common.go | 2 +- pkg/io/mdio/sg.go | 2 +- pkg/io/tfio/acl.go | 2 +- pkg/io/tfio/common.go | 2 +- pkg/io/tfio/sg.go | 2 +- pkg/ir/sg.go | 56 ++++++++++++----------- 13 files changed, 41 insertions(+), 39 deletions(-) rename cmd/subcmds/{output.go => synthOutput.go} (97%) diff --git a/cmd/subcmds/output.go b/cmd/subcmds/synthOutput.go similarity index 97% rename from cmd/subcmds/output.go rename to cmd/subcmds/synthOutput.go index aa817b7e..ff694c47 100644 --- a/cmd/subcmds/output.go +++ b/cmd/subcmds/synthOutput.go @@ -85,7 +85,7 @@ func writeToFile(outputFile string, data *bytes.Buffer) error { return os.WriteFile(outputFile, data.Bytes(), defaultFilePermission) } -func pickWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { +func pickWriter(args *inArgs, data *bytes.Buffer) (ir.SynthWriter, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: diff --git a/pkg/io/confio/acl.go b/pkg/io/confio/acl.go index 20f06d1a..09231c65 100644 --- a/pkg/io/confio/acl.go +++ b/pkg/io/confio/acl.go @@ -169,7 +169,7 @@ func subnetRef(subnet *configModel.Subnet) *vpcv1.SubnetReference { } } -func (w *Writer) WriteACL(collection *ir.ACLCollection, _ string) error { +func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, _ string) error { updateACL(w.model, collection) return w.writeModel() } diff --git a/pkg/io/confio/sg.go b/pkg/io/confio/sg.go index ee551214..cadf8232 100644 --- a/pkg/io/confio/sg.go +++ b/pkg/io/confio/sg.go @@ -245,7 +245,7 @@ func updateSG(model *configModel.ResourcesContainerModel, collection *ir.SGColle globalIndex = 0 // making test results more predictable } -func (w *Writer) WriteSG(collection *ir.SGCollection, _ string) error { +func (w *Writer) WriteSynthSG(collection *ir.SGCollection, _ string) error { updateSG(w.model, collection) return w.writeModel() } diff --git a/pkg/io/csvio/acl.go b/pkg/io/csvio/acl.go index a5e9c00e..47e9b5ea 100644 --- a/pkg/io/csvio/acl.go +++ b/pkg/io/csvio/acl.go @@ -36,7 +36,7 @@ func ACLPort(p interval.Interval) string { } // Write prints an entire collection of acls as a single CSV table. -func (w *Writer) WriteACL(collection *ir.ACLCollection, vpc string) error { +func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, vpc string) error { if err := w.w.WriteAll(aclHeader()); err != nil { return err } diff --git a/pkg/io/csvio/common.go b/pkg/io/csvio/common.go index 41cd664d..c61e180e 100644 --- a/pkg/io/csvio/common.go +++ b/pkg/io/csvio/common.go @@ -18,7 +18,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// Writer implements ir.Writer +// Writer implements ir.SynthWriter type Writer struct { w *csv.Writer } diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index a10dc8db..78fa772c 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -16,7 +16,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { +func (w *Writer) WriteSynthSG(collection *ir.SGCollection, vpc string) error { if err := w.w.WriteAll(sgHeader()); err != nil { return err } diff --git a/pkg/io/mdio/acl.go b/pkg/io/mdio/acl.go index e593de0e..34fd55c7 100644 --- a/pkg/io/mdio/acl.go +++ b/pkg/io/mdio/acl.go @@ -36,7 +36,7 @@ func ACLPort(p interval.Interval) string { } // Write prints an entire collection of acls as a single MD table. -func (w *Writer) WriteACL(collection *ir.ACLCollection, vpc string) error { +func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, vpc string) error { if err := w.writeAll(aclHeader()); err != nil { return err } diff --git a/pkg/io/mdio/common.go b/pkg/io/mdio/common.go index abfb24a8..fad3d774 100644 --- a/pkg/io/mdio/common.go +++ b/pkg/io/mdio/common.go @@ -20,7 +20,7 @@ import ( const leftAlign = " :--- " -// Writer implements ir.Writer +// Writer implements ir.SynthWriter type Writer struct { w *bufio.Writer } diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index 044ddbca..8535fb19 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -16,7 +16,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { +func (w *Writer) WriteSynthSG(collection *ir.SGCollection, vpc string) error { if err := w.writeAll(sgHeader()); err != nil { return err } diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index e6d36637..b09e3a11 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -18,7 +18,7 @@ import ( ) // WriteACL prints an entire collection of acls as a sequence of terraform resources. -func (w *Writer) WriteACL(c *ir.ACLCollection, vpc string) error { +func (w *Writer) WriteSynthACL(c *ir.ACLCollection, vpc string) error { output := aclCollection(c, vpc).Print() _, err := w.w.WriteString(output) if err != nil { diff --git a/pkg/io/tfio/common.go b/pkg/io/tfio/common.go index 00b9d2b7..60b9f1da 100644 --- a/pkg/io/tfio/common.go +++ b/pkg/io/tfio/common.go @@ -21,7 +21,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// Writer implements ir.Writer +// Writer implements ir.SynthWriter type Writer struct { w *bufio.Writer } diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 1958ec24..6cd5447d 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -19,7 +19,7 @@ import ( ) // WriteSG prints an entire collection of Security Groups as a sequence of terraform resources. -func (w *Writer) WriteSG(c *ir.SGCollection, vpc string) error { +func (w *Writer) WriteSynthSG(c *ir.SGCollection, vpc string) error { output := sgCollection(c, vpc).Print() _, err := w.w.WriteString(output) if err != nil { diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 5cf895ec..b9783071 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -26,37 +26,39 @@ const ( SGResourceFileShareMountTarget SGResource = "fsmt" ) -type SGName string +type ( + SGName string -func (s SGName) String() string { - return string(s) -} + RemoteType interface { + fmt.Stringer + // *netset.IPBlock | SGName + } -type RemoteType interface { - fmt.Stringer - // *netset.IPBlock | SGName -} + SGRule struct { + Direction Direction + Remote RemoteType + Protocol netp.Protocol + Local *netset.IPBlock + Explanation string + } -type SGRule struct { - Direction Direction - Remote RemoteType - Protocol netp.Protocol - Local *netset.IPBlock - Explanation string -} + SG struct { + InboundRules []SGRule + OutboundRules []SGRule + Attached []ID + } -type SG struct { - InboundRules []SGRule - OutboundRules []SGRule - Attached []ID -} + SGCollection struct { + SGs map[ID]map[SGName]*SG + } -type SGCollection struct { - SGs map[ID]map[SGName]*SG -} + SynthSGWriter interface { + WriteSynthSG(sgColl *SGCollection, vpc string) error + } +) -type SGWriter interface { - WriteSG(sgColl *SGCollection, vpc string) error +func (s SGName) String() string { + return string(s) } func (r *SGRule) isRedundant(rules []SGRule) bool { @@ -110,8 +112,8 @@ func (a *SG) AllRules() []SGRule { return append(a.InboundRules, a.OutboundRules...) } -func (c *SGCollection) Write(w Writer, vpc string) error { - return w.WriteSG(c, vpc) +func (c *SGCollection) Write(w SynthWriter, vpc string) error { + return w.WriteSynthSG(c, vpc) } func (c *SGCollection) SortedSGNames(vpc ID) []SGName { From 8203f7884c890c1c243b51024674a2d54e0b4275 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 14:45:58 +0300 Subject: [PATCH 12/79] unexported two functions --- pkg/io/csvio/acl.go | 32 ++++++++++++++++---------------- pkg/io/csvio/sg.go | 8 ++++---- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/pkg/io/csvio/acl.go b/pkg/io/csvio/acl.go index 47e9b5ea..308910a1 100644 --- a/pkg/io/csvio/acl.go +++ b/pkg/io/csvio/acl.go @@ -17,6 +17,20 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) +// Write prints an entire collection of acls as a single CSV table. +func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, vpc string) error { + if err := w.w.WriteAll(aclHeader()); err != nil { + return err + } + for _, subnet := range collection.SortedACLSubnets(vpc) { + vpcName := ir.VpcFromScopedResource(subnet) + if err := w.w.WriteAll(makeACLTable(collection.ACLs[vpcName][subnet], subnet)); err != nil { + return err + } + } + return nil +} + func makeACLTable(t *ir.ACL, subnet string) [][]string { rules := t.Rules() rows := make([][]string, len(rules)) @@ -26,7 +40,7 @@ func makeACLTable(t *ir.ACL, subnet string) [][]string { return rows } -func ACLPort(p interval.Interval) string { +func aclPort(p interval.Interval) string { switch { case p.Start() == netp.MinPort && p.End() == netp.MaxPort: return "any port" //nolint:goconst // independent decision for SG and ACL @@ -35,20 +49,6 @@ func ACLPort(p interval.Interval) string { } } -// Write prints an entire collection of acls as a single CSV table. -func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, vpc string) error { - if err := w.w.WriteAll(aclHeader()); err != nil { - return err - } - for _, subnet := range collection.SortedACLSubnets(vpc) { - vpcName := ir.VpcFromScopedResource(subnet) - if err := w.w.WriteAll(makeACLTable(collection.ACLs[vpcName][subnet], subnet)); err != nil { - return err - } - } - return nil -} - func action(a ir.Action) string { if a == ir.Deny { return "Deny" @@ -101,7 +101,7 @@ func printIP(ip *netset.IPBlock, protocol netp.Protocol, isSource bool) string { } else { r = p.DstPorts() } - return fmt.Sprintf("%v, %v", ipString, ACLPort(r)) + return fmt.Sprintf("%v, %v", ipString, aclPort(r)) case netp.AnyProtocol: return ipString default: diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index 78fa772c..aa320afe 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -45,7 +45,7 @@ func makeSGRow(rule *ir.SGRule, sgName ir.SGName) []string { return []string{ string(sgName), direction(rule.Direction), - sGRemoteType(rule.Remote), + sgRemoteType(rule.Remote), sgRemote(rule.Remote), printProtocolName(rule.Protocol), printProtocolParams(rule.Protocol, rule.Direction == ir.Inbound), @@ -62,7 +62,7 @@ func makeSGTable(t *ir.SG, sgName ir.SGName) [][]string { return rows } -func sGPort(p interval.Interval) string { +func sgPort(p interval.Interval) string { switch { case p.Start() == netp.MinPort && p.End() == netp.MaxPort: return "any port" @@ -71,7 +71,7 @@ func sGPort(p interval.Interval) string { } } -func sGRemoteType(t ir.RemoteType) string { +func sgRemoteType(t ir.RemoteType) string { switch t := t.(type) { case *netset.IPBlock: if t.Size() == 1 { @@ -112,7 +112,7 @@ func printProtocolParams(protocol netp.Protocol, isSource bool) string { } else { r = p.DstPorts() } - return sGPort(r) + return sgPort(r) case netp.AnyProtocol: return "" default: From 5fbeefc1455268fb3a99ed2bc33a2e2154f51c93 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 14:47:59 +0300 Subject: [PATCH 13/79] wip --- pkg/io/confio/common.go | 2 +- pkg/ir/acl.go | 54 +++++++++++++++++++++-------------------- pkg/ir/common.go | 16 ++++++------ test/end_to_end_test.go | 2 +- 4 files changed, 39 insertions(+), 35 deletions(-) diff --git a/pkg/io/confio/common.go b/pkg/io/confio/common.go index e3e86f61..97aa4274 100644 --- a/pkg/io/confio/common.go +++ b/pkg/io/confio/common.go @@ -12,7 +12,7 @@ import ( configModel "github.com/np-guard/cloud-resource-collector/pkg/ibm/datamodel" ) -// Writer implements ir.Writer +// Writer implements ir.SynthWriter type Writer struct { w *bufio.Writer model *configModel.ResourcesContainerModel diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 41248c82..993e5047 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -15,36 +15,38 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) -type Action string +type ( + Action string + + ACLRule struct { + Action Action + Direction Direction + Source *netset.IPBlock + Destination *netset.IPBlock + Protocol netp.Protocol + Explanation string + } + + ACL struct { + Subnet string + Internal []ACLRule + External []ACLRule + } + + ACLCollection struct { + ACLs map[ID]map[string]*ACL + } + + SynthACLWriter interface { + WriteSynthACL(aclColl *ACLCollection, vpc string) error + } +) const ( Allow Action = "allow" Deny Action = "deny" ) -type ACLRule struct { - Action Action - Direction Direction - Source *netset.IPBlock - Destination *netset.IPBlock - Protocol netp.Protocol - Explanation string -} - -type ACL struct { - Subnet string - Internal []ACLRule - External []ACLRule -} - -type ACLCollection struct { - ACLs map[ID]map[string]*ACL -} - -type ACLWriter interface { - WriteACL(aclColl *ACLCollection, vpc string) error -} - func (r *ACLRule) isRedundant(rules []ACLRule) bool { for i := range rules { if rules[i].mustSupersede(r) { @@ -123,8 +125,8 @@ func (c *ACLCollection) LookupOrCreate(name string) *ACL { return newACL } -func (c *ACLCollection) Write(w Writer, vpc string) error { - return w.WriteACL(c, vpc) +func (c *ACLCollection) Write(w SynthWriter, vpc string) error { + return w.WriteSynthACL(c, vpc) } func (c *ACLCollection) SortedACLSubnets(vpc string) []string { diff --git a/pkg/ir/common.go b/pkg/ir/common.go index e10b1265..17b2a69d 100644 --- a/pkg/ir/common.go +++ b/pkg/ir/common.go @@ -5,18 +5,20 @@ SPDX-License-Identifier: Apache-2.0 package ir -type Direction string +type ( + Direction string + + SynthWriter interface { + SynthACLWriter + SynthSGWriter + } +) const ( Outbound Direction = "outbound" Inbound Direction = "inbound" ) -type Writer interface { - ACLWriter - SGWriter -} - type Collection interface { - Write(writer Writer, vpc string) error + Write(writer SynthWriter, vpc string) error } diff --git a/test/end_to_end_test.go b/test/end_to_end_test.go index 695a98d5..484ec4c0 100644 --- a/test/end_to_end_test.go +++ b/test/end_to_end_test.go @@ -146,7 +146,7 @@ func shrinkWhitespace(s string) string { func write(collection ir.Collection, outputFormat, conn, vpc string) (text string, err error) { buf := new(bytes.Buffer) - var writer ir.Writer + var writer ir.SynthWriter switch outputFormat { case "csv": writer = csvio.NewWriter(buf) From 19c5483b9cfdf69dda87c3cf35a0bb646b915f3b Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 14:49:27 +0300 Subject: [PATCH 14/79] rename folder name --- pkg/{optimize.go => optimize}/sg.go | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkg/{optimize.go => optimize}/sg.go (100%) diff --git a/pkg/optimize.go/sg.go b/pkg/optimize/sg.go similarity index 100% rename from pkg/optimize.go/sg.go rename to pkg/optimize/sg.go From 74737e7b523a2965cd0310d1c60a323df1d484fc Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 14:52:00 +0300 Subject: [PATCH 15/79] renaming --- cmd/subcmds/optimizeSG.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index 8cdeec92..ac3c4fdc 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -11,7 +11,7 @@ import ( "github.com/spf13/cobra" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" - "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize.go" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" ) func NewOptimizeSGCommand(args *inArgs) *cobra.Command { From 02030aca2af8c3896f5a4a7ccd68547eaa609f6a Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 15:32:22 +0300 Subject: [PATCH 16/79] updated --- pkg/io/confio/parse_sgs.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index daf044cc..a079f9c0 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -19,20 +19,25 @@ import ( ) // ReadSG translates SGs from a config_object file to map[ir.SGName]*SG -func ReadSGs(filename string) (map[ir.SGName]*ir.SG, error) { +func ReadSGs(filename string) (*ir.SGCollection, error) { config, err := readModel(filename) if err != nil { return nil, err } - result := make(map[ir.SGName]*ir.SG, len(config.SecurityGroupList)) + result := ir.NewSGCollection() + for _, sg := range config.SecurityGroupList { inbound, outbound, err := translateSGRules(&sg.SecurityGroup) if err != nil { return nil, err } if sg.Name != nil { - result[ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} + vpcName := *sg.VPC.Name + if result.SGs[vpcName] == nil { + result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) + } + result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} } } return result, nil From 4fb97b4d18cd3e12a305b9207e87e0124ad534ed Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 15:33:50 +0300 Subject: [PATCH 17/79] updated template --- cmd/subcmds/optimizeOutput.go | 2 +- cmd/subcmds/optimizeSG.go | 2 +- cmd/subcmds/root.go | 2 +- pkg/io/confio/parse_sgs.go | 4 ++-- pkg/optimize/sg.go | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go index 9ac7f8ce..af92e337 100644 --- a/cmd/subcmds/optimizeOutput.go +++ b/cmd/subcmds/optimizeOutput.go @@ -9,6 +9,6 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func writeOptimizeOutput(_ *inArgs, _ map[ir.SGName]*ir.SG) error { +func writeOptimizeOutput(_ *inArgs, _ ir.Collection) error { return nil } diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index ac3c4fdc..57ee6c32 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -21,7 +21,7 @@ func NewOptimizeSGCommand(args *inArgs) *cobra.Command { Long: `OptimizeSG attempts to reduce the number of security group rules in a SG without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return nil + return optimization(cmd, args) }, } diff --git a/cmd/subcmds/root.go b/cmd/subcmds/root.go index 471b55d5..1f47e591 100644 --- a/cmd/subcmds/root.go +++ b/cmd/subcmds/root.go @@ -60,7 +60,7 @@ func NewRootCommand() *cobra.Command { rootCmd.MarkFlagsMutuallyExclusive(outputFileFlag, outputDirFlag) rootCmd.AddCommand(NewSynthCommand(args)) - // Todo: add optimize command + rootCmd.AddCommand(NewOptimizeCommand(args)) rootCmd.CompletionOptions.HiddenDefaultCmd = true rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) // disable help command. should use --help flag instead diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index fa6f7685..b7892297 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -7,6 +7,6 @@ package confio import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -func ReadSGs(filename string) (map[ir.SGName]*ir.SG, error) { - return map[ir.SGName]*ir.SG{}, nil +func ReadSGs(filename string) (*ir.SGCollection, error) { + return nil, nil } diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index cc4ddbb2..f3301962 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -9,6 +9,6 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func ReduceSGRules(_ map[ir.SGName]*ir.SG, _ string) error { +func ReduceSGRules(_ *ir.SGCollection, _ string) error { return nil } From 0c9cfe29f5f7591ca8660ae1ef5b97d1c17e9281 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 26 Aug 2024 17:27:34 +0300 Subject: [PATCH 18/79] wip --- cmd/subcmds/optimizeOutput.go | 24 ++++++++++++++- cmd/subcmds/optimizeSG.go | 3 +- cmd/subcmds/outputCommon.go | 58 +++++++++++++++++++++++++++++++++++ cmd/subcmds/synthOutput.go | 56 ++++++--------------------------- pkg/io/tfio/acl.go | 4 +++ pkg/io/tfio/sg.go | 4 +++ pkg/ir/acl.go | 10 +++++- pkg/ir/common.go | 17 +++++++--- pkg/ir/sg.go | 10 +++++- pkg/synth/acl.go | 2 +- pkg/synth/common.go | 2 +- pkg/synth/sg.go | 2 +- test/end_to_end_test.go | 8 ++--- 13 files changed, 139 insertions(+), 61 deletions(-) create mode 100644 cmd/subcmds/outputCommon.go diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go index af92e337..1d20542c 100644 --- a/cmd/subcmds/optimizeOutput.go +++ b/cmd/subcmds/optimizeOutput.go @@ -6,9 +6,31 @@ SPDX-License-Identifier: Apache-2.0 package subcmds import ( + "bufio" + "bytes" + "fmt" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func writeOptimizeOutput(_ *inArgs, _ ir.Collection) error { +func writeOptimizeOutput(args *inArgs, collection ir.OptimizeCollection, vpcNames []string) error { + if err := checkOutputFlags(args); err != nil { + return err + } + _, isACLCollection := collection.(*ir.ACLCollection) + if err := writeLocals(args, vpcNames, isACLCollection); err != nil { + return err + } return nil } + +func pickOptimizeWriter(args *inArgs, data *bytes.Buffer) (ir.SynthWriter, error) { + w := bufio.NewWriter(data) + switch args.outputFmt { + case tfOutputFormat: + return tfio.NewWriter(w), nil + default: + return nil, fmt.Errorf("bad output format: %q", args.outputFmt) + } +} diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index 57ee6c32..53f83477 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -12,6 +12,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) func NewOptimizeSGCommand(args *inArgs) *cobra.Command { @@ -40,5 +41,5 @@ func optimization(cmd *cobra.Command, args *inArgs) error { if optimize.ReduceSGRules(sgs, args.sgName) != nil { return err } - return writeOptimizeOutput(args, sgs) + return writeOptimizeOutput(args, sgs, utils.MapKeys(sgs.SGs)) } diff --git a/cmd/subcmds/outputCommon.go b/cmd/subcmds/outputCommon.go new file mode 100644 index 00000000..d663670c --- /dev/null +++ b/cmd/subcmds/outputCommon.go @@ -0,0 +1,58 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package subcmds + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +func checkOutputFlags(args *inArgs) error { + if err := updateOutputFormat(args); err != nil { + return err + } + if args.outputDir != "" && args.outputFmt == apiOutputFormat { + return fmt.Errorf("-d cannot be used with format json") + } + return nil +} + +func writeToFile(outputFile string, data *bytes.Buffer) error { + if outputFile == "" { + fmt.Println(data.String()) + return nil + } + return os.WriteFile(outputFile, data.Bytes(), defaultFilePermission) +} + +func writeLocals(args *inArgs, vpcNames []ir.ID, isACL bool) error { + if !args.locals { + return nil + } + if args.outputFmt != tfOutputFormat { + return fmt.Errorf("--locals flag requires setting the output format to tf") + } + + var data *bytes.Buffer + var err error + if data, err = tfio.WriteLocals(vpcNames, isACL); err != nil { + return err + } + + outputFile := "" + suffix := "/locals.tf" + if args.outputDir != "" { + outputFile = args.outputDir + suffix + } else if args.outputFile != "" { + outputFile = filepath.Dir(args.outputFile) + suffix + } + return writeToFile(outputFile, data) +} diff --git a/cmd/subcmds/synthOutput.go b/cmd/subcmds/synthOutput.go index ff694c47..c1ba8a0d 100644 --- a/cmd/subcmds/synthOutput.go +++ b/cmd/subcmds/synthOutput.go @@ -10,7 +10,6 @@ import ( "bytes" "fmt" "os" - "path/filepath" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/csvio" @@ -23,26 +22,24 @@ import ( const defaultFilePermission = 0o644 const defaultDirectoryPermission = 0o755 -func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error { - if err := updateOutputFormat(args); err != nil { +func writeOutput(args *inArgs, collection ir.SynthCollection, vpcNames []ir.ID) error { + if err := checkOutputFlags(args); err != nil { return err } - if args.outputDir != "" && args.outputFmt == apiOutputFormat { - return fmt.Errorf("-d cannot be used with format json") - } if args.outputDir != "" { // create the directory if needed if err := os.MkdirAll(args.outputDir, defaultDirectoryPermission); err != nil { return err } } - if err := writeLocals(args, collection, vpcNames); err != nil { + _, isACLCollection := collection.(*ir.ACLCollection) + if err := writeLocals(args, vpcNames, isACLCollection); err != nil { return err } var data *bytes.Buffer var err error if args.outputDir == "" { - if data, err = writeCollection(args, collection, ""); err != nil { + if data, err = writeSynthCollection(args, collection, ""); err != nil { return err } return writeToFile(args.outputFile, data) @@ -55,7 +52,7 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error if args.prefix != "" { args.outputFile = args.outputDir + "/" + args.prefix + "_" + suffix } - if data, err = writeCollection(args, collection, vpc); err != nil { + if data, err = writeSynthCollection(args, collection, vpc); err != nil { return err } if err := writeToFile(args.outputFile, data); err != nil { @@ -65,27 +62,19 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error return nil } -func writeCollection(args *inArgs, collection ir.Collection, vpc string) (*bytes.Buffer, error) { +func writeSynthCollection(args *inArgs, collection ir.SynthCollection, vpc string) (*bytes.Buffer, error) { var data bytes.Buffer - writer, err := pickWriter(args, &data) + writer, err := pickSynthWriter(args, &data) if err != nil { return nil, err } - if err := collection.Write(writer, vpc); err != nil { + if err := collection.WriteSynth(writer, vpc); err != nil { return nil, err } return &data, nil } -func writeToFile(outputFile string, data *bytes.Buffer) error { - if outputFile == "" { - fmt.Println(data.String()) - return nil - } - return os.WriteFile(outputFile, data.Bytes(), defaultFilePermission) -} - -func pickWriter(args *inArgs, data *bytes.Buffer) (ir.SynthWriter, error) { +func pickSynthWriter(args *inArgs, data *bytes.Buffer) (ir.SynthWriter, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: @@ -100,28 +89,3 @@ func pickWriter(args *inArgs, data *bytes.Buffer) (ir.SynthWriter, error) { return nil, fmt.Errorf("bad output format: %q", args.outputFmt) } } - -func writeLocals(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error { - if !args.locals { - return nil - } - if args.outputFmt != tfOutputFormat { - return fmt.Errorf("--locals flag requires setting the output format to tf") - } - - _, isACLCollection := collection.(*ir.ACLCollection) - var data *bytes.Buffer - var err error - if data, err = tfio.WriteLocals(vpcNames, isACLCollection); err != nil { - return err - } - - outputFile := "" - suffix := "/locals.tf" - if args.outputDir != "" { - outputFile = args.outputDir + suffix - } else if args.outputFile != "" { - outputFile = filepath.Dir(args.outputFile) + suffix - } - return writeToFile(outputFile, data) -} diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index b09e3a11..1c0d7cda 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -28,6 +28,10 @@ func (w *Writer) WriteSynthACL(c *ir.ACLCollection, vpc string) error { return err } +func (w *Writer) WriteOptimizeACL(c *ir.ACLCollection) error { + return nil +} + func aclProtocol(t netp.Protocol) []tf.Block { switch p := t.(type) { case netp.TCPUDP: diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 6cd5447d..ddb66ac7 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -29,6 +29,10 @@ func (w *Writer) WriteSynthSG(c *ir.SGCollection, vpc string) error { return err } +func (w *Writer) WriteOptimizeSG(c *ir.SGCollection, vpc string) error { + return nil +} + func value(x interface{}) string { switch v := x.(type) { case *netset.IPBlock: diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 993e5047..9075a28e 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -40,6 +40,10 @@ type ( SynthACLWriter interface { WriteSynthACL(aclColl *ACLCollection, vpc string) error } + + OptimizeACLWriter interface { + WriteOptimizeACL(aclColl *ACLCollection) error + } ) const ( @@ -125,10 +129,14 @@ func (c *ACLCollection) LookupOrCreate(name string) *ACL { return newACL } -func (c *ACLCollection) Write(w SynthWriter, vpc string) error { +func (c *ACLCollection) WriteSynth(w SynthWriter, vpc string) error { return w.WriteSynthACL(c, vpc) } +func (c *ACLCollection) WriteOptimize(w OptimizeWriter) error { + return w.WriteOptimizeACL(c) +} + func (c *ACLCollection) SortedACLSubnets(vpc string) []string { if vpc == "" { return utils.SortedAllInnerMapsKeys(c.ACLs) diff --git a/pkg/ir/common.go b/pkg/ir/common.go index 17b2a69d..5f9fddd8 100644 --- a/pkg/ir/common.go +++ b/pkg/ir/common.go @@ -8,17 +8,26 @@ package ir type ( Direction string + SynthCollection interface { + WriteSynth(writer SynthWriter, vpc string) error + } + + OptimizeCollection interface { + WriteOptimize(writer OptimizeWriter) error + } + SynthWriter interface { SynthACLWriter SynthSGWriter } + + OptimizeWriter interface { + OptimizeACLWriter + OptimizeSGWriter + } ) const ( Outbound Direction = "outbound" Inbound Direction = "inbound" ) - -type Collection interface { - Write(writer SynthWriter, vpc string) error -} diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index b9783071..917125e3 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -55,6 +55,10 @@ type ( SynthSGWriter interface { WriteSynthSG(sgColl *SGCollection, vpc string) error } + + OptimizeSGWriter interface { + WriteOptimizeSG(sgColl *SGCollection) error + } ) func (s SGName) String() string { @@ -112,10 +116,14 @@ func (a *SG) AllRules() []SGRule { return append(a.InboundRules, a.OutboundRules...) } -func (c *SGCollection) Write(w SynthWriter, vpc string) error { +func (c *SGCollection) WriteSynth(w SynthWriter, vpc string) error { return w.WriteSynthSG(c, vpc) } +func (c *SGCollection) WriteOptimize(w OptimizeWriter) error { + return w.WriteOptimizeSG(c) +} + func (c *SGCollection) SortedSGNames(vpc ID) []SGName { if vpc == "" { return utils.SortedAllInnerMapsKeys(c.SGs) diff --git a/pkg/synth/acl.go b/pkg/synth/acl.go index ab16eb35..50e999fd 100644 --- a/pkg/synth/acl.go +++ b/pkg/synth/acl.go @@ -28,7 +28,7 @@ func NewACLSynthesizer(s *ir.Spec, single bool) Synthesizer { return &ACLSynthesizer{spec: s, singleACL: single, result: ir.NewACLCollection()} } -func (a *ACLSynthesizer) Synth() ir.Collection { +func (a *ACLSynthesizer) Synth() ir.SynthCollection { return a.makeACL() } diff --git a/pkg/synth/common.go b/pkg/synth/common.go index 9833c121..5ce7b220 100644 --- a/pkg/synth/common.go +++ b/pkg/synth/common.go @@ -15,7 +15,7 @@ import ( type ( Synthesizer interface { - Synth() ir.Collection + Synth() ir.SynthCollection } namedAddrs struct { diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index 054171cf..13938223 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -23,7 +23,7 @@ func NewSGSynthesizer(s *ir.Spec, _ bool) Synthesizer { return &SGSynthesizer{spec: s, result: ir.NewSGCollection()} } -func (s *SGSynthesizer) Synth() ir.Collection { +func (s *SGSynthesizer) Synth() ir.SynthCollection { return s.makeSG() } diff --git a/test/end_to_end_test.go b/test/end_to_end_test.go index 484ec4c0..a3cceeb4 100644 --- a/test/end_to_end_test.go +++ b/test/end_to_end_test.go @@ -144,7 +144,7 @@ func shrinkWhitespace(s string) string { return regexp.MustCompile(`[ \t]+`).ReplaceAllString(s, " ") } -func write(collection ir.Collection, outputFormat, conn, vpc string) (text string, err error) { +func write(collection ir.SynthCollection, outputFormat, conn, vpc string) (text string, err error) { buf := new(bytes.Buffer) var writer ir.SynthWriter switch outputFormat { @@ -160,7 +160,7 @@ func write(collection ir.Collection, outputFormat, conn, vpc string) (text strin if err != nil { return "", err } - err = collection.Write(writer, vpc) + err = collection.WriteSynth(writer, vpc) if err != nil { return "", err } @@ -175,7 +175,7 @@ func readExpectedFile(filename string) string { return shrinkWhitespace(string(buf)) } -func writeSingleFile(testCase TestCase, t *testing.T, collection ir.Collection) { +func writeSingleFile(testCase TestCase, t *testing.T, collection ir.SynthCollection) { actual, err := write(collection, testCase.outputFormat, fmt.Sprintf("../test/%s", testCase.resolve(defaultConfigName)), "") if err != nil { t.Fatal(err) @@ -188,7 +188,7 @@ func writeSingleFile(testCase TestCase, t *testing.T, collection ir.Collection) } } -func writeMultipleFiles(testCase TestCase, t *testing.T, collection ir.Collection, s *ir.Spec) { +func writeMultipleFiles(testCase TestCase, t *testing.T, collection ir.SynthCollection, s *ir.Spec) { for vpcName := range s.Defs.VPCs { actual, err := write(collection, testCase.outputFormat, fmt.Sprintf("../test/%s", testCase.resolve(defaultConfigName)), vpcName) if err != nil { From eebd628a1ff4be48a286ca963910e8ec6bbb2f21 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 27 Aug 2024 14:56:06 +0300 Subject: [PATCH 19/79] template --- cmd/subcmds/optimize.go | 23 ++++++++++++++++- cmd/subcmds/optimizeOutput.go | 20 +++++++++++++-- cmd/subcmds/optimizeSG.go | 22 +--------------- cmd/subcmds/outputCommon.go | 3 +++ cmd/subcmds/root.go | 48 +++++++++++++++++------------------ cmd/subcmds/synth.go | 7 +++++ pkg/io/tfio/common.go | 2 +- pkg/io/tfio/sg.go | 2 +- pkg/ir/acl.go | 4 +++ pkg/ir/sg.go | 4 +++ pkg/optimize/common.go | 19 ++++++++++++++ pkg/optimize/sg.go | 26 ++++++++++++++++++- 12 files changed, 129 insertions(+), 51 deletions(-) create mode 100644 pkg/optimize/common.go diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index 877662a9..4b215fe1 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -5,7 +5,13 @@ SPDX-License-Identifier: Apache-2.0 package subcmds -import "github.com/spf13/cobra" +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" +) func NewOptimizeCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ @@ -14,7 +20,22 @@ func NewOptimizeCommand(args *inArgs) *cobra.Command { Long: `optimization of existing SG (nACLS are not supported yet)`, } + // flags + cmd.Flags().StringVarP(&args.firewallName, firewallNameFlag, "s", "", "which vpcFirewall to optimize") + + // flags settings + _ = cmd.MarkPersistentFlagRequired(firewallNameFlag) // temporary + + // sub cmds cmd.AddCommand(NewOptimizeSGCommand(args)) return cmd } + +func optimization(cmd *cobra.Command, args *inArgs, newOptimizer optimize.Optimizer) error { + cmd.SilenceUsage = true // if we got this far, flags are syntactically correct, so no need to print usage + if err := newOptimizer.ParseCollection(args.configFile); err != nil { + return fmt.Errorf("could not parse config file %v: %w", args.configFile, err) + } + return writeOptimizeOutput(args, newOptimizer.Optimize(), newOptimizer.VpcNames()) +} diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go index 1d20542c..2b602f1c 100644 --- a/cmd/subcmds/optimizeOutput.go +++ b/cmd/subcmds/optimizeOutput.go @@ -22,10 +22,26 @@ func writeOptimizeOutput(args *inArgs, collection ir.OptimizeCollection, vpcName if err := writeLocals(args, vpcNames, isACLCollection); err != nil { return err } - return nil + data, err := writeOptimizeCollection(args, collection) + if err != nil { + return err + } + return writeToFile(args.outputFile, data) +} + +func writeOptimizeCollection(args *inArgs, collection ir.OptimizeCollection) (*bytes.Buffer, error) { + var data bytes.Buffer + writer, err := pickOptimizeWriter(args, &data) + if err != nil { + return nil, err + } + if err := collection.WriteOptimize(writer); err != nil { + return nil, err + } + return &data, nil } -func pickOptimizeWriter(args *inArgs, data *bytes.Buffer) (ir.SynthWriter, error) { +func pickOptimizeWriter(args *inArgs, data *bytes.Buffer) (ir.OptimizeWriter, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index 53f83477..6a07c367 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -6,13 +6,9 @@ SPDX-License-Identifier: Apache-2.0 package subcmds import ( - "fmt" - "github.com/spf13/cobra" - "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" - "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) func NewOptimizeSGCommand(args *inArgs) *cobra.Command { @@ -22,24 +18,8 @@ func NewOptimizeSGCommand(args *inArgs) *cobra.Command { Long: `OptimizeSG attempts to reduce the number of security group rules in a SG without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return optimization(cmd, args) + return optimization(cmd, args, optimize.NewSGOptimizer(args.firewallName)) }, } - - cmd.Flags().StringVarP(&args.sgName, sgNameFlag, "s", "", "which SG to optimize") - _ = cmd.MarkFlagRequired(sgNameFlag) // Todo: delete this line. if sgName flag is not supplied - optimize all SGs - return cmd } - -func optimization(cmd *cobra.Command, args *inArgs) error { - cmd.SilenceUsage = true // if we got this far, flags are syntactically correct, so no need to print usage - sgs, err := confio.ReadSGs(args.configFile) - if err != nil { - return fmt.Errorf("could not parse config file %v: %w", args.configFile, err) - } - if optimize.ReduceSGRules(sgs, args.sgName) != nil { - return err - } - return writeOptimizeOutput(args, sgs, utils.MapKeys(sgs.SGs)) -} diff --git a/cmd/subcmds/outputCommon.go b/cmd/subcmds/outputCommon.go index d663670c..55872136 100644 --- a/cmd/subcmds/outputCommon.go +++ b/cmd/subcmds/outputCommon.go @@ -16,6 +16,9 @@ import ( ) func checkOutputFlags(args *inArgs) error { + if args.outputDir != "" && args.outputFile != "" { + return fmt.Errorf("only one of -d and -o can be supplied") + } if err := updateOutputFormat(args); err != nil { return err } diff --git a/cmd/subcmds/root.go b/cmd/subcmds/root.go index 1f47e591..a6e13486 100644 --- a/cmd/subcmds/root.go +++ b/cmd/subcmds/root.go @@ -13,27 +13,27 @@ import ( ) const ( - configFlag = "config" - specFlag = "spec" - outputFmtFlag = "format" - outputFileFlag = "output-file" - outputDirFlag = "output-dir" - prefixFlag = "prefix" - sgNameFlag = "sg-name" - singleACLFlag = "single" - localsFlag = "locals" + configFlag = "config" + specFlag = "spec" + outputFmtFlag = "format" + outputFileFlag = "output-file" + outputDirFlag = "output-dir" + prefixFlag = "prefix" + firewallNameFlag = "firewall-name" + singleACLFlag = "single" + localsFlag = "locals" ) type inArgs struct { - configFile string - specFile string - outputFmt string - outputFile string - outputDir string - prefix string - sgName string - singleacl bool - locals bool + configFile string + specFile string + outputFmt string + outputFile string + outputDir string + prefix string + firewallName string + singleacl bool + locals bool } func NewRootCommand() *cobra.Command { @@ -45,25 +45,25 @@ func NewRootCommand() *cobra.Command { Long: `Tool for automatic synthesis of VPC network configurations, namely Network ACLs and Security Groups.`, } + // flags rootCmd.PersistentFlags().StringVarP(&args.configFile, configFlag, "c", "", "JSON file containing a configuration object of existing resources") rootCmd.PersistentFlags().StringVarP(&args.outputFmt, outputFmtFlag, "f", "", "Output format; "+mustBeOneOf(outputFormats)) rootCmd.PersistentFlags().StringVarP(&args.outputFile, outputFileFlag, "o", "", "Write all generated resources to the specified file.") - rootCmd.PersistentFlags().StringVarP(&args.outputDir, outputDirFlag, "d", "", - "Write generated resources to files in the specified directory, one file per VPC.") - rootCmd.PersistentFlags().StringVarP(&args.prefix, prefixFlag, "p", "", "The prefix of the files that will be created.") rootCmd.PersistentFlags().BoolVarP(&args.locals, localsFlag, "l", false, "whether to generate a locals.tf file (only possible when the output format is tf)") - rootCmd.PersistentFlags().SortFlags = false + // flags set for all commands + rootCmd.PersistentFlags().SortFlags = false _ = rootCmd.MarkPersistentFlagRequired(configFlag) - rootCmd.MarkFlagsMutuallyExclusive(outputFileFlag, outputDirFlag) + // sub cmds rootCmd.AddCommand(NewSynthCommand(args)) rootCmd.AddCommand(NewOptimizeCommand(args)) + // disable help command. should use --help flag instead rootCmd.CompletionOptions.HiddenDefaultCmd = true - rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) // disable help command. should use --help flag instead + rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) return rootCmd } diff --git a/cmd/subcmds/synth.go b/cmd/subcmds/synth.go index 04e4cc1c..b0b2210b 100644 --- a/cmd/subcmds/synth.go +++ b/cmd/subcmds/synth.go @@ -21,9 +21,16 @@ func NewSynthCommand(args *inArgs) *cobra.Command { --config and --spec parameters must be supplied.`, } + // flags cmd.PersistentFlags().StringVarP(&args.specFile, specFlag, "s", "", "JSON file containing spec file") + cmd.PersistentFlags().StringVarP(&args.outputDir, outputDirFlag, "d", "", + "Write generated resources to files in the specified directory, one file per VPC.") + cmd.PersistentFlags().StringVarP(&args.prefix, prefixFlag, "p", "", "The prefix of the files that will be created.") + + // flags settings _ = cmd.MarkPersistentFlagRequired(specFlag) + // sub cmds cmd.AddCommand(NewSynthACLCommand(args)) cmd.AddCommand(NewSynthSGCommand(args)) diff --git a/pkg/io/tfio/common.go b/pkg/io/tfio/common.go index 60b9f1da..7726b591 100644 --- a/pkg/io/tfio/common.go +++ b/pkg/io/tfio/common.go @@ -21,7 +21,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// Writer implements ir.SynthWriter +// Writer implements ir.SynthWriter and ir.OptimizeWriter type Writer struct { w *bufio.Writer } diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index ddb66ac7..981f44cb 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -29,7 +29,7 @@ func (w *Writer) WriteSynthSG(c *ir.SGCollection, vpc string) error { return err } -func (w *Writer) WriteOptimizeSG(c *ir.SGCollection, vpc string) error { +func (w *Writer) WriteOptimizeSG(c *ir.SGCollection) error { return nil } diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 9075a28e..094ee726 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -129,6 +129,10 @@ func (c *ACLCollection) LookupOrCreate(name string) *ACL { return newACL } +func (c *ACLCollection) VpcNames() []string { + return utils.MapKeys(c.ACLs) +} + func (c *ACLCollection) WriteSynth(w SynthWriter, vpc string) error { return w.WriteSynthACL(c, vpc) } diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 917125e3..f92d94e8 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -116,6 +116,10 @@ func (a *SG) AllRules() []SGRule { return append(a.InboundRules, a.OutboundRules...) } +func (c *SGCollection) VpcNames() []string { + return utils.MapKeys(c.SGs) +} + func (c *SGCollection) WriteSynth(w SynthWriter, vpc string) error { return w.WriteSynthSG(c, vpc) } diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go new file mode 100644 index 00000000..d0aa9e52 --- /dev/null +++ b/pkg/optimize/common.go @@ -0,0 +1,19 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + +type Optimizer interface { + // read the collection from the config object file + ParseCollection(filename string) error + + // optimize number of SG/nACL rules + Optimize() ir.OptimizeCollection + + // returns a slice of all vpc names. used to generate locals file + VpcNames() []string +} diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index f3301962..4c74a514 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -6,9 +6,33 @@ SPDX-License-Identifier: Apache-2.0 package optimize import ( + "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) -func ReduceSGRules(_ *ir.SGCollection, _ string) error { +type SGOptimizer struct { + sgCollection *ir.SGCollection + sgName string +} + +func NewSGOptimizer(sgName string) Optimizer { + return &SGOptimizer{sgCollection: nil, sgName: sgName} +} + +func (s *SGOptimizer) ParseCollection(filename string) error { + c, err := confio.ReadSGs(filename) + if err != nil { + return err + } + s.sgCollection = c return nil } + +func (s *SGOptimizer) Optimize() ir.OptimizeCollection { + return s.sgCollection +} + +func (s *SGOptimizer) VpcNames() []string { + return utils.MapKeys(s.sgCollection.SGs) +} From 26473b326f930a9b34d054add9a954084888f15e Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 28 Aug 2024 16:32:19 +0300 Subject: [PATCH 20/79] done --- cmd/subcmds/synth.go | 2 +- pkg/io/confio/parse_sgs.go | 4 ++- pkg/io/tfio/acl.go | 2 +- pkg/io/tfio/sg.go | 57 ++++++++++++++++++++++++-------------- pkg/ir/acl.go | 18 ++++++------ pkg/ir/sg.go | 10 ++++--- 6 files changed, 56 insertions(+), 37 deletions(-) diff --git a/cmd/subcmds/synth.go b/cmd/subcmds/synth.go index b0b2210b..71d94e01 100644 --- a/cmd/subcmds/synth.go +++ b/cmd/subcmds/synth.go @@ -44,5 +44,5 @@ func synthesis(cmd *cobra.Command, args *inArgs, newSynthesizer func(*ir.Spec, b return err } synthesizer := newSynthesizer(spec, single) - return writeOutput(args, synthesizer.Synth(), utils.MapKeys(spec.Defs.ConfigDefs.VPCs)) + return writeOutput(args, synthesizer.Synth(), utils.SortedMapKeys(spec.Defs.ConfigDefs.VPCs)) } diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index ce685abd..8d8eac44 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -35,7 +35,9 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { if result.SGs[vpcName] == nil { result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) } - result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} + sgName := ir.SGName(*sg.Name) + result.SGs[vpcName][sgName] = &ir.SG{SGName: sgName, VpcName: vpcName, + InboundRules: inbound, OutboundRules: outbound} } } return result, nil diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index 1c0d7cda..9a91f680 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -29,7 +29,7 @@ func (w *Writer) WriteSynthACL(c *ir.ACLCollection, vpc string) error { } func (w *Writer) WriteOptimizeACL(c *ir.ACLCollection) error { - return nil + return fmt.Errorf("OptimizeACL is not supported yet") } func aclProtocol(t netp.Protocol) []tf.Block { diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 981f44cb..8f5a6fd7 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -18,9 +18,17 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// WriteSG prints an entire collection of Security Groups as a sequence of terraform resources. func (w *Writer) WriteSynthSG(c *ir.SGCollection, vpc string) error { - output := sgCollection(c, vpc).Print() + return w.writeSGCollection(c, vpc, true) +} + +func (w *Writer) WriteOptimizeSG(c *ir.SGCollection) error { + return w.writeSGCollection(c, "", false) +} + +// writeSGCollection prints an entire collection of Security Groups as a sequence of terraform resources. +func (w *Writer) writeSGCollection(c *ir.SGCollection, vpc string, writeComments bool) error { + output := sgCollection(c, vpc, writeComments).Print() _, err := w.w.WriteString(output) if err != nil { return err @@ -29,10 +37,6 @@ func (w *Writer) WriteSynthSG(c *ir.SGCollection, vpc string) error { return err } -func (w *Writer) WriteOptimizeSG(c *ir.SGCollection) error { - return nil -} - func value(x interface{}) string { switch v := x.(type) { case *netset.IPBlock: @@ -69,13 +73,17 @@ func sgProtocol(t netp.Protocol, d ir.Direction) []tf.Block { return nil } -func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) tf.Block { +func sgRule(rule *ir.SGRule, sgName ir.SGName, i int, writeComment bool) tf.Block { ruleName := fmt.Sprintf("%v-%v", sgName, i) verifyName(ruleName) + comment := "" + if writeComment { + comment = fmt.Sprintf("# %v", rule.Explanation) + } return tf.Block{ Name: "resource", Labels: []string{quote("ibm_is_security_group_rule"), ir.ChangeScoping(quote(ruleName))}, - Comment: fmt.Sprintf("# %v", rule.Explanation), + Comment: comment, Arguments: []tf.Argument{ {Name: "group", Value: value(sgName)}, {Name: "direction", Value: quote(direction(rule.Direction))}, @@ -85,7 +93,8 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) tf.Block { } } -func sg(sgName, comment string) tf.Block { +func sgBlock(sg *ir.SG, comment string) tf.Block { + sgName := sg.SGName.String() verifyName(sgName) return tf.Block{ Name: "resource", //nolint:revive // obvious false positive @@ -94,22 +103,28 @@ func sg(sgName, comment string) tf.Block { Arguments: []tf.Argument{ {Name: "name", Value: ir.ChangeScoping(quote("sg-" + sgName))}, {Name: "resource_group", Value: "local.sg_synth_resource_group_id"}, - {Name: "vpc", Value: fmt.Sprintf("local.sg_synth_%s_id", ir.VpcFromScopedResource(sgName))}, + {Name: "vpc", Value: fmt.Sprintf("local.sg_synth_%s_id", sg.VpcName)}, }, } } -func sgCollection(t *ir.SGCollection, vpc string) *tf.ConfigFile { - var resources []tf.Block //nolint:prealloc // nontrivial to calculate, and an unlikely performance bottleneck - for _, sgName := range t.SortedSGNames(vpc) { - comment := "" - vpcName := ir.VpcFromScopedResource(string(sgName)) - rules := t.SGs[vpcName][sgName].AllRules() - comment = fmt.Sprintf("\n### SG attached to %v", sgName) - resources = append(resources, sg(sgName.String(), comment)) - for i := range rules { - rule := sgRule(&rules[i], sgName, i) - resources = append(resources, rule) +func sgCollection(t *ir.SGCollection, vpc string, writeComments bool) *tf.ConfigFile { + var resources []tf.Block + for _, vpcName := range t.VpcNames() { + if vpc != vpcName && vpc != "" { + continue + } + for _, sgName := range t.SortedSGNames(vpcName) { + sg := t.SGs[vpcName][sgName] + comment := "\n" + if writeComments { + comment = fmt.Sprintf("\n### SG attached to %v", sgName) + } + resources = append(resources, sgBlock(sg, comment)) + rules := sg.AllRules() + for i := range rules { + resources = append(resources, sgRule(&rules[i], sgName, i, writeComments)) + } } } return &tf.ConfigFile{ diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 094ee726..81c621be 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -29,6 +29,7 @@ type ( ACL struct { Subnet string + VpcName string Internal []ACLRule External []ACLRule } @@ -111,26 +112,25 @@ func NewACLCollection() *ACLCollection { return &ACLCollection{ACLs: map[ID]map[string]*ACL{}} } -func NewACL() *ACL { - return &ACL{Internal: []ACLRule{}, External: []ACLRule{}} +func NewACL(subnet, vpcName string) *ACL { + return &ACL{Subnet: subnet, VpcName: vpcName, Internal: []ACLRule{}, External: []ACLRule{}} } -func (c *ACLCollection) LookupOrCreate(name string) *ACL { - vpcName := VpcFromScopedResource(name) - if acl, ok := c.ACLs[vpcName][name]; ok { +func (c *ACLCollection) LookupOrCreate(subnet string) *ACL { + vpcName := VpcFromScopedResource(subnet) + if acl, ok := c.ACLs[vpcName][subnet]; ok { return acl } - newACL := NewACL() - newACL.Subnet = name + newACL := NewACL(subnet, vpcName) if c.ACLs[vpcName] == nil { c.ACLs[vpcName] = make(map[string]*ACL) } - c.ACLs[vpcName][name] = newACL + c.ACLs[vpcName][subnet] = newACL return newACL } func (c *ACLCollection) VpcNames() []string { - return utils.MapKeys(c.ACLs) + return utils.SortedMapKeys(c.ACLs) } func (c *ACLCollection) WriteSynth(w SynthWriter, vpc string) error { diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index f92d94e8..e1d2f0a3 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -43,6 +43,8 @@ type ( } SG struct { + SGName SGName + VpcName string InboundRules []SGRule OutboundRules []SGRule Attached []ID @@ -82,8 +84,8 @@ func (r *SGRule) mustSupersede(other *SGRule) bool { return res } -func NewSG() *SG { - return &SG{InboundRules: []SGRule{}, OutboundRules: []SGRule{}, Attached: []ID{}} +func NewSG(vpcName string, sgName SGName) *SG { + return &SG{SGName: sgName, VpcName: vpcName, InboundRules: []SGRule{}, OutboundRules: []SGRule{}, Attached: []ID{}} } func NewSGCollection() *SGCollection { @@ -95,7 +97,7 @@ func (c *SGCollection) LookupOrCreate(name SGName) *SG { if sg, ok := c.SGs[vpcName][name]; ok { return sg } - newSG := NewSG() + newSG := NewSG(vpcName, name) if c.SGs[vpcName] == nil { c.SGs[vpcName] = make(map[SGName]*SG) } @@ -117,7 +119,7 @@ func (a *SG) AllRules() []SGRule { } func (c *SGCollection) VpcNames() []string { - return utils.MapKeys(c.SGs) + return utils.SortedMapKeys(c.SGs) } func (c *SGCollection) WriteSynth(w SynthWriter, vpc string) error { From 010ee9da864cbb6abaf4848328d8f7d7fa57b480 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 1 Sep 2024 17:36:07 +0300 Subject: [PATCH 21/79] fixed --- cmd/subcmds/optimize.go | 2 +- cmd/subcmds/outputCommon.go | 2 + cmd/subcmds/synthOutput.go | 1 - pkg/io/confio/parse_sgs.go | 21 +++- pkg/optimize/sg.go | 199 ++++++++++++++++++++++++++++++++++-- 5 files changed, 213 insertions(+), 12 deletions(-) diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index 4b215fe1..fe137a15 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -21,7 +21,7 @@ func NewOptimizeCommand(args *inArgs) *cobra.Command { } // flags - cmd.Flags().StringVarP(&args.firewallName, firewallNameFlag, "s", "", "which vpcFirewall to optimize") + cmd.PersistentFlags().StringVarP(&args.firewallName, firewallNameFlag, "n", "", "which vpcFirewall to optimize") // flags settings _ = cmd.MarkPersistentFlagRequired(firewallNameFlag) // temporary diff --git a/cmd/subcmds/outputCommon.go b/cmd/subcmds/outputCommon.go index 55872136..aa399315 100644 --- a/cmd/subcmds/outputCommon.go +++ b/cmd/subcmds/outputCommon.go @@ -15,6 +15,8 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) +const defaultFilePermission = 0o644 + func checkOutputFlags(args *inArgs) error { if args.outputDir != "" && args.outputFile != "" { return fmt.Errorf("only one of -d and -o can be supplied") diff --git a/cmd/subcmds/synthOutput.go b/cmd/subcmds/synthOutput.go index c1ba8a0d..12e0670b 100644 --- a/cmd/subcmds/synthOutput.go +++ b/cmd/subcmds/synthOutput.go @@ -19,7 +19,6 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -const defaultFilePermission = 0o644 const defaultDirectoryPermission = 0o755 func writeOutput(args *inArgs, collection ir.SynthCollection, vpcNames []ir.ID) error { diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index 8d8eac44..f50f6cc2 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -154,19 +154,34 @@ func translateRemote(remote vpcv1.SecurityGroupRuleRemoteIntf) (ir.RemoteType, e } func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, error) { + var err error + var ipAddrs *netset.IPBlock + if l, ok := local.(*vpcv1.SecurityGroupRuleLocal); ok { if l.CIDRBlock != nil { - return netset.IPBlockFromCidr(*l.CIDRBlock) + ipAddrs, err = netset.IPBlockFromCidr(*l.CIDRBlock) } if l.Address != nil { - return netset.IPBlockFromIPAddress(*l.CIDRBlock) + ipAddrs, err = netset.IPBlockFromIPAddress(*l.CIDRBlock) + } + if err != nil { + return nil, err } + return verifyLocalsValue(ipAddrs) } return nil, fmt.Errorf("error parsing Local field") } +// temporary +func verifyLocalsValue(ipAddrs *netset.IPBlock) (*netset.IPBlock, error) { + if !ipAddrs.Equal(netset.GetCidrAll()) { + return nil, fmt.Errorf("only 0.0.0.0/32 CIDR block is supported for locals values") + } + return ipAddrs, nil +} + func translateProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (netp.Protocol, error) { - isTCP := *rule.Protocol == string(netp.ProtocolStringTCP) + isTCP := *rule.Protocol == "tcp" minDstPort := utils.GetProperty(rule.PortMin, netp.MinPort) maxDstPort := utils.GetProperty(rule.PortMax, netp.MaxPort) return netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(minDstPort), int(maxDstPort)) diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 4c74a514..5b62b170 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -6,20 +6,42 @@ SPDX-License-Identifier: Apache-2.0 package optimize import ( + "log" + "sort" + + "github.com/np-guard/models/pkg/ds" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) -type SGOptimizer struct { - sgCollection *ir.SGCollection - sgName string -} +type ( + SGOptimizer struct { + sgCollection *ir.SGCollection + sgName ir.SGName + } + + sgRuleGroups struct { + tcpToAddrs []ir.SGRule + tcpToSG []ir.SGRule + udpToAddrs []ir.SGRule + udpToSG []ir.SGRule + icmpToAddrs []ir.SGRule + icmpToSG []ir.SGRule + allToAddrs []ir.SGRule + allToSG []ir.SGRule + } +) func NewSGOptimizer(sgName string) Optimizer { - return &SGOptimizer{sgCollection: nil, sgName: sgName} + return &SGOptimizer{sgCollection: nil, sgName: ir.SGName(sgName)} } +// read SGs from config file func (s *SGOptimizer) ParseCollection(filename string) error { c, err := confio.ReadSGs(filename) if err != nil { @@ -29,10 +51,173 @@ func (s *SGOptimizer) ParseCollection(filename string) error { return nil } +// returns a sorted slice of the vpc names +func (s *SGOptimizer) VpcNames() []string { + return utils.SortedMapKeys(s.sgCollection.SGs) +} + +// Optimize attempts to reduce thr number of SG rules +// the algorithm attempts to reduce both inbound and outbound rules separately +// A message is printed to the log at the end of the algorithm func (s *SGOptimizer) Optimize() ir.OptimizeCollection { + for vpcName := range s.sgCollection.SGs { + var sg *ir.SG + var ok bool + if sg, ok = s.sgCollection.SGs[vpcName][s.sgName]; !ok && s.sgName != "" { + continue + } + reducedRules := 0 + newInboundRules := s.reduceSGRules(sg.InboundRules, ir.Inbound) + if len(sg.InboundRules) > len(newInboundRules) { + reducedRules += len(sg.InboundRules) - len(newInboundRules) + s.sgCollection.SGs[vpcName][s.sgName].InboundRules = newInboundRules + } + newOutboundRules := s.reduceSGRules(sg.OutboundRules, ir.Outbound) + if len(sg.OutboundRules) > len(newOutboundRules) { + reducedRules += len(sg.OutboundRules) - len(newOutboundRules) + s.sgCollection.SGs[vpcName][s.sgName].OutboundRules = newOutboundRules + } + + switch { + case reducedRules == 0: + log.Printf("no rules were reduced in sg %s", string(s.sgName)) + case reducedRules == 1: + log.Printf("1 rule was reduced in sg %s", string(s.sgName)) + default: + log.Printf("%d rules were reduced in sg %s", reducedRules, string(s.sgName)) + } + } return s.sgCollection } -func (s *SGOptimizer) VpcNames() []string { - return utils.MapKeys(s.sgCollection.SGs) +// divideSGRules divides the rules into groups based on their protocol and remote +// and attempts to reduce each group separately +func (s *SGOptimizer) reduceSGRules(rules []ir.SGRule, direction ir.Direction) []ir.SGRule { + ruleGroups := divideSGRules(rules) + tcpToAddrs := s.reduceSGRulesTcpudpToAddrs(rulesToIPAddrsToPortsSpan(ruleGroups.tcpToAddrs), direction, true) + tcpToSg := s.reduceSGRulesTcpudpToSG(rulesToSGToPortsSpan(rules), direction, true) + return append(tcpToAddrs, tcpToSg...) +} + +// reduceSGRulesTcpudpToAddrs attempts to reduce the number of rules of tcp/udp rules with ipAddrs as remote +func (s *SGOptimizer) reduceSGRulesTcpudpToAddrs(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], + direction ir.Direction, isTCP bool) []ir.SGRule { + result := make([]ir.SGRule, len(span)) + for i := range span { + for _, dstPorts := range span[i].Right.Intervals() { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) + rule := ir.SGRule{ + Direction: direction, + Remote: span[i].Left, + Protocol: p, + Local: netset.GetCidrAll(), + } + result[i] = rule + } + } + return result +} + +// reduceSGRulesTcpudpToAddrs attempts to reduce the number of rules of tcp/udp rules with a sg as remote +func (s *SGOptimizer) reduceSGRulesTcpudpToSG(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []ir.SGRule { + result := make([]ir.SGRule, 0) + for sgName, intervals := range span { + for _, dstPorts := range intervals.Intervals() { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) + rule := ir.SGRule{ + Direction: direction, + Remote: sgName, + Protocol: p, + Local: netset.GetCidrAll(), + } + result = append(result, rule) + } + } + return result +} + +// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span of (IPBlock X ports) +func rulesToIPAddrsToPortsSpan(rules []ir.SGRule) (p []ds.Pair[*netset.IPBlock, *interval.CanonicalSet]) { + span := ds.NewProductLeft[*netset.IPBlock, *interval.CanonicalSet]() + for i := range rules { + p := rules[i].Protocol.(netp.TCPUDP) // already checked + r := ds.CartesianPairLeft(rules[i].Remote.(*netset.IPBlock), p.DstPorts().ToSet()) + span = span.Union(r).(*ds.ProductLeft[*netset.IPBlock, *interval.CanonicalSet]) + } + return sortPartitionsByIPAddrs(span.Partitions()) +} + +// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span intervals for each remote +func rulesToSGToPortsSpan(rules []ir.SGRule) map[ir.SGName]*interval.CanonicalSet { + result := make(map[ir.SGName]*interval.CanonicalSet) + for i := range rules { + p := rules[i].Protocol.(netp.TCPUDP) // already checked + remote := rules[i].Remote.(ir.SGName) // already checked + if result[remote] == nil { + result[remote] = interval.NewCanonicalSet() + } + result[remote].AddInterval(p.DstPorts()) + } + return result +} + +// each IPBlock is a single CIDR/IP address. The IPBlocks are disjoint. +func sortPartitionsByIPAddrs(p []ds.Pair[*netset.IPBlock, *interval.CanonicalSet]) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { + cmp := func(i, j int) bool { return p[i].Left.FirstIPAddress() < p[j].Left.FirstIPAddress() } + sort.Slice(p, cmp) + return p +} + +// divide SGCollection to TCP/UDP/ICMP/ProtocolALL X SGRemote/IPAddrs rules +func divideSGRules(rules []ir.SGRule) *sgRuleGroups { + tcpAddrs := make([]ir.SGRule, 0) + tcpSG := make([]ir.SGRule, 0) + udpAddrs := make([]ir.SGRule, 0) + udpSG := make([]ir.SGRule, 0) + icmpAddrs := make([]ir.SGRule, 0) + icmpSG := make([]ir.SGRule, 0) + allAddrs := make([]ir.SGRule, 0) + allSG := make([]ir.SGRule, 0) + + for _, rule := range rules { + // TCP rule + if p, ok := rule.Protocol.(netp.TCPUDP); ok && p.ProtocolString() == "TCP" { + if _, ok := rule.Remote.(*netset.IPBlock); ok { + tcpAddrs = append(tcpAddrs, rule) + } else { + tcpSG = append(tcpSG, rule) + } + } + + // UDP rule + if p, ok := rule.Protocol.(netp.TCPUDP); ok && p.ProtocolString() == "UDP" { + if _, ok := rule.Remote.(*netset.IPBlock); ok { + udpAddrs = append(udpAddrs, rule) + } else { + udpSG = append(udpSG, rule) + } + } + + // ICMP rule + if _, ok := rule.Protocol.(netp.ICMP); ok { + if _, ok := rule.Remote.(*netset.IPBlock); ok { + icmpAddrs = append(icmpAddrs, rule) + } else { + icmpSG = append(icmpSG, rule) + } + } + + // all protocol rules + if _, ok := rule.Protocol.(netp.AnyProtocol); ok { + if _, ok := rule.Remote.(*netset.IPBlock); ok { + allAddrs = append(allAddrs, rule) + } else { + allSG = append(allSG, rule) + } + } + } + return utils.Ptr(sgRuleGroups{tcpToAddrs: tcpAddrs, tcpToSG: tcpSG, + udpToAddrs: udpAddrs, udpToSG: udpSG, + icmpToAddrs: icmpAddrs, icmpToSG: icmpSG, + allToAddrs: allAddrs, allToSG: allSG}) } From 524956c866f88fd9dd35c2d9f8aada6b328f3879 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 2 Sep 2024 11:18:01 +0300 Subject: [PATCH 22/79] fixed --- pkg/optimize/sg.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 5b62b170..b4ecabee 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -63,7 +63,7 @@ func (s *SGOptimizer) Optimize() ir.OptimizeCollection { for vpcName := range s.sgCollection.SGs { var sg *ir.SG var ok bool - if sg, ok = s.sgCollection.SGs[vpcName][s.sgName]; !ok && s.sgName != "" { + if sg, ok = s.sgCollection.SGs[vpcName][s.sgName]; !ok { continue } reducedRules := 0 @@ -78,6 +78,7 @@ func (s *SGOptimizer) Optimize() ir.OptimizeCollection { s.sgCollection.SGs[vpcName][s.sgName].OutboundRules = newOutboundRules } + // print a message to the log switch { case reducedRules == 0: log.Printf("no rules were reduced in sg %s", string(s.sgName)) From 02231d33a43ba5d13b495bf17c41d54a94f13ab1 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 2 Sep 2024 11:23:31 +0300 Subject: [PATCH 23/79] use ToIPAddressString --- pkg/io/confio/sg.go | 2 +- pkg/io/csvio/sg.go | 2 +- pkg/io/mdio/sg.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/io/confio/sg.go b/pkg/io/confio/sg.go index ee551214..656ec479 100644 --- a/pkg/io/confio/sg.go +++ b/pkg/io/confio/sg.go @@ -53,7 +53,7 @@ func sgRemote(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteSecurit st := rule.Remote.String() switch t := rule.Remote.(type) { case *netset.IPBlock: - if t.Size() == 1 { // single IP address + if ipString := t.ToIPAddressString(); ipString != "" { // single IP address return &vpcv1.SecurityGroupRuleRemoteIP{ Address: &st, } diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index a10dc8db..3a958754 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -74,7 +74,7 @@ func sGPort(p interval.Interval) string { func sGRemoteType(t ir.RemoteType) string { switch t := t.(type) { case *netset.IPBlock: - if t.Size() == 1 { + if ipString := t.ToIPAddressString(); ipString != "" { return "IP address" } return "CIDR block" diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index 044ddbca..8750af42 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -88,7 +88,7 @@ func sGPort(p interval.Interval) string { func sGRemoteType(t ir.RemoteType) string { switch t := t.(type) { case *netset.IPBlock: - if t.Size() == 1 { + if ipString := t.ToIPAddressString(); ipString != "" { return "IP address" } return "CIDR block" From aabe195c7783b8cbf5c4fd88c4215af447c1ee62 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 2 Sep 2024 18:32:34 +0300 Subject: [PATCH 24/79] wip --- pkg/optimize/common.go | 22 ++++++- pkg/optimize/icmp.go | 45 +++++++++++++ pkg/optimize/sg.go | 115 +++++++++++++++------------------- pkg/optimize/sgRulesToSpan.go | 76 ++++++++++++++++++++++ pkg/optimize/spanToSGRules.go | 73 +++++++++++++++++++++ 5 files changed, 267 insertions(+), 64 deletions(-) create mode 100644 pkg/optimize/icmp.go create mode 100644 pkg/optimize/sgRulesToSpan.go create mode 100644 pkg/optimize/spanToSGRules.go diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index d0aa9e52..5d1beb8c 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -5,7 +5,16 @@ SPDX-License-Identifier: Apache-2.0 package optimize -import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +import ( + "sort" + + "github.com/np-guard/models/pkg/ds" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) type Optimizer interface { // read the collection from the config object file @@ -17,3 +26,14 @@ type Optimizer interface { // returns a slice of all vpc names. used to generate locals file VpcNames() []string } + +// each IPBlock is a single CIDR/IP address. The IPBlocks are disjoint. +func sortPartitionsByIPAddrs(p []ds.Pair[*netset.IPBlock, *interval.CanonicalSet]) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { + cmp := func(i, j int) bool { return p[i].Left.FirstIPAddress() < p[j].Left.FirstIPAddress() } + sort.Slice(p, cmp) + return p +} + +func allPorts(ports *interval.CanonicalSet) bool { + return ports.Equal(netp.AllPorts().ToSet()) +} diff --git a/pkg/optimize/icmp.go b/pkg/optimize/icmp.go new file mode 100644 index 00000000..f4fb3a68 --- /dev/null +++ b/pkg/optimize/icmp.go @@ -0,0 +1,45 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import ( + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +type icmp struct { + allowed map[int]bool // type X code X allow/deny +} + +func newIcmp() *icmp { + return &icmp{} +} + +func (i *icmp) add(*netp.ICMPTypeCode) { + +} + +func (i *icmp) allCodes(t int) bool { + return true +} + +func (i *icmp) allTypesAndCodes() bool { + return true +} + +func (i *icmp) toSGRulestoSG(sgName *ir.SGName) []ir.SGRule { + return []ir.SGRule{} +} + +func (i *icmp) toSGRulestoIPAddrs(ipAddrs *netset.IPBlock) []ir.SGRule { + return []ir.SGRule{} +} + +func (i *icmp) all() bool { + return false +} diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index b4ecabee..6d824d8a 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -7,9 +7,7 @@ package optimize import ( "log" - "sort" - "github.com/np-guard/models/pkg/ds" "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" @@ -35,6 +33,10 @@ type ( allToAddrs []ir.SGRule allToSG []ir.SGRule } + + sgRemotePortsSpan map[*ir.SGName]*interval.CanonicalSet + sgRemoteIcmpSpan map[*ir.SGName]*icmp + sgRemoteAllSpan []*ir.SGName ) func NewSGOptimizer(sgName string) Optimizer { @@ -67,11 +69,15 @@ func (s *SGOptimizer) Optimize() ir.OptimizeCollection { continue } reducedRules := 0 + + // reduce inbound rules first newInboundRules := s.reduceSGRules(sg.InboundRules, ir.Inbound) if len(sg.InboundRules) > len(newInboundRules) { reducedRules += len(sg.InboundRules) - len(newInboundRules) s.sgCollection.SGs[vpcName][s.sgName].InboundRules = newInboundRules } + + // reduce outbound rules second newOutboundRules := s.reduceSGRules(sg.OutboundRules, ir.Outbound) if len(sg.OutboundRules) > len(newOutboundRules) { reducedRules += len(sg.OutboundRules) - len(newOutboundRules) @@ -95,78 +101,61 @@ func (s *SGOptimizer) Optimize() ir.OptimizeCollection { // and attempts to reduce each group separately func (s *SGOptimizer) reduceSGRules(rules []ir.SGRule, direction ir.Direction) []ir.SGRule { ruleGroups := divideSGRules(rules) - tcpToAddrs := s.reduceSGRulesTcpudpToAddrs(rulesToIPAddrsToPortsSpan(ruleGroups.tcpToAddrs), direction, true) - tcpToSg := s.reduceSGRulesTcpudpToSG(rulesToSGToPortsSpan(rules), direction, true) - return append(tcpToAddrs, tcpToSg...) + + // rules with SG as a remote + tcpToSGSpan := tcpudpRulesToSGToPortsSpan(ruleGroups.tcpToSG) + udpToSGSpan := tcpudpRulesToSGToPortsSpan(ruleGroups.udpToSG) + icmpToSGSpan := icmpRulesToSGToIcmpSpan(ruleGroups.icmpToSG) + protocolAllToSGSpan := allProtocolRulesToSGToSpan(ruleGroups.allToSG) + rulesToSG := reduceSGRulesToSG(tcpToSGSpan, udpToSGSpan, icmpToSGSpan, protocolAllToSGSpan, direction) + + // rules with IPBlock as a remote + tcpToIPAddrsSpan := tcpudpRulesToIPAddrsToPortsSpan(ruleGroups.tcpToAddrs) + udpToIPAddrsSpan := tcpudpRulesToIPAddrsToPortsSpan(ruleGroups.udpToAddrs) + icmpToAddrsSpan := icmpRulesToIPAddrsToIcmpSpan(ruleGroups.icmpToSG) + protocolAllToIPAddrsSpan := allProtocolRulesToIPAddrsToSpan(ruleGroups.allToAddrs) + rulesToIPAddrs := reduceSGRulesToIPAddrs(tcpToIPAddrsSpan, udpToIPAddrsSpan, icmpToAddrsSpan, protocolAllToIPAddrsSpan, direction) + + // append both slices together + return append(rulesToSG, rulesToIPAddrs...) } -// reduceSGRulesTcpudpToAddrs attempts to reduce the number of rules of tcp/udp rules with ipAddrs as remote -func (s *SGOptimizer) reduceSGRulesTcpudpToAddrs(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], - direction ir.Direction, isTCP bool) []ir.SGRule { - result := make([]ir.SGRule, len(span)) - for i := range span { - for _, dstPorts := range span[i].Right.Intervals() { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) - rule := ir.SGRule{ - Direction: direction, - Remote: span[i].Left, - Protocol: p, - Local: netset.GetCidrAll(), - } - result[i] = rule - } +func reduceSGRulesToSG(tcp, udp sgRemotePortsSpan, icmp sgRemoteIcmpSpan, all sgRemoteAllSpan, direction ir.Direction) []ir.SGRule { + // delete other protocols if all protocol rule exists + for _, sgName := range all { + delete(tcp, sgName) + delete(udp, sgName) + delete(icmp, sgName) } - return result -} -// reduceSGRulesTcpudpToAddrs attempts to reduce the number of rules of tcp/udp rules with a sg as remote -func (s *SGOptimizer) reduceSGRulesTcpudpToSG(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []ir.SGRule { - result := make([]ir.SGRule, 0) - for sgName, intervals := range span { - for _, dstPorts := range intervals.Intervals() { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) - rule := ir.SGRule{ - Direction: direction, - Remote: sgName, - Protocol: p, - Local: netset.GetCidrAll(), + // merge tcp, udp and icmp rules into all protocol rule + for sgName, tcpPorts := range tcp { + if udpPorts, ok := udp[sgName]; ok { + if i, ok := icmp[sgName]; ok { + if i.all() && allPorts(tcpPorts) && allPorts(udpPorts) { // all tcp&udp ports and all icmp types&codes + delete(tcp, sgName) + delete(udp, sgName) + delete(icmp, sgName) + all = append(all, sgName) + } } - result = append(result, rule) } } - return result -} -// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span of (IPBlock X ports) -func rulesToIPAddrsToPortsSpan(rules []ir.SGRule) (p []ds.Pair[*netset.IPBlock, *interval.CanonicalSet]) { - span := ds.NewProductLeft[*netset.IPBlock, *interval.CanonicalSet]() - for i := range rules { - p := rules[i].Protocol.(netp.TCPUDP) // already checked - r := ds.CartesianPairLeft(rules[i].Remote.(*netset.IPBlock), p.DstPorts().ToSet()) - span = span.Union(r).(*ds.ProductLeft[*netset.IPBlock, *interval.CanonicalSet]) - } - return sortPartitionsByIPAddrs(span.Partitions()) -} + // convert to spans to SG rules + tcpRules := tcpudpToSGSpanToSGRules(tcp, direction, true) + udpRules := tcpudpToSGSpanToSGRules(tcp, direction, false) + icmpRules := icmpToSGSpanToSGRules(icmp, direction) + protocolAll := protocolAllToSGSpanToSGRules(all, direction) -// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span intervals for each remote -func rulesToSGToPortsSpan(rules []ir.SGRule) map[ir.SGName]*interval.CanonicalSet { - result := make(map[ir.SGName]*interval.CanonicalSet) - for i := range rules { - p := rules[i].Protocol.(netp.TCPUDP) // already checked - remote := rules[i].Remote.(ir.SGName) // already checked - if result[remote] == nil { - result[remote] = interval.NewCanonicalSet() - } - result[remote].AddInterval(p.DstPorts()) - } - return result + // merge all rules together + tcpudp := append(tcpRules, udpRules...) + icmpAll := append(icmpRules, protocolAll...) + return append(tcpudp, icmpAll...) } -// each IPBlock is a single CIDR/IP address. The IPBlocks are disjoint. -func sortPartitionsByIPAddrs(p []ds.Pair[*netset.IPBlock, *interval.CanonicalSet]) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { - cmp := func(i, j int) bool { return p[i].Left.FirstIPAddress() < p[j].Left.FirstIPAddress() } - sort.Slice(p, cmp) - return p +func reduceSGRulesToIPAddrs() []ir.SGRule { + return []ir.SGRule{} } // divide SGCollection to TCP/UDP/ICMP/ProtocolALL X SGRemote/IPAddrs rules diff --git a/pkg/optimize/sgRulesToSpan.go b/pkg/optimize/sgRulesToSpan.go new file mode 100644 index 00000000..61066a36 --- /dev/null +++ b/pkg/optimize/sgRulesToSpan.go @@ -0,0 +1,76 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import ( + "github.com/np-guard/models/pkg/ds" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" +) + +// Rules with SG remote +func tcpudpRulesToSGToPortsSpan(rules []ir.SGRule) map[*ir.SGName]*interval.CanonicalSet { + result := make(map[*ir.SGName]*interval.CanonicalSet) + for i := range rules { + p := rules[i].Protocol.(netp.TCPUDP) // already checked + remote := utils.Ptr(rules[i].Remote.(ir.SGName)) // already checked + if result[remote] == nil { + result[remote] = interval.NewCanonicalSet() + } + result[remote].AddInterval(p.DstPorts()) + } + return result +} + +func icmpRulesToSGToIcmpSpan(rules []ir.SGRule) map[*ir.SGName]*icmp { + result := make(map[*ir.SGName]*icmp) + for i := range rules { + p := rules[i].Protocol.(netp.ICMP) // already checked + remote := utils.Ptr(rules[i].Remote.(ir.SGName)) // already checked + if result[remote] == nil { + result[remote] = newIcmp() + } + result[remote].add(p.TypeCode) + } + return result +} + +func allProtocolRulesToSGToSpan(rules []ir.SGRule) []*ir.SGName { + result := make([]*ir.SGName, len(rules)) + for i := range rules { + result[i] = rules[i].Remote.(*ir.SGName) + } + return result +} + +// Rules with IPAddrs remote + +// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span of (IPBlock X ports) +func tcpudpRulesToIPAddrsToPortsSpan(rules []ir.SGRule) (p []ds.Pair[*netset.IPBlock, *interval.CanonicalSet]) { + span := ds.NewProductLeft[*netset.IPBlock, *interval.CanonicalSet]() + for i := range rules { + p := rules[i].Protocol.(netp.TCPUDP) // already checked + r := ds.CartesianPairLeft(rules[i].Remote.(*netset.IPBlock), p.DstPorts().ToSet()) + span = span.Union(r).(*ds.ProductLeft[*netset.IPBlock, *interval.CanonicalSet]) + } + return sortPartitionsByIPAddrs(span.Partitions()) +} + +func icmpRulesToIPAddrsToIcmpSpan(rules []ir.SGRule) bool { + return true +} + +func allProtocolRulesToIPAddrsToSpan(rules []ir.SGRule) []*netset.IPBlock { + result := make([]*netset.IPBlock, len(rules)) + for i := range rules { + result[i] = rules[i].Remote.(*netset.IPBlock) + } + return result // should sort !! +} diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go new file mode 100644 index 00000000..0c37bbb4 --- /dev/null +++ b/pkg/optimize/spanToSGRules.go @@ -0,0 +1,73 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import ( + "github.com/np-guard/models/pkg/ds" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +// SG remote +func tcpudpToSGSpanToSGRules(span map[*ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []ir.SGRule { + result := make([]ir.SGRule, 0) + for sgName, intervals := range span { + for _, dstPorts := range intervals.Intervals() { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) + rule := ir.SGRule{ + Direction: direction, + Remote: sgName, + Protocol: p, + Local: netset.GetCidrAll(), + } + result = append(result, rule) + } + } + return result +} + +func icmpToSGSpanToSGRules(span map[*ir.SGName]*icmp, direction ir.Direction) []ir.SGRule { + result := make([]ir.SGRule, 0) + for sgName, icmp := range span { + result = append(result, icmp.toSGRulestoSG(sgName)...) + } + return result +} + +func protocolAllToSGSpanToSGRules(span []*ir.SGName, direction ir.Direction) []ir.SGRule { + result := make([]ir.SGRule, len(span)) + for i, sgName := range span { + result[i] = ir.SGRule{ + Direction: direction, + Remote: sgName, + Protocol: netp.AnyProtocol{}, + Local: netset.GetCidrAll(), + } + } + return result +} + +// IPAddrs remote +func tcpudpToIPAddrsSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], + direction ir.Direction, isTCP bool) []ir.SGRule { + result := make([]ir.SGRule, len(span)) + for i := range span { + for _, dstPorts := range span[i].Right.Intervals() { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) + rule := ir.SGRule{ + Direction: direction, + Remote: span[i].Left, + Protocol: p, + Local: netset.GetCidrAll(), + } + result[i] = rule + } + } + return result +} From b16364501f027b7d5acde2f39a4f15de02355994 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 3 Sep 2024 17:31:03 +0300 Subject: [PATCH 25/79] wip --- pkg/optimize/common.go | 10 ++- pkg/optimize/icmp.go | 19 ++--- pkg/optimize/ip.go | 15 ++++ pkg/optimize/sg.go | 152 ++++++++++++++++++++-------------- pkg/optimize/sgRulesToSpan.go | 27 ++++-- pkg/optimize/spanToSGRules.go | 12 ++- 6 files changed, 152 insertions(+), 83 deletions(-) create mode 100644 pkg/optimize/ip.go diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index 5d1beb8c..46c0070a 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -27,13 +27,19 @@ type Optimizer interface { VpcNames() []string } -// each IPBlock is a single CIDR/IP address. The IPBlocks are disjoint. -func sortPartitionsByIPAddrs(p []ds.Pair[*netset.IPBlock, *interval.CanonicalSet]) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { +// each IPBlock is a single CIDR. The CIDRs are disjoint. +func sortPartitionsByIPAddrs[T any](p []ds.Pair[*netset.IPBlock, T]) []ds.Pair[*netset.IPBlock, T] { cmp := func(i, j int) bool { return p[i].Left.FirstIPAddress() < p[j].Left.FirstIPAddress() } sort.Slice(p, cmp) return p } +func sortIPBlockSlice(s []*netset.IPBlock) []*netset.IPBlock { + cmp := func(i, j int) bool { return s[i].FirstIPAddress() < s[j].FirstIPAddress() } + sort.Slice(s, cmp) + return s +} + func allPorts(ports *interval.CanonicalSet) bool { return ports.Equal(netp.AllPorts().ToSet()) } diff --git a/pkg/optimize/icmp.go b/pkg/optimize/icmp.go index f4fb3a68..3633a5a1 100644 --- a/pkg/optimize/icmp.go +++ b/pkg/optimize/icmp.go @@ -13,7 +13,7 @@ import ( ) type icmp struct { - allowed map[int]bool // type X code X allow/deny + allowed map[int]bool // type x code X allow/deny } func newIcmp() *icmp { @@ -24,22 +24,19 @@ func (i *icmp) add(*netp.ICMPTypeCode) { } -func (i *icmp) allCodes(t int) bool { - return true -} - -func (i *icmp) allTypesAndCodes() bool { - return true +func (i *icmp) all() bool { + return false } -func (i *icmp) toSGRulestoSG(sgName *ir.SGName) []ir.SGRule { +func (i *icmp) toSGRulestoSG(sgName *ir.SGName, direction ir.Direction) []ir.SGRule { return []ir.SGRule{} } -func (i *icmp) toSGRulestoIPAddrs(ipAddrs *netset.IPBlock) []ir.SGRule { +func (i *icmp) toSGRulestoIPAddrs(ipAddrs *netset.IPBlock, direction ir.Direction) []ir.SGRule { return []ir.SGRule{} } -func (i *icmp) all() bool { - return false +// returns true if i is a subset of other +func (i *icmp) subset(other *icmp) bool { + return true } diff --git a/pkg/optimize/ip.go b/pkg/optimize/ip.go new file mode 100644 index 00000000..87c32c45 --- /dev/null +++ b/pkg/optimize/ip.go @@ -0,0 +1,15 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import "github.com/np-guard/models/pkg/netset" + +// temporary file, should be implement in models repo + +// given a Date: Sun, 8 Sep 2024 14:13:22 +0300 Subject: [PATCH 26/79] wip --- pkg/ir/sg.go | 5 ++ pkg/optimize/icmp.go | 42 ----------- pkg/optimize/ip.go | 63 ++++++++++++++-- pkg/optimize/sg.go | 42 +++++------ pkg/optimize/sgRulesToSpan.go | 35 +++++---- pkg/optimize/spanToSGRules.go | 134 ++++++++++++++++++++++++++-------- pkg/utils/utils.go | 8 ++ 7 files changed, 213 insertions(+), 116 deletions(-) delete mode 100644 pkg/optimize/icmp.go diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index e1d2f0a3..83bb7413 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -84,6 +84,11 @@ func (r *SGRule) mustSupersede(other *SGRule) bool { return res } +func NewSGRule(direction Direction, remote RemoteType, p netp.Protocol, local *netset.IPBlock, e string) SGRule { + return SGRule{Direction: direction, Remote: remote, Protocol: p, + Local: local, Explanation: e} +} + func NewSG(vpcName string, sgName SGName) *SG { return &SG{SGName: sgName, VpcName: vpcName, InboundRules: []SGRule{}, OutboundRules: []SGRule{}, Attached: []ID{}} } diff --git a/pkg/optimize/icmp.go b/pkg/optimize/icmp.go deleted file mode 100644 index 3633a5a1..00000000 --- a/pkg/optimize/icmp.go +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package optimize - -import ( - "github.com/np-guard/models/pkg/netp" - "github.com/np-guard/models/pkg/netset" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -) - -type icmp struct { - allowed map[int]bool // type x code X allow/deny -} - -func newIcmp() *icmp { - return &icmp{} -} - -func (i *icmp) add(*netp.ICMPTypeCode) { - -} - -func (i *icmp) all() bool { - return false -} - -func (i *icmp) toSGRulestoSG(sgName *ir.SGName, direction ir.Direction) []ir.SGRule { - return []ir.SGRule{} -} - -func (i *icmp) toSGRulestoIPAddrs(ipAddrs *netset.IPBlock, direction ir.Direction) []ir.SGRule { - return []ir.SGRule{} -} - -// returns true if i is a subset of other -func (i *icmp) subset(other *icmp) bool { - return true -} diff --git a/pkg/optimize/ip.go b/pkg/optimize/ip.go index 87c32c45..348b8aa8 100644 --- a/pkg/optimize/ip.go +++ b/pkg/optimize/ip.go @@ -5,11 +5,64 @@ SPDX-License-Identifier: Apache-2.0 package optimize -import "github.com/np-guard/models/pkg/netset" +import ( + "log" + "strings" -// temporary file, should be implement in models repo + "github.com/np-guard/models/pkg/netset" +) -// given a 0 && !touching(span[i-1].Left, span[i].Left) { // if the CIDRS are not touching + for _, r := range rules { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + + rules = []ds.Pair[*netset.IPBlock, *interval.Interval]{} + continue + } + + activePorts := interval.NewCanonicalSet() + for _, r := range rules { + if !r.Right.ToSet().IsSubset(span[i].Right) { // close old rules + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } else { + activePorts.AddInterval(*r.Right) + } + } + + // open new rules + for _, ports := range span[i].Right.Intervals() { + if !ports.ToSet().IsSubset(activePorts) { // it does not contained in other rules + r := ds.Pair[*netset.IPBlock, *interval.Interval]{Left: FirstIPAddress(span[i].Left), Right: &ports} + rules = append(rules, r) } - result[i] = rule } } + + // close all old rules + for _, r := range rules { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.Start())) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + return result } -func icmpToIPAddrsSpanToSGRules(span []ds.Pair[*netset.IPBlock, *icmp], direction ir.Direction) []ir.SGRule { +func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ []*netset.IPBlock, direction ir.Direction) []ir.SGRule { + rules := []ds.Pair[*netset.IPBlock, *netp.ICMP]{} result := make([]ir.SGRule, 0) + + for i := range span { + if i > 0 && !touching(span[i-1].Left, span[i].Left) { // if the CIDRS are not touching + for _, r := range rules { + p, _ := netp.NewICMP(r.Right.TypeCode) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + + rules = []ds.Pair[*netset.IPBlock, *netp.ICMP]{} + continue + } + + activeICMP := netset.EmptyICMPSet() + for _, r := range rules { + ruleIcmpSet := netset.NewICMPSet(*r.Right) + if !ruleIcmpSet.IsSubset(span[i].Right) { // close old rules + p, _ := netp.NewICMP(r.Right.TypeCode) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } else { + activeICMP.Union(ruleIcmpSet) + } + } + + // new rules + for _, p := range span[i].Right.Partitions() { + if !netset.NewICMPSet(p).IsSubset(activeICMP) { // it does not contained in other rules + r := ds.Pair[*netset.IPBlock, *netp.ICMP]{Left: FirstIPAddress(span[i].Left), Right: &p} + rules = append(rules, r) + } + } + } + + // close all rules + for _, r := range rules { + p, _ := netp.NewICMP(r.Right.TypeCode) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + return result } -func allToIPAddrsSpanToSGRules(span []*netset.IPBlock, direction ir.Direction) []ir.SGRule { +func allSpanToSGRules(span []*netset.IPBlock, direction ir.Direction) []ir.SGRule { result := make([]ir.SGRule, 0) + for _, ipAddrs := range span { + for _, cidr := range ToCidrs(ipAddrs) { + result = append(result, ir.NewSGRule(direction, cidr, netp.AnyProtocol{}, netset.GetCidrAll(), "")) + } + } return result } diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index ede1bb67..ab4783d5 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -47,3 +47,11 @@ func Int64PointerToIntPointer(v *int64) *int { } return Ptr(int(*v)) } + +func ToPtrSlice[T any](s []T) []*T { + res := make([]*T, len(s)) + for i := range s { + res[i] = Ptr(s[i]) + } + return res +} From c4f9ed43ad57e36d41c99a205fb3de0d1aa46029 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 8 Sep 2024 14:20:38 +0300 Subject: [PATCH 27/79] wip --- pkg/optimize/sg.go | 5 +++-- pkg/optimize/spanToSGRules.go | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 35f8a570..11ad8e42 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -130,7 +130,7 @@ func (s *SGOptimizer) reduceSGRules(rules []ir.SGRule, direction ir.Direction) [ } func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGRule { - // delete other protocols if all protocol rule exists + // delete other protocols rules if all protocol rule exists for _, sgName := range spans.all { delete(spans.tcp, sgName) delete(spans.udp, sgName) @@ -151,7 +151,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR } } - // convert to spans to SG rules + // convert spans to SG rules tcpRules := tcpudpSGSpanToSGRules(spans.tcp, direction, true) udpRules := tcpudpSGSpanToSGRules(spans.tcp, direction, false) icmpRules := icmpSGSpanToSGRules(spans.icmp, direction) @@ -166,6 +166,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction) []ir.SGRule { // Todo: check if we can replace tcp, udp, icmp with protocol all + // spans to SG rules tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) udpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, false) icmpRules := icmpSpanToSGRules(spans.icmp, spans.all, direction) diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go index 021e5760..ab12f467 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/spanToSGRules.go @@ -76,9 +76,9 @@ func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSe } } - // open new rules + // new rules for _, ports := range span[i].Right.Intervals() { - if !ports.ToSet().IsSubset(activePorts) { // it does not contained in other rules + if !ports.ToSet().IsSubset(activePorts) { // it is not contained in other rules r := ds.Pair[*netset.IPBlock, *interval.Interval]{Left: FirstIPAddress(span[i].Left), Right: &ports} rules = append(rules, r) } @@ -128,7 +128,7 @@ func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ []*ne // new rules for _, p := range span[i].Right.Partitions() { - if !netset.NewICMPSet(p).IsSubset(activeICMP) { // it does not contained in other rules + if !netset.NewICMPSet(p).IsSubset(activeICMP) { r := ds.Pair[*netset.IPBlock, *netp.ICMP]{Left: FirstIPAddress(span[i].Left), Right: &p} rules = append(rules, r) } From 820a023d8ffbed35e09484ef1235c3c8c4356b1d Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 8 Sep 2024 16:03:45 +0300 Subject: [PATCH 28/79] check protocol is not nil --- pkg/synth/sg.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index d829d68d..7da07bd4 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -105,13 +105,16 @@ func (s *SGSynthesizer) allowConnectionToDst(conn *ir.Connection, trackedProtoco sgDstName := ir.SGName(dstEndpoint.Name) sgDst := s.result.LookupOrCreate(sgDstName) sgDst.Attached = []ir.ID{ir.ID(sgDstName)} - rule := &ir.SGRule{ - Remote: sgRemote(&s.spec.Defs, srcEndpoint), - Direction: ir.Inbound, - Protocol: trackedProtocol.Protocol.InverseDirection(), - Explanation: reason, + if p := trackedProtocol.Protocol.InverseDirection(); p != nil { + rule := &ir.SGRule{ + Remote: sgRemote(&s.spec.Defs, srcEndpoint), + Direction: ir.Inbound, + Protocol: trackedProtocol.Protocol.InverseDirection(), + Explanation: reason, + } + sgDst.Add(rule) } - sgDst.Add(rule) + } // generate SGs for blocked endpoints (endpoints that do not appear in Spec) From 92866896736e85314974cb80f0f4d1f77a065f86 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 9 Sep 2024 11:27:29 +0300 Subject: [PATCH 29/79] inbound udp --- pkg/synth/sg.go | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index 7da07bd4..0dc2f560 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -8,6 +8,7 @@ package synth import ( "log" + "github.com/np-guard/models/pkg/netp" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -105,16 +106,20 @@ func (s *SGSynthesizer) allowConnectionToDst(conn *ir.Connection, trackedProtoco sgDstName := ir.SGName(dstEndpoint.Name) sgDst := s.result.LookupOrCreate(sgDstName) sgDst.Attached = []ir.ID{ir.ID(sgDstName)} - if p := trackedProtocol.Protocol.InverseDirection(); p != nil { - rule := &ir.SGRule{ - Remote: sgRemote(&s.spec.Defs, srcEndpoint), - Direction: ir.Inbound, - Protocol: trackedProtocol.Protocol.InverseDirection(), - Explanation: reason, - } - sgDst.Add(rule) + + // udp protocol does not have inverse direction + inverseP := trackedProtocol.Protocol.InverseDirection() + if p, ok := trackedProtocol.Protocol.(netp.TCPUDP); ok && p.ProtocolString() == netp.ProtocolStringUDP { + inverseP, _ = netp.NewTCPUDP(false, netp.MinPort, netp.MaxPort, netp.MinPort, netp.MaxPort) } + rule := &ir.SGRule{ + Remote: sgRemote(&s.spec.Defs, srcEndpoint), + Direction: ir.Inbound, + Protocol: inverseP, + Explanation: reason, + } + sgDst.Add(rule) } // generate SGs for blocked endpoints (endpoints that do not appear in Spec) From a7f68f57921dc5d6e4d1f3de8917a6776afc832f Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 11 Sep 2024 11:51:36 +0300 Subject: [PATCH 30/79] lint --- pkg/synth/sg.go | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index 9e4d65c4..285b0185 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -114,7 +114,6 @@ func (s *SGSynthesizer) allowConnectionToDst(conn *ir.Connection, trackedProtoco } sgDst.Add(rule) } - } // generate SGs for blocked endpoints (endpoints that do not appear in Spec) From d25bf9c9854626d47a69e37e4c235473134df588 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 11 Sep 2024 12:03:18 +0300 Subject: [PATCH 31/79] make mod --- go.mod | 10 +--------- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/go.mod b/go.mod index 86b90cca..9d963915 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/IBM/vpc-go-sdk v0.56.0 github.com/np-guard/cloud-resource-collector v0.14.0 - github.com/np-guard/models v0.3.4 + github.com/np-guard/models v0.4.1-0.20240911081500-0a30b7aefb6f github.com/spf13/cobra v1.8.1 ) @@ -35,11 +35,3 @@ require ( golang.org/x/text v0.16.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) - -// Todo: -// (1) delete the following line when np-guard/models#33 is merged. -// (2) replace lines 137 and 138 in go.sum with -// github.com/np-guard/models v0.3.4 h1:HOhVi6wyGvo+KmYBnQ5Km5HYCF+/PQlDs1v7mL1v05g= -// github.com/np-guard/models v0.3.4/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= -//nolint:gomoddirectives // this line is temporary -replace github.com/np-guard/models => github.com/np-guard/models v0.3.5-0.20240818081750-bb83d7f53d64 diff --git a/go.sum b/go.sum index 1b2f9689..b5750e7b 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/np-guard/cloud-resource-collector v0.14.0 h1:MBPtPBYVCQoMfUkn/wODpF7SRpJ9TlOfMszO8N0PePo= github.com/np-guard/cloud-resource-collector v0.14.0/go.mod h1:klCHnNnuuVcCtGQHA7R1a8fqnvfMCk/5Jdld6V7sN2A= -github.com/np-guard/models v0.3.5-0.20240818081750-bb83d7f53d64 h1:e3Fljv3NXu8UogaS4mq8TVqzfga/AuHElL8j0EQLrXw= -github.com/np-guard/models v0.3.5-0.20240818081750-bb83d7f53d64/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= +github.com/np-guard/models v0.4.1-0.20240911081500-0a30b7aefb6f h1:gjmcxRRtiBjDO1mo2XC3yL9KnLM3KvZ/3Ulehv5Cn1c= +github.com/np-guard/models v0.4.1-0.20240911081500-0a30b7aefb6f/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= From dc400bf66d1730ccdedc1c851f40b4e4ff957ae5 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 11 Sep 2024 12:08:23 +0300 Subject: [PATCH 32/79] update --- go.sum | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/go.sum b/go.sum index d5ebcf50..bfbf57e0 100644 --- a/go.sum +++ b/go.sum @@ -132,17 +132,10 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -<<<<<<< HEAD -github.com/np-guard/cloud-resource-collector v0.14.0 h1:MBPtPBYVCQoMfUkn/wODpF7SRpJ9TlOfMszO8N0PePo= -github.com/np-guard/cloud-resource-collector v0.14.0/go.mod h1:klCHnNnuuVcCtGQHA7R1a8fqnvfMCk/5Jdld6V7sN2A= -github.com/np-guard/models v0.4.1-0.20240911081500-0a30b7aefb6f h1:gjmcxRRtiBjDO1mo2XC3yL9KnLM3KvZ/3Ulehv5Cn1c= -github.com/np-guard/models v0.4.1-0.20240911081500-0a30b7aefb6f/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= -======= github.com/np-guard/cloud-resource-collector v0.15.0 h1:jkmxql6D1uBr/qmSOsBzUgeDxlUXSCe7dBKfqfK+QZ4= github.com/np-guard/cloud-resource-collector v0.15.0/go.mod h1:klCHnNnuuVcCtGQHA7R1a8fqnvfMCk/5Jdld6V7sN2A= -github.com/np-guard/models v0.4.0 h1:lU9XymcjwOJ5RQdVpziurqBmcLtlKVIQxVUwm+qMczk= -github.com/np-guard/models v0.4.0/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= ->>>>>>> main +github.com/np-guard/models v0.4.1-0.20240911081500-0a30b7aefb6f h1:gjmcxRRtiBjDO1mo2XC3yL9KnLM3KvZ/3Ulehv5Cn1c= +github.com/np-guard/models v0.4.1-0.20240911081500-0a30b7aefb6f/go.mod h1:mqE2Irf8r+7HWh8fII0fWbWyQRMHGEo2SgSLN/6VKs8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= From 8e5cb2d2a8ffbeba1f4a0ff62da52b1fefd104dc Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 11 Sep 2024 18:18:15 +0300 Subject: [PATCH 33/79] wip --- pkg/optimize/sg.go | 29 ++++++--- pkg/optimize/sgRulesToSpan.go | 117 ++++++++++++++++++++++++++++------ pkg/optimize/spanToSGRules.go | 4 +- 3 files changed, 118 insertions(+), 32 deletions(-) diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 11ad8e42..aa944db2 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -37,9 +37,9 @@ type ( } sgRulesToSGSpans struct { - tcp map[*ir.SGName]*interval.CanonicalSet - udp map[*ir.SGName]*interval.CanonicalSet - icmp map[*ir.SGName]*netset.ICMPSet + tcp map[ir.SGName]*interval.CanonicalSet + udp map[ir.SGName]*interval.CanonicalSet + icmp map[ir.SGName]*netset.ICMPSet all []*ir.SGName } @@ -132,9 +132,9 @@ func (s *SGOptimizer) reduceSGRules(rules []ir.SGRule, direction ir.Direction) [ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGRule { // delete other protocols rules if all protocol rule exists for _, sgName := range spans.all { - delete(spans.tcp, sgName) - delete(spans.udp, sgName) - delete(spans.icmp, sgName) + delete(spans.tcp, *sgName) + delete(spans.udp, *sgName) + delete(spans.icmp, *sgName) } // merge tcp, udp and icmp rules into all protocol rule @@ -145,7 +145,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR delete(spans.tcp, sgName) delete(spans.udp, sgName) delete(spans.icmp, sgName) - spans.all = append(spans.all, sgName) + spans.all = append(spans.all, utils.Ptr(sgName)) } } } @@ -153,7 +153,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR // convert spans to SG rules tcpRules := tcpudpSGSpanToSGRules(spans.tcp, direction, true) - udpRules := tcpudpSGSpanToSGRules(spans.tcp, direction, false) + udpRules := tcpudpSGSpanToSGRules(spans.udp, direction, false) icmpRules := icmpSGSpanToSGRules(spans.icmp, direction) protocolAll := protocolAllSGSpanToSGRules(spans.all, direction) @@ -166,9 +166,20 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction) []ir.SGRule { // Todo: check if we can replace tcp, udp, icmp with protocol all + for i, p := range spans.tcp { + log.Println("pair ", i) + + log.Print("l: ", p.Left.String()) + log.Println("intervals: ") + for _, interval := range p.Right.Intervals() { + log.Println(interval.String()) + } + log.Println("\n\n") + } + // spans to SG rules tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) - udpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, false) + udpRules := tcpudpIPSpanToSGRules(spans.udp, spans.all, direction, false) icmpRules := icmpSpanToSGRules(spans.icmp, spans.all, direction) allRules := allSpanToSGRules(spans.all, direction) diff --git a/pkg/optimize/sgRulesToSpan.go b/pkg/optimize/sgRulesToSpan.go index 4a61d241..79eb0757 100644 --- a/pkg/optimize/sgRulesToSpan.go +++ b/pkg/optimize/sgRulesToSpan.go @@ -24,11 +24,11 @@ func sgRulesToSGToSpans(rules *sgRulesPerProtocol) *sgRulesToSGSpans { return &sgRulesToSGSpans{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} } -func tcpudpRulesToSGToPortsSpan(rules []ir.SGRule) map[*ir.SGName]*interval.CanonicalSet { - result := make(map[*ir.SGName]*interval.CanonicalSet) +func tcpudpRulesToSGToPortsSpan(rules []ir.SGRule) map[ir.SGName]*interval.CanonicalSet { + result := make(map[ir.SGName]*interval.CanonicalSet) for i := range rules { - p := rules[i].Protocol.(netp.TCPUDP) // already checked - remote := utils.Ptr(rules[i].Remote.(ir.SGName)) // already checked + p := rules[i].Protocol.(netp.TCPUDP) // already checked + remote := rules[i].Remote.(ir.SGName) // already checked if result[remote] == nil { result[remote] = interval.NewCanonicalSet() } @@ -37,11 +37,11 @@ func tcpudpRulesToSGToPortsSpan(rules []ir.SGRule) map[*ir.SGName]*interval.Cano return result } -func icmpRulesToSGToSpan(rules []ir.SGRule) map[*ir.SGName]*netset.ICMPSet { - result := make(map[*ir.SGName]*netset.ICMPSet) +func icmpRulesToSGToSpan(rules []ir.SGRule) map[ir.SGName]*netset.ICMPSet { + result := make(map[ir.SGName]*netset.ICMPSet) for i := range rules { - p := rules[i].Protocol.(netp.ICMP) // already checked - remote := utils.Ptr(rules[i].Remote.(ir.SGName)) // already checked + p := rules[i].Protocol.(netp.ICMP) // already checked + remote := rules[i].Remote.(ir.SGName) // already checked if result[remote] == nil { result[remote] = netset.EmptyICMPSet() } @@ -68,25 +68,26 @@ func sgRulesToIPAddrsToSpans(rules *sgRulesPerProtocol) *sgRulesToIPAddrsSpans { return &sgRulesToIPAddrsSpans{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} } -// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span of (IPBlock X ports) +// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span of (IPBlock X ports). +// all IPBlocks are disjoint. func tcpudpRulesToIPAddrsToPortsSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { - span := ds.NewProductLeft[*netset.IPBlock, *interval.CanonicalSet]() - for i := range rules { - p := rules[i].Protocol.(netp.TCPUDP) // already checked - r := ds.CartesianPairLeft(rules[i].Remote.(*netset.IPBlock), p.DstPorts().ToSet()) - span = span.Union(r).(*ds.ProductLeft[*netset.IPBlock, *interval.CanonicalSet]) + span := tcpudpMapSpan(rules) + result := ds.NewProductLeft[*netset.IPBlock, *interval.CanonicalSet]() + for ipblock, portsSet := range span { + r := ds.CartesianPairLeft(ipblock, portsSet) + result = result.Union(r).(*ds.ProductLeft[*netset.IPBlock, *interval.CanonicalSet]) } - return sortPartitionsByIPAddrs(span.Partitions()) + return sortPartitionsByIPAddrs(result.Partitions()) } func icmpRulesToIPAddrsToSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.ICMPSet] { - span := ds.NewProductLeft[*netset.IPBlock, *netset.ICMPSet]() - for i := range rules { - p := rules[i].Protocol.(netp.ICMP) // already checked - r := ds.CartesianPairLeft(rules[i].Remote.(*netset.IPBlock), netset.NewICMPSet(p)) - span = span.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.ICMPSet]) + span := icmpMapSpan((rules)) + result := ds.NewProductLeft[*netset.IPBlock, *netset.ICMPSet]() + for ipblock, icmpSet := range span { + r := ds.CartesianPairLeft(ipblock, icmpSet) + result = result.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.ICMPSet]) } - return sortPartitionsByIPAddrs(span.Partitions()) + return sortPartitionsByIPAddrs(result.Partitions()) } func allProtocolRulesToIPAddrsToSpan(rules []ir.SGRule) []*netset.IPBlock { @@ -96,3 +97,77 @@ func allProtocolRulesToIPAddrsToSpan(rules []ir.SGRule) []*netset.IPBlock { } return sortIPBlockSlice(res.Split()) } + +// Help functions +func tcpudpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*interval.CanonicalSet { + span := make(map[*netset.IPBlock]*interval.CanonicalSet, 0) // all keys are disjoint + for i := range rules { + p := rules[i].Protocol.(netp.TCPUDP) // already checked + portsSet := p.DstPorts().ToSet() + ruleIP := rules[i].Remote.(*netset.IPBlock) // already checked + + if ports, ok := span[ruleIP]; ok { + span[ruleIP] = ports.Union(portsSet) + continue + } + + newMap := make(map[*netset.IPBlock]*interval.CanonicalSet, 0) + for ipblock := range span { + if ipblock.Overlap(ruleIP) { + overlappingIPs := ruleIP.Subtract(ipblock) + for _, ip := range overlappingIPs.Split() { + newMap[ip] = span[ipblock].Copy().Union(portsSet) + } + notOverlappingIPs := ipblock.Subtract(overlappingIPs) + for _, ip := range notOverlappingIPs.Split() { + newMap[ip] = span[ipblock].Copy() + } + } + } + span = mergeTcpudpMaps(span, newMap) + } + return span +} + +func icmpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*netset.ICMPSet { + span := make(map[*netset.IPBlock]*netset.ICMPSet, 0) // all keys are disjoint + for i := range rules { + icmpSet := netset.NewICMPSet(rules[i].Protocol.(netp.ICMP)) // already checked + ruleIP := rules[i].Remote.(*netset.IPBlock) // already checked + + if ports, ok := span[ruleIP]; ok { + span[ruleIP] = ports.Union(icmpSet) + continue + } + + newMap := make(map[*netset.IPBlock]*netset.ICMPSet, 0) + for ipblock := range span { + if ipblock.Overlap(ruleIP) { + overlappingIPs := ruleIP.Subtract(ipblock) + for _, ip := range overlappingIPs.Split() { + newMap[ip] = span[ipblock].Copy().Union(icmpSet) + } + notOverlappingIPs := ipblock.Subtract(overlappingIPs) + for _, ip := range notOverlappingIPs.Split() { + newMap[ip] = span[ipblock].Copy() + } + } + } + span = mergeIcmpMaps(span, newMap) + } + return span +} + +func mergeTcpudpMaps(m1, m2 map[*netset.IPBlock]*interval.CanonicalSet) map[*netset.IPBlock]*interval.CanonicalSet { + for ipblock, portsSet := range m2 { + m1[ipblock] = portsSet.Copy() + } + return m1 +} + +func mergeIcmpMaps(m1, m2 map[*netset.IPBlock]*netset.ICMPSet) map[*netset.IPBlock]*netset.ICMPSet { + for ipblock, portsSet := range m2 { + m1[ipblock] = portsSet.Copy() + } + return m1 +} diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go index ab12f467..1866ac99 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/spanToSGRules.go @@ -15,7 +15,7 @@ import ( ) // SG remote -func tcpudpSGSpanToSGRules(span map[*ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []ir.SGRule { +func tcpudpSGSpanToSGRules(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []ir.SGRule { result := make([]ir.SGRule, 0) for sgName, intervals := range span { for _, dstPorts := range intervals.Intervals() { @@ -26,7 +26,7 @@ func tcpudpSGSpanToSGRules(span map[*ir.SGName]*interval.CanonicalSet, direction return result } -func icmpSGSpanToSGRules(span map[*ir.SGName]*netset.ICMPSet, direction ir.Direction) []ir.SGRule { +func icmpSGSpanToSGRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction) []ir.SGRule { result := make([]ir.SGRule, 0) for sgName, icmpSet := range span { for _, icmp := range icmpSet.Partitions() { From a86172246fa89a4a15090174b07af48858c91ed8 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Thu, 12 Sep 2024 15:11:08 +0300 Subject: [PATCH 34/79] wip --- pkg/optimize/common.go | 6 --- pkg/optimize/ip.go | 8 +++ pkg/optimize/sg.go | 4 +- pkg/optimize/sgRulesToSpan.go | 96 ++++++++++++++--------------------- pkg/optimize/spanToSGRules.go | 26 +++++----- pkg/utils/utils.go | 10 ++++ 6 files changed, 70 insertions(+), 80 deletions(-) diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index 46c0070a..1f95beab 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -34,12 +34,6 @@ func sortPartitionsByIPAddrs[T any](p []ds.Pair[*netset.IPBlock, T]) []ds.Pair[* return p } -func sortIPBlockSlice(s []*netset.IPBlock) []*netset.IPBlock { - cmp := func(i, j int) bool { return s[i].FirstIPAddress() < s[j].FirstIPAddress() } - sort.Slice(s, cmp) - return s -} - func allPorts(ports *interval.CanonicalSet) bool { return ports.Equal(netp.AllPorts().ToSet()) } diff --git a/pkg/optimize/ip.go b/pkg/optimize/ip.go index 348b8aa8..89bf4e9f 100644 --- a/pkg/optimize/ip.go +++ b/pkg/optimize/ip.go @@ -66,3 +66,11 @@ func FirstIPAddress(i *netset.IPBlock) *netset.IPBlock { } return ipblock } + +func NextIP(ip *netset.IPBlock) *netset.IPBlock { + return ip +} + +func BeforeIP(ip *netset.IPBlock) *netset.IPBlock { + return ip +} diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index aa944db2..14621bd8 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -47,7 +47,7 @@ type ( tcp []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] udp []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] icmp []ds.Pair[*netset.IPBlock, *netset.ICMPSet] - all []*netset.IPBlock + all *netset.IPBlock } ) @@ -181,7 +181,7 @@ func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) udpRules := tcpudpIPSpanToSGRules(spans.udp, spans.all, direction, false) icmpRules := icmpSpanToSGRules(spans.icmp, spans.all, direction) - allRules := allSpanToSGRules(spans.all, direction) + allRules := allSpanIPToSGRules(spans.all, direction) tcpudp := append(tcpRules, udpRules...) //nolint:gocritic // should merge all rules together icmpAll := append(icmpRules, allRules...) //nolint:gocritic // should merge all rules together diff --git a/pkg/optimize/sgRulesToSpan.go b/pkg/optimize/sgRulesToSpan.go index 79eb0757..0edbbc88 100644 --- a/pkg/optimize/sgRulesToSpan.go +++ b/pkg/optimize/sgRulesToSpan.go @@ -6,6 +6,8 @@ SPDX-License-Identifier: Apache-2.0 package optimize import ( + "log" + "github.com/np-guard/models/pkg/ds" "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" @@ -68,6 +70,14 @@ func sgRulesToIPAddrsToSpans(rules *sgRulesPerProtocol) *sgRulesToIPAddrsSpans { return &sgRulesToIPAddrsSpans{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} } +func allProtocolRulesToIPAddrsToSpan(rules []ir.SGRule) *netset.IPBlock { + res := netset.NewIPBlock() + for i := range rules { + res.Union(rules[i].Remote.(*netset.IPBlock)) + } + return res +} + // converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span of (IPBlock X ports). // all IPBlocks are disjoint. func tcpudpRulesToIPAddrsToPortsSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { @@ -90,41 +100,13 @@ func icmpRulesToIPAddrsToSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBlock, *net return sortPartitionsByIPAddrs(result.Partitions()) } -func allProtocolRulesToIPAddrsToSpan(rules []ir.SGRule) []*netset.IPBlock { - res := netset.NewIPBlock() - for i := range rules { - res.Union(rules[i].Remote.(*netset.IPBlock)) - } - return sortIPBlockSlice(res.Split()) -} - // Help functions func tcpudpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*interval.CanonicalSet { span := make(map[*netset.IPBlock]*interval.CanonicalSet, 0) // all keys are disjoint for i := range rules { - p := rules[i].Protocol.(netp.TCPUDP) // already checked - portsSet := p.DstPorts().ToSet() - ruleIP := rules[i].Remote.(*netset.IPBlock) // already checked - - if ports, ok := span[ruleIP]; ok { - span[ruleIP] = ports.Union(portsSet) - continue - } - - newMap := make(map[*netset.IPBlock]*interval.CanonicalSet, 0) - for ipblock := range span { - if ipblock.Overlap(ruleIP) { - overlappingIPs := ruleIP.Subtract(ipblock) - for _, ip := range overlappingIPs.Split() { - newMap[ip] = span[ipblock].Copy().Union(portsSet) - } - notOverlappingIPs := ipblock.Subtract(overlappingIPs) - for _, ip := range notOverlappingIPs.Split() { - newMap[ip] = span[ipblock].Copy() - } - } - } - span = mergeTcpudpMaps(span, newMap) + portsSet := rules[i].Protocol.(netp.TCPUDP).DstPorts().ToSet() // already checked + ruleIP := rules[i].Remote.(*netset.IPBlock) // already checked + span = updateSpan(span, portsSet, ruleIP) } return span } @@ -134,40 +116,36 @@ func icmpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*netset.ICMPSet { for i := range rules { icmpSet := netset.NewICMPSet(rules[i].Protocol.(netp.ICMP)) // already checked ruleIP := rules[i].Remote.(*netset.IPBlock) // already checked - - if ports, ok := span[ruleIP]; ok { - span[ruleIP] = ports.Union(icmpSet) - continue - } - - newMap := make(map[*netset.IPBlock]*netset.ICMPSet, 0) - for ipblock := range span { - if ipblock.Overlap(ruleIP) { - overlappingIPs := ruleIP.Subtract(ipblock) - for _, ip := range overlappingIPs.Split() { - newMap[ip] = span[ipblock].Copy().Union(icmpSet) - } - notOverlappingIPs := ipblock.Subtract(overlappingIPs) - for _, ip := range notOverlappingIPs.Split() { - newMap[ip] = span[ipblock].Copy() - } - } - } - span = mergeIcmpMaps(span, newMap) + span = updateSpan(span, icmpSet, ruleIP) } return span } -func mergeTcpudpMaps(m1, m2 map[*netset.IPBlock]*interval.CanonicalSet) map[*netset.IPBlock]*interval.CanonicalSet { - for ipblock, portsSet := range m2 { - m1[ipblock] = portsSet.Copy() +func updateSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleSet T, ruleIP *netset.IPBlock) map[*netset.IPBlock]T { + if protocolSet, ok := span[ruleIP]; ok { + span[ruleIP] = protocolSet.Union(ruleSet) + return span } - return m1 + var k float32 + k = 32.2 + log.Print(k) + return utils.MergeSetMaps(span, addRuleToSpan(span, ruleIP, ruleSet)) + } -func mergeIcmpMaps(m1, m2 map[*netset.IPBlock]*netset.ICMPSet) map[*netset.IPBlock]*netset.ICMPSet { - for ipblock, portsSet := range m2 { - m1[ipblock] = portsSet.Copy() +func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlock, ruleSet T) map[*netset.IPBlock]T { + result := make(map[*netset.IPBlock]T, 0) + for ipblock := range span { + if ipblock.Overlap(ruleIP) { + overlappingIPs := ruleIP.Subtract(ipblock) + for _, ip := range overlappingIPs.Split() { + result[ip] = span[ipblock].Copy().Union(ruleSet) + } + notOverlappingIPs := ipblock.Subtract(overlappingIPs) + for _, ip := range notOverlappingIPs.Split() { + result[ip] = span[ipblock].Copy() + } + } } - return m1 + return result } diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go index 1866ac99..41cfe744 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/spanToSGRules.go @@ -46,13 +46,23 @@ func protocolAllSGSpanToSGRules(span []*ir.SGName, direction ir.Direction) []ir. } // IPAddrs remote -func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], _ []*netset.IPBlock, +func allSpanIPToSGRules(span *netset.IPBlock, direction ir.Direction) []ir.SGRule { + result := make([]ir.SGRule, 0) + for _, cidr := range ToCidrs(span) { + result = append(result, ir.NewSGRule(direction, cidr, netp.AnyProtocol{}, netset.GetCidrAll(), "")) + } + return result +} + +func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], allSpan *netset.IPBlock, direction ir.Direction, isTCP bool) []ir.SGRule { rules := []ds.Pair[*netset.IPBlock, *interval.Interval]{} // start ip and ports result := make([]ir.SGRule, 0) for i := range span { - if i > 0 && !touching(span[i-1].Left, span[i].Left) { // if the CIDRS are not touching + // should be here if i > 0 + // hole := IPBlockFromRange(NextIP(LastIPAddress(span[i-1].Left)), BeforeIP(FirstIPAddress(span[i].Left))) + if i > 0 && !touching(span[i-1].Left, span[i].Left) { // if the CIDRS are not touching and there is no all rule for _, r := range rules { p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { @@ -96,7 +106,7 @@ func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSe return result } -func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ []*netset.IPBlock, direction ir.Direction) []ir.SGRule { +func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allSpan *netset.IPBlock, direction ir.Direction) []ir.SGRule { rules := []ds.Pair[*netset.IPBlock, *netp.ICMP]{} result := make([]ir.SGRule, 0) @@ -145,13 +155,3 @@ func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ []*ne return result } - -func allSpanToSGRules(span []*netset.IPBlock, direction ir.Direction) []ir.SGRule { - result := make([]ir.SGRule, 0) - for _, ipAddrs := range span { - for _, cidr := range ToCidrs(ipAddrs) { - result = append(result, ir.NewSGRule(direction, cidr, netp.AnyProtocol{}, netset.GetCidrAll(), "")) - } - } - return result -} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index ab4783d5..c867fc55 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -9,6 +9,8 @@ import ( "cmp" "maps" "slices" + + "github.com/np-guard/models/pkg/ds" ) func Ptr[T any](t T) *T { @@ -55,3 +57,11 @@ func ToPtrSlice[T any](s []T) []*T { } return res } + +// m1 does not have any key of m2 +func MergeSetMaps[T comparable, K ds.Set[K]](m1, m2 map[T]K) map[T]K { + for key, val := range m2 { + m1[key] = val.Copy() + } + return m1 +} From 380c62e9cb3c812555e35c563e4a8860b3160b31 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Thu, 12 Sep 2024 15:42:33 +0300 Subject: [PATCH 35/79] fixed --- pkg/io/confio/parse_sgs.go | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index ce685abd..f97cdb6d 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -152,19 +152,33 @@ func translateRemote(remote vpcv1.SecurityGroupRuleRemoteIntf) (ir.RemoteType, e } func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, error) { + var err error + var ipAddrs *netset.IPBlock if l, ok := local.(*vpcv1.SecurityGroupRuleLocal); ok { if l.CIDRBlock != nil { - return netset.IPBlockFromCidr(*l.CIDRBlock) + ipAddrs, err = netset.IPBlockFromCidr(*l.CIDRBlock) } if l.Address != nil { - return netset.IPBlockFromIPAddress(*l.CIDRBlock) + ipAddrs, err = netset.IPBlockFromIPAddress(*l.CIDRBlock) } + if err != nil { + return nil, err + } + return verifyLocalValue(ipAddrs) } return nil, fmt.Errorf("error parsing Local field") } +// temporary - first version of optimization requires that local value will be 0.0.0.0/32 +func verifyLocalValue(ipAddrs *netset.IPBlock) (*netset.IPBlock, error) { + if !ipAddrs.Equal(netset.GetCidrAll()) { + return nil, fmt.Errorf("only 0.0.0.0/32 CIDR block is supported for local values") + } + return ipAddrs, nil +} + func translateProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (netp.Protocol, error) { - isTCP := *rule.Protocol == string(netp.ProtocolStringTCP) + isTCP := *rule.Protocol == "tcp" minDstPort := utils.GetProperty(rule.PortMin, netp.MinPort) maxDstPort := utils.GetProperty(rule.PortMax, netp.MaxPort) return netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(minDstPort), int(maxDstPort)) From 197ed317f695b0c621b5c58766bc4c06f8348217 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Thu, 12 Sep 2024 15:47:21 +0300 Subject: [PATCH 36/79] fixed --- cmd/subcmds/optimize.go | 2 +- cmd/subcmds/outputCommon.go | 2 ++ cmd/subcmds/synthOutput.go | 1 - 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index 4b215fe1..fe137a15 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -21,7 +21,7 @@ func NewOptimizeCommand(args *inArgs) *cobra.Command { } // flags - cmd.Flags().StringVarP(&args.firewallName, firewallNameFlag, "s", "", "which vpcFirewall to optimize") + cmd.PersistentFlags().StringVarP(&args.firewallName, firewallNameFlag, "n", "", "which vpcFirewall to optimize") // flags settings _ = cmd.MarkPersistentFlagRequired(firewallNameFlag) // temporary diff --git a/cmd/subcmds/outputCommon.go b/cmd/subcmds/outputCommon.go index 55872136..aa399315 100644 --- a/cmd/subcmds/outputCommon.go +++ b/cmd/subcmds/outputCommon.go @@ -15,6 +15,8 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) +const defaultFilePermission = 0o644 + func checkOutputFlags(args *inArgs) error { if args.outputDir != "" && args.outputFile != "" { return fmt.Errorf("only one of -d and -o can be supplied") diff --git a/cmd/subcmds/synthOutput.go b/cmd/subcmds/synthOutput.go index c1ba8a0d..12e0670b 100644 --- a/cmd/subcmds/synthOutput.go +++ b/cmd/subcmds/synthOutput.go @@ -19,7 +19,6 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -const defaultFilePermission = 0o644 const defaultDirectoryPermission = 0o755 func writeOutput(args *inArgs, collection ir.SynthCollection, vpcNames []ir.ID) error { From 9078e5c96b896eac2829630547c24ec0ec5006cf Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Thu, 12 Sep 2024 16:02:03 +0300 Subject: [PATCH 37/79] wip --- pkg/optimize/ip.go | 2 ++ pkg/optimize/sg.go | 13 +------------ pkg/optimize/sgRulesToSpan.go | 6 ------ pkg/optimize/spanToSGRules.go | 7 +++---- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/pkg/optimize/ip.go b/pkg/optimize/ip.go index 89bf4e9f..3f61e621 100644 --- a/pkg/optimize/ip.go +++ b/pkg/optimize/ip.go @@ -67,10 +67,12 @@ func FirstIPAddress(i *netset.IPBlock) *netset.IPBlock { return ipblock } +// should implement func NextIP(ip *netset.IPBlock) *netset.IPBlock { return ip } +// should implement func BeforeIP(ip *netset.IPBlock) *netset.IPBlock { return ip } diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 14621bd8..be1df47c 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -164,18 +164,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR } func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction) []ir.SGRule { - // Todo: check if we can replace tcp, udp, icmp with protocol all - - for i, p := range spans.tcp { - log.Println("pair ", i) - - log.Print("l: ", p.Left.String()) - log.Println("intervals: ") - for _, interval := range p.Right.Intervals() { - log.Println(interval.String()) - } - log.Println("\n\n") - } + // Todo: check if we can replace tcp, udp, icmp with protocol all. Maybe we should not? // spans to SG rules tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) diff --git a/pkg/optimize/sgRulesToSpan.go b/pkg/optimize/sgRulesToSpan.go index 0edbbc88..ac37cf4c 100644 --- a/pkg/optimize/sgRulesToSpan.go +++ b/pkg/optimize/sgRulesToSpan.go @@ -6,8 +6,6 @@ SPDX-License-Identifier: Apache-2.0 package optimize import ( - "log" - "github.com/np-guard/models/pkg/ds" "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" @@ -126,11 +124,7 @@ func updateSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleSet T, ruleIP *nets span[ruleIP] = protocolSet.Union(ruleSet) return span } - var k float32 - k = 32.2 - log.Print(k) return utils.MergeSetMaps(span, addRuleToSpan(span, ruleIP, ruleSet)) - } func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlock, ruleSet T) map[*netset.IPBlock]T { diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go index 41cfe744..d0e87c15 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/spanToSGRules.go @@ -54,14 +54,13 @@ func allSpanIPToSGRules(span *netset.IPBlock, direction ir.Direction) []ir.SGRul return result } -func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], allSpan *netset.IPBlock, +func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], _ *netset.IPBlock, direction ir.Direction, isTCP bool) []ir.SGRule { rules := []ds.Pair[*netset.IPBlock, *interval.Interval]{} // start ip and ports result := make([]ir.SGRule, 0) for i := range span { - // should be here if i > 0 - // hole := IPBlockFromRange(NextIP(LastIPAddress(span[i-1].Left)), BeforeIP(FirstIPAddress(span[i].Left))) + // maybe all protocol rule covers the hole if i > 0 && !touching(span[i-1].Left, span[i].Left) { // if the CIDRS are not touching and there is no all rule for _, r := range rules { p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) @@ -106,7 +105,7 @@ func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSe return result } -func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allSpan *netset.IPBlock, direction ir.Direction) []ir.SGRule { +func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ *netset.IPBlock, direction ir.Direction) []ir.SGRule { rules := []ds.Pair[*netset.IPBlock, *netp.ICMP]{} result := make([]ir.SGRule, 0) From dfb8a7dd33d624cf35ba4c810f7b0dba9e566af8 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Thu, 12 Sep 2024 16:03:58 +0300 Subject: [PATCH 38/79] wip --- pkg/optimize/sg.go | 2 +- pkg/optimize/spanToSGRules.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index be1df47c..36870b76 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -164,7 +164,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR } func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction) []ir.SGRule { - // Todo: check if we can replace tcp, udp, icmp with protocol all. Maybe we should not? + // Todo: check if we can replace tcp, udp, icmp with protocol all. Should we? // spans to SG rules tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go index d0e87c15..01fb437a 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/spanToSGRules.go @@ -75,7 +75,7 @@ func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSe activePorts := interval.NewCanonicalSet() for _, r := range rules { - if !r.Right.ToSet().IsSubset(span[i].Right) { // close old rules + if !r.Right.ToSet().IsSubset(span[i].Right) { // create rules p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) @@ -94,7 +94,7 @@ func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSe } } - // close all old rules + // create the rest of the rules for _, r := range rules { p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.Start())) for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { @@ -125,7 +125,7 @@ func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ *nets activeICMP := netset.EmptyICMPSet() for _, r := range rules { ruleIcmpSet := netset.NewICMPSet(*r.Right) - if !ruleIcmpSet.IsSubset(span[i].Right) { // close old rules + if !ruleIcmpSet.IsSubset(span[i].Right) { // create rules p, _ := netp.NewICMP(r.Right.TypeCode) for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) @@ -144,7 +144,7 @@ func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ *nets } } - // close all rules + // create the rest of the rules for _, r := range rules { p, _ := netp.NewICMP(r.Right.TypeCode) for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { From 88951493fe9f1c37758becbac0b6ecddeb539662 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Thu, 12 Sep 2024 16:53:12 +0300 Subject: [PATCH 39/79] implement ip functions --- pkg/optimize/ip.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkg/optimize/ip.go b/pkg/optimize/ip.go index 3f61e621..0c51dff4 100644 --- a/pkg/optimize/ip.go +++ b/pkg/optimize/ip.go @@ -67,12 +67,14 @@ func FirstIPAddress(i *netset.IPBlock) *netset.IPBlock { return ipblock } -// should implement +// ip is not 255.255.255.255 func NextIP(ip *netset.IPBlock) *netset.IPBlock { - return ip + other := netset.GetCidrAll().Subtract(ip) + return FirstIPAddress(other.Split()[1]) } -// should implement +// ip is not 0.0.0.0 func BeforeIP(ip *netset.IPBlock) *netset.IPBlock { - return ip + other := netset.GetCidrAll().Subtract(ip) + return LastIPAddress(other.Split()[0]) } From c8fe2d726d8451a9299d9399e3672953c23d03cf Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Thu, 12 Sep 2024 17:19:50 +0300 Subject: [PATCH 40/79] all protocol rule covers the holes --- pkg/optimize/spanToSGRules.go | 47 +++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go index 01fb437a..15310e4d 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/spanToSGRules.go @@ -54,23 +54,27 @@ func allSpanIPToSGRules(span *netset.IPBlock, direction ir.Direction) []ir.SGRul return result } -func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], _ *netset.IPBlock, +func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], allSpan *netset.IPBlock, direction ir.Direction, isTCP bool) []ir.SGRule { rules := []ds.Pair[*netset.IPBlock, *interval.Interval]{} // start ip and ports result := make([]ir.SGRule, 0) for i := range span { - // maybe all protocol rule covers the hole - if i > 0 && !touching(span[i-1].Left, span[i].Left) { // if the CIDRS are not touching and there is no all rule - for _, r := range rules { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + if i > 0 { + prevIPBlock := span[i-1].Left + currIPBlock := span[i].Left + if !touching(prevIPBlock, currIPBlock) { // the cidrs are not touching + hole := IPBlockFromRange(NextIP(prevIPBlock), BeforeIP(currIPBlock)) + if !hole.IsSubset(allSpan) { // there in no all rule covering the hole + for _, r := range rules { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + rules = []ds.Pair[*netset.IPBlock, *interval.Interval]{} } } - - rules = []ds.Pair[*netset.IPBlock, *interval.Interval]{} - continue } activePorts := interval.NewCanonicalSet() @@ -105,21 +109,26 @@ func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSe return result } -func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], _ *netset.IPBlock, direction ir.Direction) []ir.SGRule { +func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allSpan *netset.IPBlock, direction ir.Direction) []ir.SGRule { rules := []ds.Pair[*netset.IPBlock, *netp.ICMP]{} result := make([]ir.SGRule, 0) for i := range span { - if i > 0 && !touching(span[i-1].Left, span[i].Left) { // if the CIDRS are not touching - for _, r := range rules { - p, _ := netp.NewICMP(r.Right.TypeCode) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + if i > 0 { + prevIPBlock := span[i-1].Left + currIPBlock := span[i].Left + if !touching(prevIPBlock, currIPBlock) { // the cidrs are not touching + hole := IPBlockFromRange(NextIP(prevIPBlock), BeforeIP(currIPBlock)) + if !hole.IsSubset(allSpan) { // there in no all rule covering the hole + for _, r := range rules { + p, _ := netp.NewICMP(r.Right.TypeCode) + for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + rules = []ds.Pair[*netset.IPBlock, *netp.ICMP]{} } } - - rules = []ds.Pair[*netset.IPBlock, *netp.ICMP]{} - continue } activeICMP := netset.EmptyICMPSet() From 0a0decdbfa213b8c0f4c19a54bb11c70a5b3ace7 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 24 Sep 2024 09:44:06 +0300 Subject: [PATCH 41/79] wip --- pkg/optimize/sg.go | 21 ++++++++------------- pkg/optimize/sgRulesToSpan.go | 29 ++++++++++++++++------------- pkg/optimize/spanToSGRules.go | 13 +++++++++++++ 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 36870b76..1e0cec3a 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -155,16 +155,15 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR tcpRules := tcpudpSGSpanToSGRules(spans.tcp, direction, true) udpRules := tcpudpSGSpanToSGRules(spans.udp, direction, false) icmpRules := icmpSGSpanToSGRules(spans.icmp, direction) - protocolAll := protocolAllSGSpanToSGRules(spans.all, direction) + allRules := protocolAllSGSpanToSGRules(spans.all, direction) - // merge all rules together - tcpudp := append(tcpRules, udpRules...) //nolint:gocritic // should merge all rules together - icmpAll := append(icmpRules, protocolAll...) //nolint:gocritic // should merge all rules together - return append(tcpudp, icmpAll...) + // return all rules + return append(tcpRules, append(udpRules, append(icmpRules, allRules...)...)...) } func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction) []ir.SGRule { - // Todo: check if we can replace tcp, udp, icmp with protocol all. Should we? + // observation: It pays to switch to all protocol rule when we have rules that cover all other protocols + // on exactly the same cidr (only one protocol can exceed). // spans to SG rules tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) @@ -172,10 +171,8 @@ func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction icmpRules := icmpSpanToSGRules(spans.icmp, spans.all, direction) allRules := allSpanIPToSGRules(spans.all, direction) - tcpudp := append(tcpRules, udpRules...) //nolint:gocritic // should merge all rules together - icmpAll := append(icmpRules, allRules...) //nolint:gocritic // should merge all rules together - - return append(tcpudp, icmpAll...) + // return all rules + return append(tcpRules, append(udpRules, append(icmpRules, allRules...)...)...) } // divide SGCollection to TCP/UDP/ICMP/ProtocolALL X SGRemote/IPAddrs rules @@ -226,7 +223,5 @@ func divideSGRules(rules []ir.SGRule) *sgRuleGroups { } func (s *sgRulesPerProtocol) allRules() []ir.SGRule { - tcpudp := append(s.tcp, s.udp...) //nolint:gocritic // should merge all rules together - icmpAll := append(s.icmp, s.all...) //nolint:gocritic // should merge all rules together - return append(tcpudp, icmpAll...) + return append(s.tcp, append(s.udp, append(s.icmp, s.all...)...)...) } diff --git a/pkg/optimize/sgRulesToSpan.go b/pkg/optimize/sgRulesToSpan.go index ac37cf4c..a9779988 100644 --- a/pkg/optimize/sgRulesToSpan.go +++ b/pkg/optimize/sgRulesToSpan.go @@ -124,22 +124,25 @@ func updateSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleSet T, ruleIP *nets span[ruleIP] = protocolSet.Union(ruleSet) return span } - return utils.MergeSetMaps(span, addRuleToSpan(span, ruleIP, ruleSet)) + span, newMap := addRuleToSpan(span, ruleIP, ruleSet) + return utils.MergeSetMaps(span, newMap) } -func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlock, ruleSet T) map[*netset.IPBlock]T { - result := make(map[*netset.IPBlock]T, 0) +func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlock, ruleSet T) (s, res map[*netset.IPBlock]T) { + res = make(map[*netset.IPBlock]T, 0) for ipblock := range span { - if ipblock.Overlap(ruleIP) { - overlappingIPs := ruleIP.Subtract(ipblock) - for _, ip := range overlappingIPs.Split() { - result[ip] = span[ipblock].Copy().Union(ruleSet) - } - notOverlappingIPs := ipblock.Subtract(overlappingIPs) - for _, ip := range notOverlappingIPs.Split() { - result[ip] = span[ipblock].Copy() - } + if !ipblock.Overlap(ruleIP) { + continue } + overlappingIPs := ruleIP.Subtract(ipblock) + for _, ip := range overlappingIPs.Split() { + res[ip] = span[ipblock].Copy().Union(ruleSet) + } + notOverlappingIPs := ipblock.Subtract(overlappingIPs) + for _, ip := range notOverlappingIPs.Split() { + res[ip] = span[ipblock].Copy() + } + delete(span, ipblock) } - return result + return span, res } diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/spanToSGRules.go index 15310e4d..b4a680be 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/spanToSGRules.go @@ -109,6 +109,19 @@ func tcpudpIPSpanToSGRules(span []ds.Pair[*netset.IPBlock, *interval.CanonicalSe return result } +// problem: where should I end the rule? +// func createTcpudpRules(rules []ds.Pair[*netset.IPBlock, *interval.Interval], span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], +// direction ir.Direction, isTCP bool) (res []ir.SGRule) { +// res = make([]ir.SGRule, 0) +// for _, r := range rules { +// p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.Start())) +// for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { +// res = append(res, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) +// } +// } +// return res +// } + func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allSpan *netset.IPBlock, direction ir.Direction) []ir.SGRule { rules := []ds.Pair[*netset.IPBlock, *netp.ICMP]{} result := make([]ir.SGRule, 0) From cf119cce1b5d86e3cfe51518019855f8df40b846 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 24 Sep 2024 12:22:10 +0300 Subject: [PATCH 42/79] wip --- pkg/optimize/common.go | 4 ++++ pkg/optimize/sg.go | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index 1f95beab..e817d161 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -34,6 +34,10 @@ func sortPartitionsByIPAddrs[T any](p []ds.Pair[*netset.IPBlock, T]) []ds.Pair[* return p } +// func less(i, j *netset.IPBlock) bool { +// return i.FirstIPAddress() < j.FirstIPAddress() +// } + func allPorts(ports *interval.CanonicalSet) bool { return ports.Equal(netp.AllPorts().ToSet()) } diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 1e0cec3a..52eebfce 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -162,8 +162,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR } func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction) []ir.SGRule { - // observation: It pays to switch to all protocol rule when we have rules that cover all other protocols - // on exactly the same cidr (only one protocol can exceed). + spans = compressToAllProtocolRule(spans) // spans to SG rules tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) @@ -222,6 +221,38 @@ func divideSGRules(rules []ir.SGRule) *sgRuleGroups { return &sgRuleGroups{rulesToSG: rulesToSG, rulesToIPAddrs: rulesToIPAddrs} } +// observation: It pays to switch to all protocol rule when we have rules that cover all other protocols +// on exactly the same cidr (only one protocol can exceed). +func compressToAllProtocolRule(span *sgRulesToIPAddrsSpans) *sgRulesToIPAddrsSpans { + t := 0 + u := 0 + i := 0 + + for t != len(span.tcp) && u != len(span.udp) && i != len(span.icmp) { + if !allPorts(span.tcp[t].Right) { + t++ + continue + } + if !allPorts(span.udp[u].Right) { + u++ + continue + } + if !span.icmp[i].Right.Equal(netset.AllICMPSet()) { + i++ + continue + } + + if span.tcp[t].Left.Equal(span.udp[u].Left) && span.tcp[t].Left.Equal(span.icmp[i].Left) { + span.all = span.all.Union(span.tcp[t].Left.Copy()) + span.tcp = append(span.tcp[:t], span.tcp[t+1:]...) + span.udp = append(span.udp[:u], span.udp[u+1:]...) + span.icmp = append(span.icmp[:i], span.icmp[i+1:]...) + } + } + + return span +} + func (s *sgRulesPerProtocol) allRules() []ir.SGRule { return append(s.tcp, append(s.udp, append(s.icmp, s.all...)...)...) } From a51e158d4a8b57d136bfb131c54b6d5a16064e53 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 24 Sep 2024 15:43:13 +0300 Subject: [PATCH 43/79] documentation --- pkg/optimize/compressRules.go | 75 +++++++++++++++++++ pkg/optimize/ip.go | 1 + .../{spanToSGRules.go => ipSpanToSGRules.go} | 31 -------- pkg/optimize/sg.go | 62 ++------------- ...{sgRulesToSpan.go => sgRulesToIPToSpan.go} | 74 ++++++------------ pkg/optimize/sgRulesToSGToSpan.go | 62 +++++++++++++++ pkg/optimize/sgSpanToSGRules.go | 47 ++++++++++++ pkg/synth/sg.go | 1 + 8 files changed, 216 insertions(+), 137 deletions(-) create mode 100644 pkg/optimize/compressRules.go rename pkg/optimize/{spanToSGRules.go => ipSpanToSGRules.go} (82%) rename pkg/optimize/{sgRulesToSpan.go => sgRulesToIPToSpan.go} (64%) create mode 100644 pkg/optimize/sgRulesToSGToSpan.go create mode 100644 pkg/optimize/sgSpanToSGRules.go diff --git a/pkg/optimize/compressRules.go b/pkg/optimize/compressRules.go new file mode 100644 index 00000000..67757fc8 --- /dev/null +++ b/pkg/optimize/compressRules.go @@ -0,0 +1,75 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import ( + "github.com/np-guard/models/pkg/netset" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" +) + +func compressSpansToSG(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { + spans = deleteOtherProtocolIfAllProtocolExists(spans) + return compressThreeProtocolsToAllProtocol(spans) +} + +// delete other protocols rules if all protocol rule exists +func deleteOtherProtocolIfAllProtocolExists(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { + for _, sgName := range spans.all { + delete(spans.tcp, *sgName) + delete(spans.udp, *sgName) + delete(spans.icmp, *sgName) + } + return spans +} + +// merge tcp, udp and icmp rules into all protocol rule +func compressThreeProtocolsToAllProtocol(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { + for sgName, tcpPorts := range spans.tcp { + if udpPorts, ok := spans.udp[sgName]; ok { + if ic, ok := spans.icmp[sgName]; ok { + if ic.Equal(netset.AllICMPSet()) && allPorts(tcpPorts) && allPorts(udpPorts) { // all tcp&udp ports and all icmp types&codes + delete(spans.tcp, sgName) + delete(spans.udp, sgName) + delete(spans.icmp, sgName) + spans.all = append(spans.all, utils.Ptr(sgName)) + } + } + } + } + return spans +} + +// observation: It pays to switch to all protocol rule when we have rules that cover all other protocols +// on exactly the same cidr (only one protocol can exceed). +func compressToAllProtocolRule(span *sgSpansToIPPerProtocol) *sgSpansToIPPerProtocol { + t := 0 + u := 0 + i := 0 + + for t != len(span.tcp) && u != len(span.udp) && i != len(span.icmp) { + if !allPorts(span.tcp[t].Right) { + t++ + continue + } + if !allPorts(span.udp[u].Right) { + u++ + continue + } + if !span.icmp[i].Right.Equal(netset.AllICMPSet()) { + i++ + continue + } + + if span.tcp[t].Left.Equal(span.udp[u].Left) && span.tcp[t].Left.Equal(span.icmp[i].Left) { + span.all = span.all.Union(span.tcp[t].Left.Copy()) + span.tcp = append(span.tcp[:t], span.tcp[t+1:]...) + span.udp = append(span.udp[:u], span.udp[u+1:]...) + span.icmp = append(span.icmp[:i], span.icmp[i+1:]...) + } + } + + return span +} diff --git a/pkg/optimize/ip.go b/pkg/optimize/ip.go index 0c51dff4..c1a844af 100644 --- a/pkg/optimize/ip.go +++ b/pkg/optimize/ip.go @@ -23,6 +23,7 @@ func touching(a, b *netset.IPBlock) bool { return len(ranges) == 1 } +// last IP address of a cidr func LastIPAddress(i *netset.IPBlock) *netset.IPBlock { IPRanges := i.ToIPRanges() ranges := strings.Split(IPRanges, commaSeparator) diff --git a/pkg/optimize/spanToSGRules.go b/pkg/optimize/ipSpanToSGRules.go similarity index 82% rename from pkg/optimize/spanToSGRules.go rename to pkg/optimize/ipSpanToSGRules.go index b4a680be..f031abee 100644 --- a/pkg/optimize/spanToSGRules.go +++ b/pkg/optimize/ipSpanToSGRules.go @@ -14,37 +14,6 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// SG remote -func tcpudpSGSpanToSGRules(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []ir.SGRule { - result := make([]ir.SGRule, 0) - for sgName, intervals := range span { - for _, dstPorts := range intervals.Intervals() { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) - result = append(result, ir.NewSGRule(direction, sgName, p, netset.GetCidrAll(), "")) - } - } - return result -} - -func icmpSGSpanToSGRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction) []ir.SGRule { - result := make([]ir.SGRule, 0) - for sgName, icmpSet := range span { - for _, icmp := range icmpSet.Partitions() { - p, _ := netp.NewICMP(icmp.TypeCode) - result = append(result, ir.NewSGRule(direction, sgName, p, netset.GetCidrAll(), "")) - } - } - return result -} - -func protocolAllSGSpanToSGRules(span []*ir.SGName, direction ir.Direction) []ir.SGRule { - result := make([]ir.SGRule, len(span)) - for i, sgName := range span { - result[i] = ir.NewSGRule(direction, sgName, netp.AnyProtocol{}, netset.GetCidrAll(), "") - } - return result -} - // IPAddrs remote func allSpanIPToSGRules(span *netset.IPBlock, direction ir.Direction) []ir.SGRule { result := make([]ir.SGRule, 0) diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 52eebfce..97ad5c2d 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -36,14 +36,14 @@ type ( all []ir.SGRule } - sgRulesToSGSpans struct { + sgSpansToSGPerProtocol struct { tcp map[ir.SGName]*interval.CanonicalSet udp map[ir.SGName]*interval.CanonicalSet icmp map[ir.SGName]*netset.ICMPSet all []*ir.SGName } - sgRulesToIPAddrsSpans struct { + sgSpansToIPPerProtocol struct { tcp []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] udp []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] icmp []ds.Pair[*netset.IPBlock, *netset.ICMPSet] @@ -111,6 +111,7 @@ func (s *SGOptimizer) Optimize() ir.OptimizeCollection { // reduceSGRules attempts to reduce the number of rules with different remote types separately func (s *SGOptimizer) reduceSGRules(rules []ir.SGRule, direction ir.Direction) []ir.SGRule { + // separate all rules to groups of (protocol X remote) ruleGroups := divideSGRules(rules) // rules with SG as a remote @@ -129,27 +130,8 @@ func (s *SGOptimizer) reduceSGRules(rules []ir.SGRule, direction ir.Direction) [ return append(optimizedRulesToSG, optimizedRulesToIPAddrs...) } -func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGRule { - // delete other protocols rules if all protocol rule exists - for _, sgName := range spans.all { - delete(spans.tcp, *sgName) - delete(spans.udp, *sgName) - delete(spans.icmp, *sgName) - } - - // merge tcp, udp and icmp rules into all protocol rule - for sgName, tcpPorts := range spans.tcp { - if udpPorts, ok := spans.udp[sgName]; ok { - if ic, ok := spans.icmp[sgName]; ok { - if ic.Equal(netset.AllICMPSet()) && allPorts(tcpPorts) && allPorts(udpPorts) { // all tcp&udp ports and all icmp types&codes - delete(spans.tcp, sgName) - delete(spans.udp, sgName) - delete(spans.icmp, sgName) - spans.all = append(spans.all, utils.Ptr(sgName)) - } - } - } - } +func reduceSGRulesToSG(spans *sgSpansToSGPerProtocol, direction ir.Direction) []ir.SGRule { + spans = compressSpansToSG(spans) // convert spans to SG rules tcpRules := tcpudpSGSpanToSGRules(spans.tcp, direction, true) @@ -161,7 +143,7 @@ func reduceSGRulesToSG(spans *sgRulesToSGSpans, direction ir.Direction) []ir.SGR return append(tcpRules, append(udpRules, append(icmpRules, allRules...)...)...) } -func reduceSGRulesToIPAddrs(spans *sgRulesToIPAddrsSpans, direction ir.Direction) []ir.SGRule { +func reduceSGRulesToIPAddrs(spans *sgSpansToIPPerProtocol, direction ir.Direction) []ir.SGRule { spans = compressToAllProtocolRule(spans) // spans to SG rules @@ -221,38 +203,6 @@ func divideSGRules(rules []ir.SGRule) *sgRuleGroups { return &sgRuleGroups{rulesToSG: rulesToSG, rulesToIPAddrs: rulesToIPAddrs} } -// observation: It pays to switch to all protocol rule when we have rules that cover all other protocols -// on exactly the same cidr (only one protocol can exceed). -func compressToAllProtocolRule(span *sgRulesToIPAddrsSpans) *sgRulesToIPAddrsSpans { - t := 0 - u := 0 - i := 0 - - for t != len(span.tcp) && u != len(span.udp) && i != len(span.icmp) { - if !allPorts(span.tcp[t].Right) { - t++ - continue - } - if !allPorts(span.udp[u].Right) { - u++ - continue - } - if !span.icmp[i].Right.Equal(netset.AllICMPSet()) { - i++ - continue - } - - if span.tcp[t].Left.Equal(span.udp[u].Left) && span.tcp[t].Left.Equal(span.icmp[i].Left) { - span.all = span.all.Union(span.tcp[t].Left.Copy()) - span.tcp = append(span.tcp[:t], span.tcp[t+1:]...) - span.udp = append(span.udp[:u], span.udp[u+1:]...) - span.icmp = append(span.icmp[:i], span.icmp[i+1:]...) - } - } - - return span -} - func (s *sgRulesPerProtocol) allRules() []ir.SGRule { return append(s.tcp, append(s.udp, append(s.icmp, s.all...)...)...) } diff --git a/pkg/optimize/sgRulesToSpan.go b/pkg/optimize/sgRulesToIPToSpan.go similarity index 64% rename from pkg/optimize/sgRulesToSpan.go rename to pkg/optimize/sgRulesToIPToSpan.go index a9779988..f0fd4541 100644 --- a/pkg/optimize/sgRulesToSpan.go +++ b/pkg/optimize/sgRulesToIPToSpan.go @@ -15,59 +15,16 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) -// Rules with remote SG -func sgRulesToSGToSpans(rules *sgRulesPerProtocol) *sgRulesToSGSpans { - tcpSpan := tcpudpRulesToSGToPortsSpan(rules.tcp) - udpSpan := tcpudpRulesToSGToPortsSpan(rules.udp) - icmpSpan := icmpRulesToSGToSpan(rules.icmp) - allSpan := allProtocolRulesToSGToSpan(rules.all) - return &sgRulesToSGSpans{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} -} - -func tcpudpRulesToSGToPortsSpan(rules []ir.SGRule) map[ir.SGName]*interval.CanonicalSet { - result := make(map[ir.SGName]*interval.CanonicalSet) - for i := range rules { - p := rules[i].Protocol.(netp.TCPUDP) // already checked - remote := rules[i].Remote.(ir.SGName) // already checked - if result[remote] == nil { - result[remote] = interval.NewCanonicalSet() - } - result[remote].AddInterval(p.DstPorts()) - } - return result -} - -func icmpRulesToSGToSpan(rules []ir.SGRule) map[ir.SGName]*netset.ICMPSet { - result := make(map[ir.SGName]*netset.ICMPSet) - for i := range rules { - p := rules[i].Protocol.(netp.ICMP) // already checked - remote := rules[i].Remote.(ir.SGName) // already checked - if result[remote] == nil { - result[remote] = netset.EmptyICMPSet() - } - result[remote].Union(netset.NewICMPSet(p)) - } - return result -} - -func allProtocolRulesToSGToSpan(rules []ir.SGRule) []*ir.SGName { - result := make(map[ir.SGName]struct{}) - for i := range rules { - remote := rules[i].Remote.(ir.SGName) - result[remote] = struct{}{} - } - return utils.ToPtrSlice(utils.SortedMapKeys(result)) -} - -// Rules with IPAddrs remote -func sgRulesToIPAddrsToSpans(rules *sgRulesPerProtocol) *sgRulesToIPAddrsSpans { +// calculate all spans and set them in sgRulesPerProtocol struct +func sgRulesToIPAddrsToSpans(rules *sgRulesPerProtocol) *sgSpansToIPPerProtocol { tcpSpan := tcpudpRulesToIPAddrsToPortsSpan(rules.tcp) udpSpan := tcpudpRulesToIPAddrsToPortsSpan(rules.udp) icmpSpan := icmpRulesToIPAddrsToSpan(rules.icmp) allSpan := allProtocolRulesToIPAddrsToSpan(rules.all) - return &sgRulesToIPAddrsSpans{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} + return &sgSpansToIPPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} } +// all protocol rules to a span. The span will be splitted to disjoint CIDRs func allProtocolRulesToIPAddrsToSpan(rules []ir.SGRule) *netset.IPBlock { res := netset.NewIPBlock() for i := range rules { @@ -76,8 +33,8 @@ func allProtocolRulesToIPAddrsToSpan(rules []ir.SGRule) *netset.IPBlock { return res } -// converts []ir.SGRule (where all rules or either TCP/UDP but not both) to a span of (IPBlock X ports). -// all IPBlocks are disjoint. +// tcp/udp rules (separately) to a span of (IPBlock X protocol ports). +// all IPBlocks are disjoint func tcpudpRulesToIPAddrsToPortsSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { span := tcpudpMapSpan(rules) result := ds.NewProductLeft[*netset.IPBlock, *interval.CanonicalSet]() @@ -88,6 +45,8 @@ func tcpudpRulesToIPAddrsToPortsSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBloc return sortPartitionsByIPAddrs(result.Partitions()) } +// icmp rules to a span of (IPBlock X icmp set). +// all IPBlocks are disjoint func icmpRulesToIPAddrsToSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.ICMPSet] { span := icmpMapSpan((rules)) result := ds.NewProductLeft[*netset.IPBlock, *netset.ICMPSet]() @@ -98,7 +57,12 @@ func icmpRulesToIPAddrsToSpan(rules []ir.SGRule) []ds.Pair[*netset.IPBlock, *net return sortPartitionsByIPAddrs(result.Partitions()) } -// Help functions +/* ######################## */ +/* #### HELP FUNCTIONS #### */ +/* ######################## */ + +// tcp/udp rules to a span in a map format, where the key is the IPBlock and the value contains the protocol ports +// all ipblocks are disjoint func tcpudpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*interval.CanonicalSet { span := make(map[*netset.IPBlock]*interval.CanonicalSet, 0) // all keys are disjoint for i := range rules { @@ -109,6 +73,8 @@ func tcpudpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*interval.CanonicalSet return span } +// icmp rules to a span in a map format, where the key is the IPBlock and the value contains the icmp set +// all ipblocks are disjoint func icmpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*netset.ICMPSet { span := make(map[*netset.IPBlock]*netset.ICMPSet, 0) // all keys are disjoint for i := range rules { @@ -119,6 +85,9 @@ func icmpMapSpan(rules []ir.SGRule) map[*netset.IPBlock]*netset.ICMPSet { return span } +// updateSpan gets the current span, and a rule details (IPBlock and a protocol set) +// if the IPBlock is already in the map, the new protocol set will be unioned with the existing one +// otherwise the rule will be added in the `addRuleToSpan` function. func updateSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleSet T, ruleIP *netset.IPBlock) map[*netset.IPBlock]T { if protocolSet, ok := span[ruleIP]; ok { span[ruleIP] = protocolSet.Union(ruleSet) @@ -128,6 +97,11 @@ func updateSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleSet T, ruleIP *nets return utils.MergeSetMaps(span, newMap) } +// any IPblock that overlaps with the new ipblock: +// 1. will be deleted from the new map +// 2. will be splitted into two parts: the part overlapping with the new ipblock and the part that is not +// a. the overlapping part will enter the new map, where the existing set will be unioned with the new set +// b. the non overlapping part will enter the new map with the same value he had. func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlock, ruleSet T) (s, res map[*netset.IPBlock]T) { res = make(map[*netset.IPBlock]T, 0) for ipblock := range span { diff --git a/pkg/optimize/sgRulesToSGToSpan.go b/pkg/optimize/sgRulesToSGToSpan.go new file mode 100644 index 00000000..364f3d91 --- /dev/null +++ b/pkg/optimize/sgRulesToSGToSpan.go @@ -0,0 +1,62 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import ( + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" +) + +// calculate all spans and set them in sgRulesPerProtocol struct +func sgRulesToSGToSpans(rules *sgRulesPerProtocol) *sgSpansToSGPerProtocol { + tcpSpan := tcpudpRulesToSGToPortsSpan(rules.tcp) + udpSpan := tcpudpRulesToSGToPortsSpan(rules.udp) + icmpSpan := icmpRulesToSGToSpan(rules.icmp) + allSpan := allProtocolRulesToSGToSpan(rules.all) + return &sgSpansToSGPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} +} + +// tcp/udp rules to a span -- map where the key is the SG name and the value is the protocol ports +func tcpudpRulesToSGToPortsSpan(rules []ir.SGRule) map[ir.SGName]*interval.CanonicalSet { + result := make(map[ir.SGName]*interval.CanonicalSet) + for i := range rules { + p := rules[i].Protocol.(netp.TCPUDP) // already checked + remote := rules[i].Remote.(ir.SGName) // already checked + if result[remote] == nil { + result[remote] = interval.NewCanonicalSet() + } + result[remote].AddInterval(p.DstPorts()) + } + return result +} + +// icmp rules to a span -- map where the key is the SG name and the value is icmp set +func icmpRulesToSGToSpan(rules []ir.SGRule) map[ir.SGName]*netset.ICMPSet { + result := make(map[ir.SGName]*netset.ICMPSet) + for i := range rules { + p := rules[i].Protocol.(netp.ICMP) // already checked + remote := rules[i].Remote.(ir.SGName) // already checked + if result[remote] == nil { + result[remote] = netset.EmptyICMPSet() + } + result[remote].Union(netset.NewICMPSet(p)) + } + return result +} + +// all protocol rules to a span of SG names slice +func allProtocolRulesToSGToSpan(rules []ir.SGRule) []*ir.SGName { + result := make(map[ir.SGName]struct{}) + for i := range rules { + remote := rules[i].Remote.(ir.SGName) + result[remote] = struct{}{} + } + return utils.ToPtrSlice(utils.SortedMapKeys(result)) +} diff --git a/pkg/optimize/sgSpanToSGRules.go b/pkg/optimize/sgSpanToSGRules.go new file mode 100644 index 00000000..c60042fd --- /dev/null +++ b/pkg/optimize/sgSpanToSGRules.go @@ -0,0 +1,47 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import ( + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +// span (SGName X ports set) to SG rules +func tcpudpSGSpanToSGRules(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []ir.SGRule { + result := make([]ir.SGRule, 0) + for sgName, intervals := range span { + for _, dstPorts := range intervals.Intervals() { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) + result = append(result, ir.NewSGRule(direction, sgName, p, netset.GetCidrAll(), "")) + } + } + return result +} + +// span (SGName X icmp set) to SG rules +func icmpSGSpanToSGRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction) []ir.SGRule { + result := make([]ir.SGRule, 0) + for sgName, icmpSet := range span { + for _, icmp := range icmpSet.Partitions() { + p, _ := netp.NewICMP(icmp.TypeCode) + result = append(result, ir.NewSGRule(direction, sgName, p, netset.GetCidrAll(), "")) + } + } + return result +} + +// span (slice of SGs) to SG rules +func protocolAllSGSpanToSGRules(span []*ir.SGName, direction ir.Direction) []ir.SGRule { + result := make([]ir.SGRule, len(span)) + for i, sgName := range span { + result[i] = ir.NewSGRule(direction, sgName, netp.AnyProtocol{}, netset.GetCidrAll(), "") + } + return result +} diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index 362ad854..293ee3bd 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -9,6 +9,7 @@ import ( "log" "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) From 67f320be4cf149954fa3794883d93bf3fe6763e6 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 25 Sep 2024 13:35:03 +0300 Subject: [PATCH 44/79] merge --- .../acl_tg_multiple/nacl_single_expected.tf | 243 ------------------ test/data/acl_tg_multiple/single_test-vpc0.tf | 145 ----------- test/data/acl_tg_multiple/single_test-vpc1.tf | 49 ---- test/data/sg_single_conn/sg_expected.csv | 3 - 4 files changed, 440 deletions(-) delete mode 100644 test/data/acl_tg_multiple/nacl_single_expected.tf delete mode 100644 test/data/acl_tg_multiple/single_test-vpc0.tf delete mode 100644 test/data/acl_tg_multiple/single_test-vpc1.tf delete mode 100644 test/data/sg_single_conn/sg_expected.csv diff --git a/test/data/acl_tg_multiple/nacl_single_expected.tf b/test/data/acl_tg_multiple/nacl_single_expected.tf deleted file mode 100644 index 09a80278..00000000 --- a/test/data/acl_tg_multiple/nacl_single_expected.tf +++ /dev/null @@ -1,243 +0,0 @@ -# test-vpc0/singleACL [10.240.0.0/24] -resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { - name = "acl-test-vpc0--singleACL" - resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id - # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" - destination = "10.240.4.0/24" - } - # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" - destination = "10.240.0.0/24" - } - # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" - destination = "10.240.4.0/24" - } - # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" - destination = "10.240.0.0/24" - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule6" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule7" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule8" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" - destination = "10.240.9.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule9" - action = "allow" - direction = "inbound" - source = "10.240.9.0/24" - destination = "10.240.8.0/24" - icmp { - type = 8 - } - } - # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule10" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" - destination = "10.240.9.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule11" - action = "allow" - direction = "outbound" - source = "10.240.9.0/24" - destination = "10.240.8.0/24" - icmp { - type = 8 - } - } - # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections - rules { - name = "rule12" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" - destination = "10.240.1.0/24" - } - # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections - rules { - name = "rule13" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" - destination = "0.0.0.0/0" - } -} - -# test-vpc1/singleACL [10.240.64.0/24] -resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { - name = "acl-test-vpc1--singleACL" - resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id - # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" - destination = "10.240.80.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.80.0/24" - destination = "10.240.64.0/24" - icmp { - type = 8 - } - } - # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" - destination = "10.240.80.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.80.0/24" - destination = "10.240.64.0/24" - icmp { - type = 8 - } - } -} - -# test-vpc2/singleACL [10.240.128.0/24] -resource "ibm_is_network_acl" "acl-test-vpc2--singleACL" { - name = "acl-test-vpc2--singleACL" - resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id - # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections - rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" - destination = "10.240.128.0/24" - } - # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections - rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" - destination = "0.0.0.0/0" - } -} - -# test-vpc3/singleACL [10.240.192.0/24] -resource "ibm_is_network_acl" "acl-test-vpc3--singleACL" { - name = "acl-test-vpc3--singleACL" - resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id - # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections - rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" - destination = "10.240.192.0/24" - } - # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections - rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" - destination = "0.0.0.0/0" - } -} diff --git a/test/data/acl_tg_multiple/single_test-vpc0.tf b/test/data/acl_tg_multiple/single_test-vpc0.tf deleted file mode 100644 index c9ea8d01..00000000 --- a/test/data/acl_tg_multiple/single_test-vpc0.tf +++ /dev/null @@ -1,145 +0,0 @@ -resource "ibm_is_network_acl" "acl-test-vpc0--singleACL" { - name = "acl-test-vpc0--singleACL" - resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id - # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" - destination = "10.240.4.0/24" - } - # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" - destination = "10.240.0.0/24" - } - # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" - destination = "10.240.4.0/24" - } - # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] - rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" - destination = "10.240.0.0/24" - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule6" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] - rules { - name = "rule7" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" - destination = "10.240.5.0/24" - udp { - port_min = 53 - port_max = 53 - } - } - # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule8" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" - destination = "10.240.9.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule9" - action = "allow" - direction = "inbound" - source = "10.240.9.0/24" - destination = "10.240.8.0/24" - icmp { - type = 8 - } - } - # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule10" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" - destination = "10.240.9.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] - rules { - name = "rule11" - action = "allow" - direction = "outbound" - source = "10.240.9.0/24" - destination = "10.240.8.0/24" - icmp { - type = 8 - } - } - # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections - rules { - name = "rule12" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" - destination = "10.240.1.0/24" - } - # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections - rules { - name = "rule13" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" - destination = "0.0.0.0/0" - } -} diff --git a/test/data/acl_tg_multiple/single_test-vpc1.tf b/test/data/acl_tg_multiple/single_test-vpc1.tf deleted file mode 100644 index c8303eee..00000000 --- a/test/data/acl_tg_multiple/single_test-vpc1.tf +++ /dev/null @@ -1,49 +0,0 @@ -resource "ibm_is_network_acl" "acl-test-vpc1--singleACL" { - name = "acl-test-vpc1--singleACL" - resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id - # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" - destination = "10.240.80.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.80.0/24" - destination = "10.240.64.0/24" - icmp { - type = 8 - } - } - # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" - destination = "10.240.80.0/24" - icmp { - type = 0 - } - } - # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] - rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.80.0/24" - destination = "10.240.64.0/24" - icmp { - type = 8 - } - } -} diff --git a/test/data/sg_single_conn/sg_expected.csv b/test/data/sg_single_conn/sg_expected.csv deleted file mode 100644 index 08335ae3..00000000 --- a/test/data/sg_single_conn/sg_expected.csv +++ /dev/null @@ -1,3 +0,0 @@ -SG,Direction,Remote type,Remote,Protocol,Protocol params,Description -test-vpc/be,Inbound,Security group,test-vpc/fe,UDP,ports 53-53,Internal. required-connections[0]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] -test-vpc/fe,Outbound,Security group,test-vpc/be,UDP,ports 53-53,Internal. required-connections[0]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] From 6be5ee02f0971e871b014df71ca4cad819c29a12 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 25 Sep 2024 13:41:58 +0300 Subject: [PATCH 45/79] fixed --- pkg/io/confio/parse_sgs.go | 59 +++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index f97cdb6d..250a7e6e 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -30,21 +30,22 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { if err != nil { return nil, err } - if sg.Name != nil { - vpcName := *sg.VPC.Name - if result.SGs[vpcName] == nil { - result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) - } - result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} + if sg.Name == nil || sg.VPC == nil || sg.VPC.Name == nil { + continue } + vpcName := *sg.VPC.Name + if result.SGs[vpcName] == nil { + result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) + } + result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} } return result, nil } // parse security rules, splitted into ingress and egress rules -func translateSGRules(sg *vpcv1.SecurityGroup) (ingressRules, egressRules []ir.SGRule, err error) { - ingressRules = []ir.SGRule{} - egressRules = []ir.SGRule{} +func translateSGRules(sg *vpcv1.SecurityGroup) (ingressRules, egressRules []*ir.SGRule, err error) { + ingressRules = []*ir.SGRule{} + egressRules = []*ir.SGRule{} for index := range sg.Rules { rule, err := translateSGRule(sg, index) if err != nil { @@ -60,7 +61,7 @@ func translateSGRules(sg *vpcv1.SecurityGroup) (ingressRules, egressRules []ir.S } // translateSGRule translates a security group rule to ir.SGRule -func translateSGRule(sg *vpcv1.SecurityGroup, index int) (sgRule ir.SGRule, err error) { +func translateSGRule(sg *vpcv1.SecurityGroup, index int) (sgRule *ir.SGRule, err error) { switch r := sg.Rules[index].(type) { case *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll: return translateSGRuleProtocolAll(r) @@ -69,63 +70,63 @@ func translateSGRule(sg *vpcv1.SecurityGroup, index int) (sgRule ir.SGRule, err case *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp: return translateSGRuleProtocolIcmp(r) } - return ir.SGRule{}, fmt.Errorf("error parsing rule number %d in %s sg", index, *sg.Name) + return nil, fmt.Errorf("error parsing rule number %d in %s sg", index, *sg.Name) } -func translateSGRuleProtocolAll(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll) (sgRule ir.SGRule, err error) { +func translateSGRuleProtocolAll(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll) (sgRule *ir.SGRule, err error) { direction, err := translateDirection(*rule.Direction) if err != nil { - return ir.SGRule{}, err + return nil, err } remote, err := translateRemote(rule.Remote) if err != nil { - return ir.SGRule{}, err + return nil, err } local, err := translateLocal(rule.Local) if err != nil { - return ir.SGRule{}, err + return nil, err } - return ir.SGRule{Direction: direction, Remote: remote, Protocol: netp.AnyProtocol{}, Local: local}, nil + return &ir.SGRule{Direction: direction, Remote: remote, Protocol: netp.AnyProtocol{}, Local: local}, nil } -func translateSGRuleProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (sgRule ir.SGRule, err error) { +func translateSGRuleProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (sgRule *ir.SGRule, err error) { direction, err := translateDirection(*rule.Direction) if err != nil { - return ir.SGRule{}, err + return nil, err } remote, err := translateRemote(rule.Remote) if err != nil { - return ir.SGRule{}, err + return nil, err } local, err := translateLocal(rule.Local) if err != nil { - return ir.SGRule{}, err + return nil, err } protocol, err := translateProtocolTCPUDP(rule) if err != nil { - return ir.SGRule{}, err + return nil, err } - return ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil + return &ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil } -func translateSGRuleProtocolIcmp(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp) (sgRule ir.SGRule, err error) { +func translateSGRuleProtocolIcmp(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp) (sgRule *ir.SGRule, err error) { direction, err := translateDirection(*rule.Direction) if err != nil { - return ir.SGRule{}, err + return nil, err } remote, err := translateRemote(rule.Remote) if err != nil { - return ir.SGRule{}, err + return nil, err } local, err := translateLocal(rule.Local) if err != nil { - return ir.SGRule{}, err + return nil, err } protocol, err := netp.ICMPFromTypeAndCode64(rule.Type, rule.Code) if err != nil { - return ir.SGRule{}, err + return nil, err } - return ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil + return &ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil } func translateDirection(direction string) (ir.Direction, error) { @@ -169,7 +170,7 @@ func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, er return nil, fmt.Errorf("error parsing Local field") } -// temporary - first version of optimization requires that local value will be 0.0.0.0/32 +// temporary - first version of optimization requires local = 0.0.0.0/32 func verifyLocalValue(ipAddrs *netset.IPBlock) (*netset.IPBlock, error) { if !ipAddrs.Equal(netset.GetCidrAll()) { return nil, fmt.Errorf("only 0.0.0.0/32 CIDR block is supported for local values") From bf9438fd772d6468b9deda511414c38d1717a19b Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 25 Sep 2024 15:40:31 +0300 Subject: [PATCH 46/79] wip --- cmd/subcmds/optimizeOutput.go | 8 ++-- cmd/subcmds/synthOutput.go | 8 ++-- pkg/io/confio/acl.go | 2 +- pkg/io/confio/common.go | 2 +- pkg/io/confio/sg.go | 2 +- pkg/io/csvio/acl.go | 2 +- pkg/io/csvio/common.go | 2 +- pkg/io/csvio/sg.go | 2 +- pkg/io/mdio/acl.go | 2 +- pkg/io/mdio/common.go | 2 +- pkg/io/mdio/sg.go | 2 +- pkg/io/tfio/acl.go | 2 +- pkg/io/tfio/common.go | 2 +- pkg/io/tfio/sg.go | 70 +++++++++++++++-------------------- pkg/ir/acl.go | 16 ++------ pkg/ir/common.go | 19 +++------- pkg/ir/sg.go | 16 ++------ pkg/optimize/common.go | 2 +- pkg/optimize/sg.go | 2 +- pkg/synth/acl.go | 2 +- pkg/synth/common.go | 2 +- pkg/synth/sg.go | 2 +- 22 files changed, 67 insertions(+), 102 deletions(-) diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go index 2b602f1c..eedf753e 100644 --- a/cmd/subcmds/optimizeOutput.go +++ b/cmd/subcmds/optimizeOutput.go @@ -14,7 +14,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func writeOptimizeOutput(args *inArgs, collection ir.OptimizeCollection, vpcNames []string) error { +func writeOptimizeOutput(args *inArgs, collection ir.Collection, vpcNames []string) error { if err := checkOutputFlags(args); err != nil { return err } @@ -29,19 +29,19 @@ func writeOptimizeOutput(args *inArgs, collection ir.OptimizeCollection, vpcName return writeToFile(args.outputFile, data) } -func writeOptimizeCollection(args *inArgs, collection ir.OptimizeCollection) (*bytes.Buffer, error) { +func writeOptimizeCollection(args *inArgs, collection ir.Collection) (*bytes.Buffer, error) { var data bytes.Buffer writer, err := pickOptimizeWriter(args, &data) if err != nil { return nil, err } - if err := collection.WriteOptimize(writer); err != nil { + if err := collection.Write(writer, ""); err != nil { return nil, err } return &data, nil } -func pickOptimizeWriter(args *inArgs, data *bytes.Buffer) (ir.OptimizeWriter, error) { +func pickOptimizeWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: diff --git a/cmd/subcmds/synthOutput.go b/cmd/subcmds/synthOutput.go index 12e0670b..ad70e1a8 100644 --- a/cmd/subcmds/synthOutput.go +++ b/cmd/subcmds/synthOutput.go @@ -21,7 +21,7 @@ import ( const defaultDirectoryPermission = 0o755 -func writeOutput(args *inArgs, collection ir.SynthCollection, vpcNames []ir.ID) error { +func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error { if err := checkOutputFlags(args); err != nil { return err } @@ -61,19 +61,19 @@ func writeOutput(args *inArgs, collection ir.SynthCollection, vpcNames []ir.ID) return nil } -func writeSynthCollection(args *inArgs, collection ir.SynthCollection, vpc string) (*bytes.Buffer, error) { +func writeSynthCollection(args *inArgs, collection ir.Collection, vpc string) (*bytes.Buffer, error) { var data bytes.Buffer writer, err := pickSynthWriter(args, &data) if err != nil { return nil, err } - if err := collection.WriteSynth(writer, vpc); err != nil { + if err := collection.Write(writer, vpc); err != nil { return nil, err } return &data, nil } -func pickSynthWriter(args *inArgs, data *bytes.Buffer) (ir.SynthWriter, error) { +func pickSynthWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: diff --git a/pkg/io/confio/acl.go b/pkg/io/confio/acl.go index b2aa75d8..74ad494c 100644 --- a/pkg/io/confio/acl.go +++ b/pkg/io/confio/acl.go @@ -209,7 +209,7 @@ func subnetRef(subnet *configModel.Subnet) *vpcv1.SubnetReference { } } -func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, _ string) error { +func (w *Writer) WriteACL(collection *ir.ACLCollection, _ string) error { if err := updateACLList(w.model, collection); err != nil { return err } diff --git a/pkg/io/confio/common.go b/pkg/io/confio/common.go index 97aa4274..e3e86f61 100644 --- a/pkg/io/confio/common.go +++ b/pkg/io/confio/common.go @@ -12,7 +12,7 @@ import ( configModel "github.com/np-guard/cloud-resource-collector/pkg/ibm/datamodel" ) -// Writer implements ir.SynthWriter +// Writer implements ir.Writer type Writer struct { w *bufio.Writer model *configModel.ResourcesContainerModel diff --git a/pkg/io/confio/sg.go b/pkg/io/confio/sg.go index 02a30ed7..e4b74be7 100644 --- a/pkg/io/confio/sg.go +++ b/pkg/io/confio/sg.go @@ -258,7 +258,7 @@ func updateSG(model *configModel.ResourcesContainerModel, collection *ir.SGColle return errors.Join(err1, err2) } -func (w *Writer) WriteSynthSG(collection *ir.SGCollection, _ string) error { +func (w *Writer) WriteSG(collection *ir.SGCollection, _ string) error { if err := updateSG(w.model, collection); err != nil { return err } diff --git a/pkg/io/csvio/acl.go b/pkg/io/csvio/acl.go index 0da377ef..0c1f62f4 100644 --- a/pkg/io/csvio/acl.go +++ b/pkg/io/csvio/acl.go @@ -18,7 +18,7 @@ import ( ) // Write prints an entire collection of acls as a single CSV table. -func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, vpc string) error { +func (w *Writer) WriteACL(collection *ir.ACLCollection, vpc string) error { if err := w.w.WriteAll(aclHeader()); err != nil { return err } diff --git a/pkg/io/csvio/common.go b/pkg/io/csvio/common.go index c61e180e..41cd664d 100644 --- a/pkg/io/csvio/common.go +++ b/pkg/io/csvio/common.go @@ -18,7 +18,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// Writer implements ir.SynthWriter +// Writer implements ir.Writer type Writer struct { w *csv.Writer } diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index 67128c51..ed91a1ef 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -16,7 +16,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func (w *Writer) WriteSynthSG(collection *ir.SGCollection, vpc string) error { +func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { if err := w.w.WriteAll(sgHeader()); err != nil { return err } diff --git a/pkg/io/mdio/acl.go b/pkg/io/mdio/acl.go index 0f895366..c75a54a1 100644 --- a/pkg/io/mdio/acl.go +++ b/pkg/io/mdio/acl.go @@ -18,7 +18,7 @@ import ( ) // Write prints an entire collection of acls as a single MD table. -func (w *Writer) WriteSynthACL(collection *ir.ACLCollection, vpc string) error { +func (w *Writer) WriteACL(collection *ir.ACLCollection, vpc string) error { if err := w.writeAll(aclHeader()); err != nil { return err } diff --git a/pkg/io/mdio/common.go b/pkg/io/mdio/common.go index fad3d774..abfb24a8 100644 --- a/pkg/io/mdio/common.go +++ b/pkg/io/mdio/common.go @@ -20,7 +20,7 @@ import ( const leftAlign = " :--- " -// Writer implements ir.SynthWriter +// Writer implements ir.Writer type Writer struct { w *bufio.Writer } diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index 5cf4308d..3277b3fa 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -16,7 +16,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func (w *Writer) WriteSynthSG(collection *ir.SGCollection, vpc string) error { +func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { if err := w.writeAll(sgHeader()); err != nil { return err } diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index 95d77473..3575629a 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -18,7 +18,7 @@ import ( ) // WriteACL prints an entire collection of acls as a sequence of terraform resources. -func (w *Writer) WriteSynthACL(c *ir.ACLCollection, vpc string) error { +func (w *Writer) WriteACL(c *ir.ACLCollection, vpc string) error { collection, err := aclCollection(c, vpc) if err != nil { return err diff --git a/pkg/io/tfio/common.go b/pkg/io/tfio/common.go index 6fd5c8f3..96611c65 100644 --- a/pkg/io/tfio/common.go +++ b/pkg/io/tfio/common.go @@ -20,7 +20,7 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// Writer implements ir.SynthWriter and ir.OptimizeWriter +// Writer implements ir.Writer type Writer struct { w *bufio.Writer } diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 05f8e017..747be97d 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -17,17 +17,9 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func (w *Writer) WriteSynthSG(c *ir.SGCollection, vpc string) error { - return w.writeSGCollection(c, vpc, true) -} - -func (w *Writer) WriteOptimizeSG(c *ir.SGCollection) error { - return w.writeSGCollection(c, "", false) -} - -// writeSGCollection prints an entire collection of Security Groups as a sequence of terraform resources. -func (w *Writer) writeSGCollection(c *ir.SGCollection, vpc string, writeComments bool) error { - collection, err := sgCollection(c, vpc, writeComments) +// WriteSG prints an entire collection of Security Groups as a sequence of terraform resources. +func (w *Writer) WriteSG(c *ir.SGCollection, vpc string) error { + collection, err := sgCollection(c, vpc) if err != nil { return err } @@ -36,7 +28,8 @@ func (w *Writer) writeSGCollection(c *ir.SGCollection, vpc string, writeComments if err != nil { return err } - return w.w.Flush() + err = w.w.Flush() + return err } func value(x interface{}) (string, error) { @@ -67,24 +60,22 @@ func sgProtocol(t netp.Protocol) []tf.Block { return nil } -func sgRule(rule *ir.SGRule, sgName ir.SGName, i int, writeComment bool) (tf.Block, error) { +func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { ruleName := fmt.Sprintf("%s-%v", ir.ChangeScoping(sgName.String()), i) if err := verifyName(ruleName); err != nil { return tf.Block{}, err } - comment := "" - if writeComment { - comment = fmt.Sprintf("# %v", rule.Explanation) - } + group, err1 := value(sgName) remote, err2 := value(rule.Remote) if err := errors.Join(err1, err2); err != nil { return tf.Block{}, err } + return tf.Block{ Name: "resource", - Labels: []string{quote("ibm_is_security_group_rule"), quote(ruleName)}, - Comment: comment, + Labels: []string{quote("ibm_is_security_group_rule"), ir.ChangeScoping(quote(ruleName))}, + Comment: fmt.Sprintf("# %v", rule.Explanation), Arguments: []tf.Argument{ {Name: "group", Value: group}, {Name: "direction", Value: quote(direction(rule.Direction))}, @@ -112,27 +103,26 @@ func sg(sgName, comment string) (tf.Block, error) { }, nil } -func sgCollection(t *ir.SGCollection, vpc string, writeComments bool) (*tf.ConfigFile, error) { - resources := make([]tf.Block, 0) - // for _, sgName := range t.SortedSGNames(vpc) { - // comment := "\n" - // if writeComments { - // comment = fmt.Sprintf("\n### SG attached to %v", sgName) - // } - // sg, err := sg(sgName.String(), comment) - // if err != nil { - // return nil, err - // } - // resources = append(resources, sg) - // rules := sg.AllRules() - // for i, rule := range rules { - // rule, err := sgRule(rule, sgName, i) - // if err != nil { - // return nil, err - // } - // resources = append(resources, rule) - // } - // } +func sgCollection(t *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { + var resources []tf.Block //nolint:prealloc // nontrivial to calculate, and an unlikely performance bottleneck + for _, sgName := range t.SortedSGNames(vpc) { + comment := "" + vpcName := ir.VpcFromScopedResource(string(sgName)) + rules := t.SGs[vpcName][sgName].AllRules() + comment = fmt.Sprintf("\n### SG attached to %v", sgName) + sg, err := sg(sgName.String(), comment) + if err != nil { + return nil, err + } + resources = append(resources, sg) + for i, rule := range rules { + rule, err := sgRule(rule, sgName, i) + if err != nil { + return nil, err + } + resources = append(resources, rule) + } + } return &tf.ConfigFile{ Resources: resources, }, nil diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 81c621be..b8e23d6e 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -38,12 +38,8 @@ type ( ACLs map[ID]map[string]*ACL } - SynthACLWriter interface { - WriteSynthACL(aclColl *ACLCollection, vpc string) error - } - - OptimizeACLWriter interface { - WriteOptimizeACL(aclColl *ACLCollection) error + ACLWriter interface { + WriteACL(aclColl *ACLCollection, vpc string) error } ) @@ -133,12 +129,8 @@ func (c *ACLCollection) VpcNames() []string { return utils.SortedMapKeys(c.ACLs) } -func (c *ACLCollection) WriteSynth(w SynthWriter, vpc string) error { - return w.WriteSynthACL(c, vpc) -} - -func (c *ACLCollection) WriteOptimize(w OptimizeWriter) error { - return w.WriteOptimizeACL(c) +func (c *ACLCollection) Write(w Writer, vpc string) error { + return w.WriteACL(c, vpc) } func (c *ACLCollection) SortedACLSubnets(vpc string) []string { diff --git a/pkg/ir/common.go b/pkg/ir/common.go index 5f9fddd8..b747840f 100644 --- a/pkg/ir/common.go +++ b/pkg/ir/common.go @@ -8,22 +8,13 @@ package ir type ( Direction string - SynthCollection interface { - WriteSynth(writer SynthWriter, vpc string) error + Collection interface { + Write(writer Writer, vpc string) error } - OptimizeCollection interface { - WriteOptimize(writer OptimizeWriter) error - } - - SynthWriter interface { - SynthACLWriter - SynthSGWriter - } - - OptimizeWriter interface { - OptimizeACLWriter - OptimizeSGWriter + Writer interface { + ACLWriter + SGWriter } ) diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 4ad83116..d394e36c 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -54,12 +54,8 @@ type ( SGs map[ID]map[SGName]*SG } - SynthSGWriter interface { - WriteSynthSG(sgColl *SGCollection, vpc string) error - } - - OptimizeSGWriter interface { - WriteOptimizeSG(sgColl *SGCollection) error + SGWriter interface { + WriteSG(sgColl *SGCollection, vpc string) error } ) @@ -122,12 +118,8 @@ func (c *SGCollection) VpcNames() []string { return utils.SortedMapKeys(c.SGs) } -func (c *SGCollection) WriteSynth(w SynthWriter, vpc string) error { - return w.WriteSynthSG(c, vpc) -} - -func (c *SGCollection) WriteOptimize(w OptimizeWriter) error { - return w.WriteOptimizeSG(c) +func (c *SGCollection) Write(w Writer, vpc string) error { + return w.WriteSG(c, vpc) } func (c *SGCollection) SortedSGNames(vpc ID) []SGName { diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index 96ed3b9d..b9ee7306 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -12,7 +12,7 @@ type Optimizer interface { ParseCollection(filename string) error // optimize number of SG/nACL rules - Optimize() (ir.OptimizeCollection, error) + Optimize() (ir.Collection, error) // returns a slice of all vpc names. used to generate locals file VpcNames() []string diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 16828db5..d039544d 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -29,7 +29,7 @@ func (s *SGOptimizer) ParseCollection(filename string) error { return nil } -func (s *SGOptimizer) Optimize() (ir.OptimizeCollection, error) { +func (s *SGOptimizer) Optimize() (ir.Collection, error) { return s.sgCollection, nil } diff --git a/pkg/synth/acl.go b/pkg/synth/acl.go index 8807a865..2b3dff12 100644 --- a/pkg/synth/acl.go +++ b/pkg/synth/acl.go @@ -27,7 +27,7 @@ func NewACLSynthesizer(s *ir.Spec, single bool) Synthesizer { return &ACLSynthesizer{spec: s, singleACL: single, result: ir.NewACLCollection()} } -func (a *ACLSynthesizer) Synth() (ir.SynthCollection, error) { +func (a *ACLSynthesizer) Synth() (ir.Collection, error) { return a.makeACL() } diff --git a/pkg/synth/common.go b/pkg/synth/common.go index d29100ca..e6e516f3 100644 --- a/pkg/synth/common.go +++ b/pkg/synth/common.go @@ -15,7 +15,7 @@ import ( type ( Synthesizer interface { - Synth() (ir.SynthCollection, error) + Synth() (ir.Collection, error) } namedAddrs struct { diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index e9947d23..70c2433a 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -25,7 +25,7 @@ func NewSGSynthesizer(s *ir.Spec, _ bool) Synthesizer { return &SGSynthesizer{spec: s, result: ir.NewSGCollection()} } -func (s *SGSynthesizer) Synth() (ir.SynthCollection, error) { +func (s *SGSynthesizer) Synth() (ir.Collection, error) { return s.makeSG() } From e3d4668fa06a388f953dbe692ce23d5fdcb4ba12 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 25 Sep 2024 15:58:35 +0300 Subject: [PATCH 47/79] wip --- pkg/io/tfio/acl.go | 4 ---- pkg/ir/acl.go | 7 +++---- pkg/ir/sg.go | 7 +++---- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index 3575629a..b7f3df42 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -32,10 +32,6 @@ func (w *Writer) WriteACL(c *ir.ACLCollection, vpc string) error { return err } -func (w *Writer) WriteOptimizeACL(c *ir.ACLCollection) error { - return fmt.Errorf("OptimizeACL is not supported yet") -} - func aclProtocol(t netp.Protocol) []tf.Block { switch p := t.(type) { case netp.TCPUDP: diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index b8e23d6e..e2f60cf6 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -29,7 +29,6 @@ type ( ACL struct { Subnet string - VpcName string Internal []ACLRule External []ACLRule } @@ -108,8 +107,8 @@ func NewACLCollection() *ACLCollection { return &ACLCollection{ACLs: map[ID]map[string]*ACL{}} } -func NewACL(subnet, vpcName string) *ACL { - return &ACL{Subnet: subnet, VpcName: vpcName, Internal: []ACLRule{}, External: []ACLRule{}} +func NewACL(subnet string) *ACL { + return &ACL{Subnet: subnet, Internal: []ACLRule{}, External: []ACLRule{}} } func (c *ACLCollection) LookupOrCreate(subnet string) *ACL { @@ -117,7 +116,7 @@ func (c *ACLCollection) LookupOrCreate(subnet string) *ACL { if acl, ok := c.ACLs[vpcName][subnet]; ok { return acl } - newACL := NewACL(subnet, vpcName) + newACL := NewACL(subnet) if c.ACLs[vpcName] == nil { c.ACLs[vpcName] = make(map[string]*ACL) } diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index d394e36c..2317a4ec 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -44,7 +44,6 @@ type ( SG struct { SGName SGName - VpcName string InboundRules []*SGRule OutboundRules []*SGRule Attached []ID @@ -80,8 +79,8 @@ func (r *SGRule) mustSupersede(other *SGRule) bool { return res } -func NewSG(vpcName string, sgName SGName) *SG { - return &SG{SGName: sgName, VpcName: vpcName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Attached: []ID{}} +func NewSG(sgName SGName) *SG { + return &SG{SGName: sgName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Attached: []ID{}} } func NewSGCollection() *SGCollection { @@ -93,7 +92,7 @@ func (c *SGCollection) LookupOrCreate(name SGName) *SG { if sg, ok := c.SGs[vpcName][name]; ok { return sg } - newSG := NewSG(vpcName, name) + newSG := NewSG(name) if c.SGs[vpcName] == nil { c.SGs[vpcName] = make(map[SGName]*SG) } From ebb4b3b48278eda39866976f0d3166177ed663c8 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 25 Sep 2024 16:22:05 +0300 Subject: [PATCH 48/79] wip --- pkg/io/confio/parse_sgs.go | 2 +- pkg/io/tfio/acl.go | 8 +++++++- pkg/io/tfio/sg.go | 21 ++++++++++++++++++++- pkg/ir/acl.go | 7 ++++--- pkg/ir/sg.go | 7 ++++--- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index 250a7e6e..1fff790b 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -37,7 +37,7 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { if result.SGs[vpcName] == nil { result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) } - result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} + result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{VpcName: vpcName, InboundRules: inbound, OutboundRules: outbound} } return result, nil } diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index b7f3df42..401aef06 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -64,8 +64,14 @@ func aclRule(rule *ir.ACLRule, name string) (tf.Block, error) { {Name: "source", Value: quote(rule.Source.String())}, {Name: "destination", Value: quote(rule.Destination.String())}, } + + comment := "" + if rule.Explanation != "" { + comment = fmt.Sprintf("# %v", rule.Explanation) + } + return tf.Block{Name: "rules", - Comment: fmt.Sprintf("# %v", rule.Explanation), + Comment: comment, Arguments: arguments, Blocks: aclProtocol(rule.Protocol), }, nil diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 747be97d..c4dadcb7 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -72,10 +72,15 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { return tf.Block{}, err } + comment := "" + if rule.Explanation != "" { + comment = fmt.Sprintf("# %v", rule.Explanation) + } + return tf.Block{ Name: "resource", Labels: []string{quote("ibm_is_security_group_rule"), ir.ChangeScoping(quote(ruleName))}, - Comment: fmt.Sprintf("# %v", rule.Explanation), + Comment: comment, Arguments: []tf.Argument{ {Name: "group", Value: group}, {Name: "direction", Value: quote(direction(rule.Direction))}, @@ -105,6 +110,20 @@ func sg(sgName, comment string) (tf.Block, error) { func sgCollection(t *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { var resources []tf.Block //nolint:prealloc // nontrivial to calculate, and an unlikely performance bottleneck + + for _, vpcName := range t.VpcNames() { + if vpc != vpcName && vpc != "" { + continue + } + for _, sgName := range t.SortedSGNames(vpcName) { + rules := t.SGs[vpcName][sgName].AllRules() + comment := fmt.Sprintf("\n### SG attached to %s", sgName) + } + if vpc == "" { + break + } + } + for _, sgName := range t.SortedSGNames(vpc) { comment := "" vpcName := ir.VpcFromScopedResource(string(sgName)) diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index e2f60cf6..b8e23d6e 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -29,6 +29,7 @@ type ( ACL struct { Subnet string + VpcName string Internal []ACLRule External []ACLRule } @@ -107,8 +108,8 @@ func NewACLCollection() *ACLCollection { return &ACLCollection{ACLs: map[ID]map[string]*ACL{}} } -func NewACL(subnet string) *ACL { - return &ACL{Subnet: subnet, Internal: []ACLRule{}, External: []ACLRule{}} +func NewACL(subnet, vpcName string) *ACL { + return &ACL{Subnet: subnet, VpcName: vpcName, Internal: []ACLRule{}, External: []ACLRule{}} } func (c *ACLCollection) LookupOrCreate(subnet string) *ACL { @@ -116,7 +117,7 @@ func (c *ACLCollection) LookupOrCreate(subnet string) *ACL { if acl, ok := c.ACLs[vpcName][subnet]; ok { return acl } - newACL := NewACL(subnet) + newACL := NewACL(subnet, vpcName) if c.ACLs[vpcName] == nil { c.ACLs[vpcName] = make(map[string]*ACL) } diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 2317a4ec..1245fcae 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -44,6 +44,7 @@ type ( SG struct { SGName SGName + VpcName string InboundRules []*SGRule OutboundRules []*SGRule Attached []ID @@ -79,8 +80,8 @@ func (r *SGRule) mustSupersede(other *SGRule) bool { return res } -func NewSG(sgName SGName) *SG { - return &SG{SGName: sgName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Attached: []ID{}} +func NewSG(sgName SGName, vpcName string) *SG { + return &SG{SGName: sgName, VpcName: vpcName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Attached: []ID{}} } func NewSGCollection() *SGCollection { @@ -92,7 +93,7 @@ func (c *SGCollection) LookupOrCreate(name SGName) *SG { if sg, ok := c.SGs[vpcName][name]; ok { return sg } - newSG := NewSG(name) + newSG := NewSG(name, vpcName) if c.SGs[vpcName] == nil { c.SGs[vpcName] = make(map[SGName]*SG) } From f34b9b7fd411ccdad95349ff39bc5039be9e5af1 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 25 Sep 2024 17:06:48 +0300 Subject: [PATCH 49/79] fixed --- pkg/io/tfio/sg.go | 46 +++++++++++++++++++--------------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index c4dadcb7..88389dc0 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -90,18 +90,21 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { }, nil } -func sg(sgName, comment string) (tf.Block, error) { - vpcName := ir.VpcFromScopedResource(sgName) - sgName = ir.ChangeScoping(sgName) - if err := verifyName(sgName); err != nil { +func sg(sgName, vpcName string) (tf.Block, error) { + tfSGName := ir.ChangeScoping(sgName) + comment := fmt.Sprintf("\n### SG attached to %s", sgName) + if sgName == tfSGName { // its optimization + comment = "" + } + if err := verifyName(tfSGName); err != nil { return tf.Block{}, err } return tf.Block{ Name: "resource", //nolint:revive // obvious false positive - Labels: []string{quote("ibm_is_security_group"), ir.ChangeScoping(quote(sgName))}, + Labels: []string{quote("ibm_is_security_group"), quote(tfSGName)}, Comment: comment, Arguments: []tf.Argument{ - {Name: "name", Value: quote("sg-" + sgName)}, + {Name: "name", Value: quote("sg-" + tfSGName)}, {Name: "resource_group", Value: "local.sg_synth_resource_group_id"}, {Name: "vpc", Value: fmt.Sprintf("local.sg_synth_%s_id", vpcName)}, }, @@ -109,7 +112,7 @@ func sg(sgName, comment string) (tf.Block, error) { } func sgCollection(t *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { - var resources []tf.Block //nolint:prealloc // nontrivial to calculate, and an unlikely performance bottleneck + var resources []tf.Block for _, vpcName := range t.VpcNames() { if vpc != vpcName && vpc != "" { @@ -117,29 +120,18 @@ func sgCollection(t *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { } for _, sgName := range t.SortedSGNames(vpcName) { rules := t.SGs[vpcName][sgName].AllRules() - comment := fmt.Sprintf("\n### SG attached to %s", sgName) - } - if vpc == "" { - break - } - } - - for _, sgName := range t.SortedSGNames(vpc) { - comment := "" - vpcName := ir.VpcFromScopedResource(string(sgName)) - rules := t.SGs[vpcName][sgName].AllRules() - comment = fmt.Sprintf("\n### SG attached to %v", sgName) - sg, err := sg(sgName.String(), comment) - if err != nil { - return nil, err - } - resources = append(resources, sg) - for i, rule := range rules { - rule, err := sgRule(rule, sgName, i) + sg, err := sg(sgName.String(), vpcName) if err != nil { return nil, err } - resources = append(resources, rule) + resources = append(resources, sg) + for i, rule := range rules { + rule, err := sgRule(rule, sgName, i) + if err != nil { + return nil, err + } + resources = append(resources, rule) + } } } return &tf.ConfigFile{ From ca64cee72f46f0ddf99d6d265265b9e729fb43ab Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 30 Sep 2024 11:01:02 +0300 Subject: [PATCH 50/79] avoid code dup --- cmd/subcmds/optimize.go | 2 +- cmd/subcmds/optimizeOutput.go | 52 ------------------- cmd/subcmds/optimizeSG.go | 3 ++ cmd/subcmds/{synthOutput.go => output.go} | 56 +++++++++++++++----- cmd/subcmds/outputCommon.go | 63 ----------------------- cmd/subcmds/outputFormat.go | 6 +-- cmd/subcmds/synth.go | 2 +- cmd/subcmds/synthACL.go | 3 ++ cmd/subcmds/synthSG.go | 3 ++ cmd/subcmds/verifyFlags.go | 24 +++++++++ 10 files changed, 80 insertions(+), 134 deletions(-) delete mode 100644 cmd/subcmds/optimizeOutput.go rename cmd/subcmds/{synthOutput.go => output.go} (57%) delete mode 100644 cmd/subcmds/outputCommon.go create mode 100644 cmd/subcmds/verifyFlags.go diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index c3ea273c..483d3705 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -41,5 +41,5 @@ func optimization(cmd *cobra.Command, args *inArgs, newOptimizer optimize.Optimi if err != nil { return err } - return writeOptimizeOutput(args, collection, newOptimizer.VpcNames()) + return writeOutput(args, collection, newOptimizer.VpcNames(), false) } diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go deleted file mode 100644 index eedf753e..00000000 --- a/cmd/subcmds/optimizeOutput.go +++ /dev/null @@ -1,52 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package subcmds - -import ( - "bufio" - "bytes" - "fmt" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio" - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -) - -func writeOptimizeOutput(args *inArgs, collection ir.Collection, vpcNames []string) error { - if err := checkOutputFlags(args); err != nil { - return err - } - _, isACLCollection := collection.(*ir.ACLCollection) - if err := writeLocals(args, vpcNames, isACLCollection); err != nil { - return err - } - data, err := writeOptimizeCollection(args, collection) - if err != nil { - return err - } - return writeToFile(args.outputFile, data) -} - -func writeOptimizeCollection(args *inArgs, collection ir.Collection) (*bytes.Buffer, error) { - var data bytes.Buffer - writer, err := pickOptimizeWriter(args, &data) - if err != nil { - return nil, err - } - if err := collection.Write(writer, ""); err != nil { - return nil, err - } - return &data, nil -} - -func pickOptimizeWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { - w := bufio.NewWriter(data) - switch args.outputFmt { - case tfOutputFormat: - return tfio.NewWriter(w), nil - default: - return nil, fmt.Errorf("bad output format: %q", args.outputFmt) - } -} diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index 6a07c367..7311dd55 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -18,6 +18,9 @@ func NewOptimizeSGCommand(args *inArgs) *cobra.Command { Long: `OptimizeSG attempts to reduce the number of security group rules in a SG without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { + if err := validateFlags(args); err != nil { + return err + } return optimization(cmd, args, optimize.NewSGOptimizer(args.firewallName)) }, } diff --git a/cmd/subcmds/synthOutput.go b/cmd/subcmds/output.go similarity index 57% rename from cmd/subcmds/synthOutput.go rename to cmd/subcmds/output.go index ad70e1a8..9def6e87 100644 --- a/cmd/subcmds/synthOutput.go +++ b/cmd/subcmds/output.go @@ -10,21 +10,19 @@ import ( "bytes" "fmt" "os" + "path/filepath" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/csvio" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/mdio" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio" - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) +const defaultFilePermission = 0o644 const defaultDirectoryPermission = 0o755 -func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error { - if err := checkOutputFlags(args); err != nil { - return err - } +func writeOutput(args *inArgs, collection ir.Collection, vpcNames []string, isSynth bool) error { if args.outputDir != "" { // create the directory if needed if err := os.MkdirAll(args.outputDir, defaultDirectoryPermission); err != nil { return err @@ -38,7 +36,7 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error var data *bytes.Buffer var err error if args.outputDir == "" { - if data, err = writeSynthCollection(args, collection, ""); err != nil { + if data, err = writeCollection(args, collection, "", isSynth); err != nil { return err } return writeToFile(args.outputFile, data) @@ -51,7 +49,7 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error if args.prefix != "" { args.outputFile = args.outputDir + "/" + args.prefix + "_" + suffix } - if data, err = writeSynthCollection(args, collection, vpc); err != nil { + if data, err = writeCollection(args, collection, vpc, isSynth); err != nil { return err } if err := writeToFile(args.outputFile, data); err != nil { @@ -61,9 +59,9 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error return nil } -func writeSynthCollection(args *inArgs, collection ir.Collection, vpc string) (*bytes.Buffer, error) { +func writeCollection(args *inArgs, collection ir.Collection, vpc string, isSynth bool) (*bytes.Buffer, error) { var data bytes.Buffer - writer, err := pickSynthWriter(args, &data) + writer, err := pickWriter(args, &data, isSynth) if err != nil { return nil, err } @@ -73,7 +71,7 @@ func writeSynthCollection(args *inArgs, collection ir.Collection, vpc string) (* return &data, nil } -func pickSynthWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { +func pickWriter(args *inArgs, data *bytes.Buffer, isSynth bool) (ir.Writer, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: @@ -82,9 +80,39 @@ func pickSynthWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { return csvio.NewWriter(w), nil case mdOutputFormat: return mdio.NewWriter(w), nil - case apiOutputFormat: - return confio.NewWriter(w, args.configFile) - default: - return nil, fmt.Errorf("bad output format: %q", args.outputFmt) + case jsonOutputFormat: + if isSynth { + return confio.NewWriter(w, args.configFile) + } + } + return nil, fmt.Errorf("bad output format: %q", args.outputFmt) +} + +func writeToFile(outputFile string, data *bytes.Buffer) error { + if outputFile == "" { + fmt.Println(data.String()) + return nil + } + return os.WriteFile(outputFile, data.Bytes(), defaultFilePermission) +} + +func writeLocals(args *inArgs, vpcNames []ir.ID, isACL bool) error { + if !args.locals { + return nil + } + + var data *bytes.Buffer + var err error + if data, err = tfio.WriteLocals(vpcNames, isACL); err != nil { + return err + } + + outputFile := "" + suffix := "/locals.tf" + if args.outputDir != "" { + outputFile = args.outputDir + suffix + } else if args.outputFile != "" { + outputFile = filepath.Dir(args.outputFile) + suffix } + return writeToFile(outputFile, data) } diff --git a/cmd/subcmds/outputCommon.go b/cmd/subcmds/outputCommon.go deleted file mode 100644 index aa399315..00000000 --- a/cmd/subcmds/outputCommon.go +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package subcmds - -import ( - "bytes" - "fmt" - "os" - "path/filepath" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio" - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -) - -const defaultFilePermission = 0o644 - -func checkOutputFlags(args *inArgs) error { - if args.outputDir != "" && args.outputFile != "" { - return fmt.Errorf("only one of -d and -o can be supplied") - } - if err := updateOutputFormat(args); err != nil { - return err - } - if args.outputDir != "" && args.outputFmt == apiOutputFormat { - return fmt.Errorf("-d cannot be used with format json") - } - return nil -} - -func writeToFile(outputFile string, data *bytes.Buffer) error { - if outputFile == "" { - fmt.Println(data.String()) - return nil - } - return os.WriteFile(outputFile, data.Bytes(), defaultFilePermission) -} - -func writeLocals(args *inArgs, vpcNames []ir.ID, isACL bool) error { - if !args.locals { - return nil - } - if args.outputFmt != tfOutputFormat { - return fmt.Errorf("--locals flag requires setting the output format to tf") - } - - var data *bytes.Buffer - var err error - if data, err = tfio.WriteLocals(vpcNames, isACL); err != nil { - return err - } - - outputFile := "" - suffix := "/locals.tf" - if args.outputDir != "" { - outputFile = args.outputDir + suffix - } else if args.outputFile != "" { - outputFile = filepath.Dir(args.outputFile) + suffix - } - return writeToFile(outputFile, data) -} diff --git a/cmd/subcmds/outputFormat.go b/cmd/subcmds/outputFormat.go index 51a36c60..f435c43a 100644 --- a/cmd/subcmds/outputFormat.go +++ b/cmd/subcmds/outputFormat.go @@ -14,11 +14,11 @@ const ( tfOutputFormat = "tf" csvOutputFormat = "csv" mdOutputFormat = "md" - apiOutputFormat = "json" + jsonOutputFormat = "json" defaultOutputFormat = csvOutputFormat ) -var outputFormats = []string{tfOutputFormat, csvOutputFormat, mdOutputFormat, apiOutputFormat} +var outputFormats = []string{tfOutputFormat, csvOutputFormat, mdOutputFormat, jsonOutputFormat} func updateOutputFormat(args *inArgs) error { var err error @@ -40,7 +40,7 @@ func inferFormatUsingFilename(filename string) (string, error) { case strings.HasSuffix(filename, ".md"): return mdOutputFormat, nil case strings.HasSuffix(filename, ".json"): - return apiOutputFormat, nil + return jsonOutputFormat, nil default: return "", fmt.Errorf("bad output format") } diff --git a/cmd/subcmds/synth.go b/cmd/subcmds/synth.go index fab5ee4b..91b8250b 100644 --- a/cmd/subcmds/synth.go +++ b/cmd/subcmds/synth.go @@ -48,5 +48,5 @@ func synthesis(cmd *cobra.Command, args *inArgs, newSynthesizer func(*ir.Spec, b if err != nil { return err } - return writeOutput(args, collection, utils.MapKeys(spec.Defs.ConfigDefs.VPCs)) + return writeOutput(args, collection, utils.MapKeys(spec.Defs.ConfigDefs.VPCs), true) } diff --git a/cmd/subcmds/synthACL.go b/cmd/subcmds/synthACL.go index 4aee4040..96c6aea3 100644 --- a/cmd/subcmds/synthACL.go +++ b/cmd/subcmds/synthACL.go @@ -19,6 +19,9 @@ func NewSynthACLCommand(args *inArgs) *cobra.Command { Endpoints in the required-connectivity specification may be subnets, subnet segments, CIDR segments and externals.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { + if err := validateFlags(args); err != nil { + return err + } return synthesis(cmd, args, synth.NewACLSynthesizer, args.singleacl) }, } diff --git a/cmd/subcmds/synthSG.go b/cmd/subcmds/synthSG.go index 88bb4a56..215324ca 100644 --- a/cmd/subcmds/synthSG.go +++ b/cmd/subcmds/synthSG.go @@ -19,6 +19,9 @@ func NewSynthSGCommand(args *inArgs) *cobra.Command { Endpoints in the required-connectivity specification may be Instances (VSIs), Network Interfaces, VPEs and externals.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { + if err := validateFlags(args); err != nil { + return err + } return synthesis(cmd, args, synth.NewSGSynthesizer, false) }, } diff --git a/cmd/subcmds/verifyFlags.go b/cmd/subcmds/verifyFlags.go new file mode 100644 index 00000000..b794732a --- /dev/null +++ b/cmd/subcmds/verifyFlags.go @@ -0,0 +1,24 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package subcmds + +import "fmt" + +func validateFlags(args *inArgs) error { + if args.outputDir != "" && args.outputFile != "" { + return fmt.Errorf("only one of -d and -o can be supplied") + } + if err := updateOutputFormat(args); err != nil { + return err + } + if args.outputDir != "" && args.outputFmt == jsonOutputFormat { + return fmt.Errorf("-d cannot be used with format json") + } + if args.locals && args.outputFmt != tfOutputFormat { + return fmt.Errorf("--locals flag requires setting the output format to tf") + } + return nil +} From 49f4a474856d97a26d8e292c90b1ab56a0aa483c Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 30 Sep 2024 11:05:10 +0300 Subject: [PATCH 51/79] fixed --- cmd/subcmds/optimize.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index 483d3705..c346e15b 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -23,9 +23,6 @@ func NewOptimizeCommand(args *inArgs) *cobra.Command { // flags cmd.PersistentFlags().StringVarP(&args.firewallName, firewallNameFlag, "n", "", "which vpcFirewall to optimize") - // flags settings - _ = cmd.MarkPersistentFlagRequired(firewallNameFlag) // temporary - // sub cmds cmd.AddCommand(NewOptimizeSGCommand(args)) From 766f737583eb1974e907e66c9401e9a91666fb77 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 30 Sep 2024 11:14:52 +0300 Subject: [PATCH 52/79] fix output fmts --- pkg/io/csvio/sg.go | 18 +++++++++++------- pkg/io/mdio/sg.go | 18 +++++++++++------- pkg/io/tfio/sg.go | 8 ++++---- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index ed91a1ef..35c74f8b 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -20,14 +20,18 @@ func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { if err := w.w.WriteAll(sgHeader()); err != nil { return err } - for _, sgName := range collection.SortedSGNames(vpc) { - vpcName := ir.VpcFromScopedResource(string(sgName)) - sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) - if err != nil { - return err + for _, vpcName := range collection.VpcNames() { + if vpc != vpcName && vpc != "" { + continue } - if err := w.w.WriteAll(sgTable); err != nil { - return err + for _, sgName := range collection.SortedSGNames(vpcName) { + sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) + if err != nil { + return err + } + if err := w.w.WriteAll(sgTable); err != nil { + return err + } } } return nil diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index 3277b3fa..0fcbf734 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -20,14 +20,18 @@ func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { if err := w.writeAll(sgHeader()); err != nil { return err } - for _, sgName := range collection.SortedSGNames(vpc) { - vpcName := ir.VpcFromScopedResource(string(sgName)) - sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) - if err != nil { - return err + for _, vpcName := range collection.VpcNames() { + if vpc != vpcName && vpc != "" { + continue } - if err := w.writeAll(sgTable); err != nil { - return err + for _, sgName := range collection.SortedSGNames(vpcName) { + sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) + if err != nil { + return err + } + if err := w.writeAll(sgTable); err != nil { + return err + } } } return nil diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 88389dc0..793c5c7a 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -111,15 +111,15 @@ func sg(sgName, vpcName string) (tf.Block, error) { }, nil } -func sgCollection(t *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { +func sgCollection(collection *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { var resources []tf.Block - for _, vpcName := range t.VpcNames() { + for _, vpcName := range collection.VpcNames() { if vpc != vpcName && vpc != "" { continue } - for _, sgName := range t.SortedSGNames(vpcName) { - rules := t.SGs[vpcName][sgName].AllRules() + for _, sgName := range collection.SortedSGNames(vpcName) { + rules := collection.SGs[vpcName][sgName].AllRules() sg, err := sg(sgName.String(), vpcName) if err != nil { return nil, err From e6bb1b3c5df15bc26291e4b56c91c7dea3848c43 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 30 Sep 2024 11:44:54 +0300 Subject: [PATCH 53/79] tests template --- .../{synth_test_list.go => main_test_list.go} | 7 +++++- test/tests_defs.go | 24 +++++++++++-------- 2 files changed, 20 insertions(+), 11 deletions(-) rename test/{synth_test_list.go => main_test_list.go} (96%) diff --git a/test/synth_test_list.go b/test/main_test_list.go similarity index 96% rename from test/synth_test_list.go rename to test/main_test_list.go index d8e37147..57e61c77 100644 --- a/test/synth_test_list.go +++ b/test/main_test_list.go @@ -37,7 +37,7 @@ const ( ) func allMainTests() []testCase { - return append(synthACLTestsList(), synthSGTestsList()...) + return append(synthACLTestsList(), append(synthSGTestsList(), optimizeSGTestsLists()...)...) } //nolint:funlen //all acl synthesis tests @@ -310,3 +310,8 @@ func synthSGTestsList() []testCase { }, } } + +// Note: spec files in data folder are used to create the config object files (acl_testing4 config) +func optimizeSGTestsLists() []testCase { + return []testCase{} +} diff --git a/test/tests_defs.go b/test/tests_defs.go index 08668069..e5a32ebd 100644 --- a/test/tests_defs.go +++ b/test/tests_defs.go @@ -14,16 +14,17 @@ type testCase struct { } type command struct { - cmd string - subcmd string - singleacl bool - config string - spec string - outputFile string - outputDir string - prefix string - format string - locals bool + cmd string + subcmd string + singleacl bool + config string + spec string + outputFile string + outputDir string + prefix string + format string + locals bool + firewallName string } const ( @@ -72,6 +73,9 @@ func (c *command) Args(dataFolder, resultsFolder string) []string { if c.locals { res = append(res, "-l") } + if c.firewallName != "" { + res = append(res, "-n", c.firewallName) + } return res } From 34410edc6a2e4b8407d306a20ebc1eaae97ae969 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 30 Sep 2024 13:32:47 +0300 Subject: [PATCH 54/79] tests data --- .../optimize_sg_icmp_codes/config_object.json | 2169 ++++++++++++++ .../optimize_sg_icmp_codes/conn_spec.json | 143 + test/data/optimize_sg_icmp_codes/details.txt | 14 + .../optimize_sg_icmp_types/config_object.json | 2493 +++++++++++++++++ .../optimize_sg_icmp_types/conn_spec.json | 359 +++ test/data/optimize_sg_icmp_types/details.txt | 28 + .../config_object.json | 2214 +++++++++++++++ .../conn_spec.json | 169 ++ .../optimize_sg_protocols_to_all/details.txt | 16 + .../optimize_sg_redundant/config_object.json | 2023 +++++++++++++ .../data/optimize_sg_redundant/conn_spec.json | 48 + test/data/optimize_sg_redundant/details.txt | 10 + test/data/optimize_sg_t/config_object.json | 2009 +++++++++++++ test/data/optimize_sg_t/conn_spec.json | 60 + test/data/optimize_sg_t/details.txt | 8 + .../data/optimize_sg_t_all/config_object.json | 2007 +++++++++++++ test/data/optimize_sg_t_all/conn_spec.json | 53 + test/data/optimize_sg_t_all/details.txt | 8 + test/main_test_list.go | 89 +- test/tests_defs.go | 7 +- 20 files changed, 13922 insertions(+), 5 deletions(-) create mode 100644 test/data/optimize_sg_icmp_codes/config_object.json create mode 100644 test/data/optimize_sg_icmp_codes/conn_spec.json create mode 100644 test/data/optimize_sg_icmp_codes/details.txt create mode 100644 test/data/optimize_sg_icmp_types/config_object.json create mode 100644 test/data/optimize_sg_icmp_types/conn_spec.json create mode 100644 test/data/optimize_sg_icmp_types/details.txt create mode 100644 test/data/optimize_sg_protocols_to_all/config_object.json create mode 100644 test/data/optimize_sg_protocols_to_all/conn_spec.json create mode 100644 test/data/optimize_sg_protocols_to_all/details.txt create mode 100644 test/data/optimize_sg_redundant/config_object.json create mode 100644 test/data/optimize_sg_redundant/conn_spec.json create mode 100644 test/data/optimize_sg_redundant/details.txt create mode 100644 test/data/optimize_sg_t/config_object.json create mode 100644 test/data/optimize_sg_t/conn_spec.json create mode 100644 test/data/optimize_sg_t/details.txt create mode 100644 test/data/optimize_sg_t_all/config_object.json create mode 100644 test/data/optimize_sg_t_all/conn_spec.json create mode 100644 test/data/optimize_sg_t_all/details.txt diff --git a/test/data/optimize_sg_icmp_codes/config_object.json b/test/data/optimize_sg_icmp_codes/config_object.json new file mode 100644 index 00000000..d059fc05 --- /dev/null +++ b/test/data/optimize_sg_icmp_codes/config_object.json @@ -0,0 +1,2169 @@ +{ + "collector_version": "0.11.0", + "provider": "ibm", + "vpcs": [ + { + "classic_access": false, + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:1", + "cse_source_ips": [ + { + "ip": { + "address": "10.22.217.112" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "ip": { + "address": "10.12.160.153" + }, + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "ip": { + "address": "10.16.253.223" + }, + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "default_network_acl": { + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail" + }, + "default_routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "default_security_group": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "dns": { + "enable_hub": false, + "resolution_binding_count": 0, + "resolver": { + "servers": [ + { + "address": "161.26.0.10" + }, + { + "address": "161.26.0.11" + } + ], + "type": "system", + "configuration": "default" + } + }, + "health_reasons": null, + "health_state": "ok", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "vpc", + "status": "available", + "region": "us-south", + "address_prefixes": [ + { + "cidr": "10.240.0.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": true, + "href": "href:18", + "id": "id:19", + "is_default": true, + "name": "filling-tasty-bacterium-parlor", + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "cidr": "10.240.64.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:20", + "id": "id:21", + "is_default": true, + "name": "relearn-ragweed-goon-feisty", + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "cidr": "10.240.128.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:22", + "id": "id:23", + "is_default": true, + "name": "unruffled-penknife-snowshoe-ninetieth", + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "tags": [] + } + ], + "subnets": [ + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:51.000Z", + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.20.0/24", + "name": "subnet2", + "network_acl": { + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.20.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:33", + "id": "id:34", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:35", + "id": "id:36", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:37", + "id": "id:38", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:39", + "id": "id:40", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.4", + "auto_delete": true, + "created_at": "2024-09-09T09:11:08.000Z", + "href": "href:41", + "id": "id:42", + "lifecycle_state": "stable", + "name": "startle-percent-embellish-squeegee", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.20.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:45", + "id": "id:46", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.10.0/24", + "name": "subnet1", + "network_acl": { + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.10.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:53", + "id": "id:54", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:55", + "id": "id:56", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:57", + "id": "id:58", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:59", + "id": "id:60", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:52.000Z", + "href": "href:61", + "id": "id:62", + "lifecycle_state": "stable", + "name": "tableware-sprawl-shrivel-popper", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.10.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:65", + "id": "id:66", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 249, + "created_at": "2024-09-09T09:10:18.000Z", + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.30.0/24", + "name": "subnet3", + "network_acl": { + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.30.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:73", + "id": "id:74", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:75", + "id": "id:76", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:77", + "id": "id:78", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:79", + "id": "id:80", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:81", + "id": "id:82", + "lifecycle_state": "stable", + "name": "disallow-oxidant-etching-selection", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.5", + "auto_delete": true, + "created_at": "2024-09-09T09:10:36.000Z", + "href": "href:85", + "id": "id:86", + "lifecycle_state": "stable", + "name": "reheat-joyride-little-overprice", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:89", + "id": "id:90", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + } + ], + "public_gateways": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:30", + "floating_ip": { + "address": "52.118.147.142", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1" + }, + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "public_gateway", + "status": "available", + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "floating_ips": [ + { + "address": "52.116.129.168", + "created_at": "2024-09-09T09:11:31.000Z", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + }, + { + "address": "52.118.147.142", + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway", + "crn": "crn:30" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "network_acls": [ + { + "created_at": "2024-09-09T09:10:15.000Z", + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:99", + "id": "id:100", + "name": "acl2-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:97", + "id": "id:98", + "ip_version": "ipv4", + "name": "acl2-out-1", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:101", + "id": "id:102", + "name": "acl2-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:99", + "id": "id:100", + "ip_version": "ipv4", + "name": "acl2-out-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:103", + "id": "id:104", + "name": "acl2-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:101", + "id": "id:102", + "ip_version": "ipv4", + "name": "acl2-in-1", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:103", + "id": "id:104", + "ip_version": "ipv4", + "name": "acl2-in-2", + "source": "10.240.10.0/24", + "protocol": "all" + } + ], + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:107", + "id": "id:108", + "name": "acl1-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "172.217.22.46/32", + "direction": "outbound", + "href": "href:105", + "id": "id:106", + "ip_version": "ipv4", + "name": "acl1-out-1", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:109", + "id": "id:110", + "name": "acl1-out-3" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "outbound", + "href": "href:107", + "id": "id:108", + "ip_version": "ipv4", + "name": "acl1-out-2", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:111", + "id": "id:112", + "name": "acl1-out-4" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:109", + "id": "id:110", + "ip_version": "ipv4", + "name": "acl1-out-3", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:113", + "id": "id:114", + "name": "acl1-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:111", + "id": "id:112", + "ip_version": "ipv4", + "name": "acl1-out-4", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:115", + "id": "id:116", + "name": "acl1-in-2" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:113", + "id": "id:114", + "ip_version": "ipv4", + "name": "acl1-in-1", + "source": "172.217.22.46/32", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:117", + "id": "id:118", + "name": "acl1-in-3" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:115", + "id": "id:116", + "ip_version": "ipv4", + "name": "acl1-in-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:119", + "id": "id:120", + "name": "acl1-in-4" + }, + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:117", + "id": "id:118", + "ip_version": "ipv4", + "name": "acl1-in-3", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:119", + "id": "id:120", + "ip_version": "ipv4", + "name": "acl1-in-4", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + } + ], + "subnets": [ + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:123", + "id": "id:124", + "name": "acl3-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:121", + "id": "id:122", + "ip_version": "ipv4", + "name": "acl3-out-1", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:125", + "id": "id:126", + "name": "acl3-in-1" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:123", + "id": "id:124", + "ip_version": "ipv4", + "name": "acl3-out-2", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:127", + "id": "id:128", + "name": "acl3-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:125", + "id": "id:126", + "ip_version": "ipv4", + "name": "acl3-in-1", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:127", + "id": "id:128", + "ip_version": "ipv4", + "name": "acl3-in-2", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + } + ], + "subnets": [ + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:131", + "id": "id:132", + "name": "allow-outbound" + }, + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "inbound", + "href": "href:129", + "id": "id:130", + "ip_version": "ipv4", + "name": "allow-inbound", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:131", + "id": "id:132", + "ip_version": "ipv4", + "name": "allow-outbound", + "source": "0.0.0.0/0", + "protocol": "all" + } + ], + "subnets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "security_groups": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:133", + "href": "href:134", + "id": "id:135", + "name": "sg1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "href:136", + "id": "id:137", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "href:138", + "id": "id:139", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "href:140", + "id": "id:141", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "inbound", + "href": "href:142", + "id": "id:143", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "fake:href:1", + "id": "fake:id:1", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "code": 0, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "inbound", + "href": "fake:href:3", + "id": "fake:id:3", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "code": 1, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "inbound", + "href": "fake:href:4", + "id": "fake:id:4", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "code": 2, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "inbound", + "href": "fake:href:5", + "id": "fake:id:5", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "code": 3, + "protocol": "icmp", + "type": 5 + } + ], + "targets": [ + { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "fake:href:7", + "id": "fake:id:7", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "code": 0, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:8", + "id": "fake:id:8", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "code": 1, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:9", + "id": "fake:id:9", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "code": 2, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:10", + "id": "fake:id:10", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "code": 3, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:11", + "id": "fake:id:11", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi2" + }, + "code": 0, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:12", + "id": "fake:id:12", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi2" + }, + "code": 1, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:13", + "id": "fake:id:13", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi2" + }, + "code": 2, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:14", + "id": "fake:id:14", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi2" + }, + "code": 3, + "protocol": "icmp", + "type": 5 + } + ], + "targets": [ + { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:15", + "href": "fake:href:15", + "id": "fake:id:15", + "name": "test-vpc1--vsi3b", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:16", + "href": "fake:href:16", + "id": "fake:id:16", + "name": "test-vpc1--vsi3a", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "endpoint_gateways": [], + "instances": [ + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:11:07.000Z", + "crn": "crn:144", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:145", + "id": "id:146", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi2", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:11:07.000Z", + "floating_ips": [], + "href": "href:43", + "id": "id:44", + "name": "ni2", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi2" + } + ], + "status": "available", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:52.000Z", + "crn": "crn:157", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:158", + "id": "id:159", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi1", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:52.000Z", + "floating_ips": [ + { + "address": "52.116.129.168", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip" + } + ], + "href": "href:63", + "id": "id:64", + "name": "ni1", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + } + ], + "status": "available", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:166", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:167", + "id": "id:168", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3b", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:15", + "href": "fake:href:15", + "id": "fake:id:15", + "name": "test-vpc1--vsi3b" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:34.000Z", + "crn": "crn:175", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:176", + "id": "id:177", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3a", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:16", + "href": "fake:href:16", + "id": "fake:id:16", + "name": "test-vpc1--vsi3a" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + } + ], + "virtual_nis": null, + "routing_tables": [ + { + "accept_routes_from": [ + { + "resource_type": "vpn_gateway" + }, + { + "resource_type": "vpn_server" + } + ], + "advertise_routes_to": [], + "created_at": "2024-09-09T09:09:51.000Z", + "href": "href:11", + "id": "id:12", + "is_default": true, + "lifecycle_state": "stable", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table", + "route_direct_link_ingress": false, + "route_internet_ingress": false, + "route_transit_gateway_ingress": false, + "route_vpc_zone_ingress": false, + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "routes": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + } + } + ], + "load_balancers": [], + "transit_connections": null, + "transit_gateways": null, + "iks_clusters": [] +} \ No newline at end of file diff --git a/test/data/optimize_sg_icmp_codes/conn_spec.json b/test/data/optimize_sg_icmp_codes/conn_spec.json new file mode 100644 index 00000000..83342736 --- /dev/null +++ b/test/data/optimize_sg_icmp_codes/conn_spec.json @@ -0,0 +1,143 @@ +{ + "externals": { + "e1": "0.0.0.0/31" + }, + "required-connections": [ + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 0 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 1 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 2 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 3 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 0 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 1 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 2 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5, + "code": 3 + } + ] + } + ] +} diff --git a/test/data/optimize_sg_icmp_codes/details.txt b/test/data/optimize_sg_icmp_codes/details.txt new file mode 100644 index 00000000..ac439dbe --- /dev/null +++ b/test/data/optimize_sg_icmp_codes/details.txt @@ -0,0 +1,14 @@ +vsi1 --> 0.0.0.0/31 (icmp type:5 code:0) +vsi1 --> 0.0.0.0/31 (icmp type:5 code:1) +vsi1 --> 0.0.0.0/31 (icmp type:5 code:2) +vsi1 --> 0.0.0.0/31 (icmp type:5 code:3) + +vsi1 --> vsi2 (icmp type:5 code:0) +vsi1 --> vsi2 (icmp type:5 code:1) +vsi1 --> vsi2 (icmp type:5 code:2) +vsi1 --> vsi2 (icmp type:5 code:3) + +==================================== + +vsi1 --> 0.0.0.0/31 (icmp type:5) +vsi1 --> vsi2 (icmp type:5) \ No newline at end of file diff --git a/test/data/optimize_sg_icmp_types/config_object.json b/test/data/optimize_sg_icmp_types/config_object.json new file mode 100644 index 00000000..0511af0e --- /dev/null +++ b/test/data/optimize_sg_icmp_types/config_object.json @@ -0,0 +1,2493 @@ +{ + "collector_version": "0.11.0", + "provider": "ibm", + "vpcs": [ + { + "classic_access": false, + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:1", + "cse_source_ips": [ + { + "ip": { + "address": "10.22.217.112" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "ip": { + "address": "10.12.160.153" + }, + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "ip": { + "address": "10.16.253.223" + }, + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "default_network_acl": { + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail" + }, + "default_routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "default_security_group": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "dns": { + "enable_hub": false, + "resolution_binding_count": 0, + "resolver": { + "servers": [ + { + "address": "161.26.0.10" + }, + { + "address": "161.26.0.11" + } + ], + "type": "system", + "configuration": "default" + } + }, + "health_reasons": null, + "health_state": "ok", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "vpc", + "status": "available", + "region": "us-south", + "address_prefixes": [ + { + "cidr": "10.240.0.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": true, + "href": "href:18", + "id": "id:19", + "is_default": true, + "name": "filling-tasty-bacterium-parlor", + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "cidr": "10.240.64.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:20", + "id": "id:21", + "is_default": true, + "name": "relearn-ragweed-goon-feisty", + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "cidr": "10.240.128.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:22", + "id": "id:23", + "is_default": true, + "name": "unruffled-penknife-snowshoe-ninetieth", + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "tags": [] + } + ], + "subnets": [ + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:51.000Z", + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.20.0/24", + "name": "subnet2", + "network_acl": { + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.20.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:33", + "id": "id:34", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:35", + "id": "id:36", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:37", + "id": "id:38", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:39", + "id": "id:40", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.4", + "auto_delete": true, + "created_at": "2024-09-09T09:11:08.000Z", + "href": "href:41", + "id": "id:42", + "lifecycle_state": "stable", + "name": "startle-percent-embellish-squeegee", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.20.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:45", + "id": "id:46", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.10.0/24", + "name": "subnet1", + "network_acl": { + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.10.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:53", + "id": "id:54", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:55", + "id": "id:56", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:57", + "id": "id:58", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:59", + "id": "id:60", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:52.000Z", + "href": "href:61", + "id": "id:62", + "lifecycle_state": "stable", + "name": "tableware-sprawl-shrivel-popper", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.10.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:65", + "id": "id:66", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 249, + "created_at": "2024-09-09T09:10:18.000Z", + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.30.0/24", + "name": "subnet3", + "network_acl": { + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.30.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:73", + "id": "id:74", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:75", + "id": "id:76", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:77", + "id": "id:78", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:79", + "id": "id:80", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:81", + "id": "id:82", + "lifecycle_state": "stable", + "name": "disallow-oxidant-etching-selection", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.5", + "auto_delete": true, + "created_at": "2024-09-09T09:10:36.000Z", + "href": "href:85", + "id": "id:86", + "lifecycle_state": "stable", + "name": "reheat-joyride-little-overprice", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:89", + "id": "id:90", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + } + ], + "public_gateways": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:30", + "floating_ip": { + "address": "52.118.147.142", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1" + }, + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "public_gateway", + "status": "available", + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "floating_ips": [ + { + "address": "52.116.129.168", + "created_at": "2024-09-09T09:11:31.000Z", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + }, + { + "address": "52.118.147.142", + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway", + "crn": "crn:30" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "network_acls": [ + { + "created_at": "2024-09-09T09:10:15.000Z", + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:99", + "id": "id:100", + "name": "acl2-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:97", + "id": "id:98", + "ip_version": "ipv4", + "name": "acl2-out-1", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:101", + "id": "id:102", + "name": "acl2-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:99", + "id": "id:100", + "ip_version": "ipv4", + "name": "acl2-out-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:103", + "id": "id:104", + "name": "acl2-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:101", + "id": "id:102", + "ip_version": "ipv4", + "name": "acl2-in-1", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:103", + "id": "id:104", + "ip_version": "ipv4", + "name": "acl2-in-2", + "source": "10.240.10.0/24", + "protocol": "all" + } + ], + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:107", + "id": "id:108", + "name": "acl1-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "172.217.22.46/32", + "direction": "outbound", + "href": "href:105", + "id": "id:106", + "ip_version": "ipv4", + "name": "acl1-out-1", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:109", + "id": "id:110", + "name": "acl1-out-3" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "outbound", + "href": "href:107", + "id": "id:108", + "ip_version": "ipv4", + "name": "acl1-out-2", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:111", + "id": "id:112", + "name": "acl1-out-4" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:109", + "id": "id:110", + "ip_version": "ipv4", + "name": "acl1-out-3", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:113", + "id": "id:114", + "name": "acl1-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:111", + "id": "id:112", + "ip_version": "ipv4", + "name": "acl1-out-4", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:115", + "id": "id:116", + "name": "acl1-in-2" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:113", + "id": "id:114", + "ip_version": "ipv4", + "name": "acl1-in-1", + "source": "172.217.22.46/32", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:117", + "id": "id:118", + "name": "acl1-in-3" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:115", + "id": "id:116", + "ip_version": "ipv4", + "name": "acl1-in-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:119", + "id": "id:120", + "name": "acl1-in-4" + }, + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:117", + "id": "id:118", + "ip_version": "ipv4", + "name": "acl1-in-3", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:119", + "id": "id:120", + "ip_version": "ipv4", + "name": "acl1-in-4", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + } + ], + "subnets": [ + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:123", + "id": "id:124", + "name": "acl3-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:121", + "id": "id:122", + "ip_version": "ipv4", + "name": "acl3-out-1", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:125", + "id": "id:126", + "name": "acl3-in-1" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:123", + "id": "id:124", + "ip_version": "ipv4", + "name": "acl3-out-2", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:127", + "id": "id:128", + "name": "acl3-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:125", + "id": "id:126", + "ip_version": "ipv4", + "name": "acl3-in-1", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:127", + "id": "id:128", + "ip_version": "ipv4", + "name": "acl3-in-2", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + } + ], + "subnets": [ + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:131", + "id": "id:132", + "name": "allow-outbound" + }, + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "inbound", + "href": "href:129", + "id": "id:130", + "ip_version": "ipv4", + "name": "allow-inbound", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:131", + "id": "id:132", + "ip_version": "ipv4", + "name": "allow-outbound", + "source": "0.0.0.0/0", + "protocol": "all" + } + ], + "subnets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "security_groups": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:133", + "href": "href:134", + "id": "id:135", + "name": "sg1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "href:136", + "id": "id:137", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "href:138", + "id": "id:139", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "href:140", + "id": "id:141", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "inbound", + "href": "href:142", + "id": "id:143", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "fake:href:1", + "id": "fake:id:1", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 0 + }, + { + "direction": "inbound", + "href": "fake:href:3", + "id": "fake:id:3", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 3 + }, + { + "direction": "inbound", + "href": "fake:href:4", + "id": "fake:id:4", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 4 + }, + { + "direction": "inbound", + "href": "fake:href:5", + "id": "fake:id:5", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "inbound", + "href": "fake:href:6", + "id": "fake:id:6", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 8 + }, + { + "direction": "inbound", + "href": "fake:href:7", + "id": "fake:id:7", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 11 + }, + { + "direction": "inbound", + "href": "fake:href:8", + "id": "fake:id:8", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 12 + }, + { + "direction": "inbound", + "href": "fake:href:9", + "id": "fake:id:9", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 13 + }, + { + "direction": "inbound", + "href": "fake:href:10", + "id": "fake:id:10", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 14 + }, + { + "direction": "inbound", + "href": "fake:href:11", + "id": "fake:id:11", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 15 + }, + { + "direction": "inbound", + "href": "fake:href:12", + "id": "fake:id:12", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp", + "type": 16 + } + ], + "targets": [ + { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "fake:href:14", + "id": "fake:id:14", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 0 + }, + { + "direction": "outbound", + "href": "fake:href:15", + "id": "fake:id:15", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 3 + }, + { + "direction": "outbound", + "href": "fake:href:16", + "id": "fake:id:16", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 4 + }, + { + "direction": "outbound", + "href": "fake:href:17", + "id": "fake:id:17", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:18", + "id": "fake:id:18", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 8 + }, + { + "direction": "outbound", + "href": "fake:href:19", + "id": "fake:id:19", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 11 + }, + { + "direction": "outbound", + "href": "fake:href:20", + "id": "fake:id:20", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 12 + }, + { + "direction": "outbound", + "href": "fake:href:21", + "id": "fake:id:21", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 13 + }, + { + "direction": "outbound", + "href": "fake:href:22", + "id": "fake:id:22", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 14 + }, + { + "direction": "outbound", + "href": "fake:href:23", + "id": "fake:id:23", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 15 + }, + { + "direction": "outbound", + "href": "fake:href:24", + "id": "fake:id:24", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp", + "type": 16 + }, + { + "direction": "outbound", + "href": "fake:href:25", + "id": "fake:id:25", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 0 + }, + { + "direction": "outbound", + "href": "fake:href:26", + "id": "fake:id:26", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 3 + }, + { + "direction": "outbound", + "href": "fake:href:27", + "id": "fake:id:27", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 4 + }, + { + "direction": "outbound", + "href": "fake:href:28", + "id": "fake:id:28", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 5 + }, + { + "direction": "outbound", + "href": "fake:href:29", + "id": "fake:id:29", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 8 + }, + { + "direction": "outbound", + "href": "fake:href:30", + "id": "fake:id:30", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 11 + }, + { + "direction": "outbound", + "href": "fake:href:31", + "id": "fake:id:31", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 12 + }, + { + "direction": "outbound", + "href": "fake:href:32", + "id": "fake:id:32", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 13 + }, + { + "direction": "outbound", + "href": "fake:href:33", + "id": "fake:id:33", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 14 + }, + { + "direction": "outbound", + "href": "fake:href:34", + "id": "fake:id:34", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 15 + }, + { + "direction": "outbound", + "href": "fake:href:35", + "id": "fake:id:35", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp", + "type": 16 + } + ], + "targets": [ + { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:36", + "href": "fake:href:36", + "id": "fake:id:36", + "name": "test-vpc1--vsi3b", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:37", + "href": "fake:href:37", + "id": "fake:id:37", + "name": "test-vpc1--vsi3a", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "endpoint_gateways": [], + "instances": [ + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:11:07.000Z", + "crn": "crn:144", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:145", + "id": "id:146", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi2", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:11:07.000Z", + "floating_ips": [], + "href": "href:43", + "id": "id:44", + "name": "ni2", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:13", + "href": "fake:href:13", + "id": "fake:id:13", + "name": "test-vpc1--vsi2" + } + ], + "status": "available", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:52.000Z", + "crn": "crn:157", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:158", + "id": "id:159", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi1", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:52.000Z", + "floating_ips": [ + { + "address": "52.116.129.168", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip" + } + ], + "href": "href:63", + "id": "id:64", + "name": "ni1", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + } + ], + "status": "available", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:166", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:167", + "id": "id:168", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3b", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:36", + "href": "fake:href:36", + "id": "fake:id:36", + "name": "test-vpc1--vsi3b" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:34.000Z", + "crn": "crn:175", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:176", + "id": "id:177", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3a", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:37", + "href": "fake:href:37", + "id": "fake:id:37", + "name": "test-vpc1--vsi3a" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + } + ], + "virtual_nis": null, + "routing_tables": [ + { + "accept_routes_from": [ + { + "resource_type": "vpn_gateway" + }, + { + "resource_type": "vpn_server" + } + ], + "advertise_routes_to": [], + "created_at": "2024-09-09T09:09:51.000Z", + "href": "href:11", + "id": "id:12", + "is_default": true, + "lifecycle_state": "stable", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table", + "route_direct_link_ingress": false, + "route_internet_ingress": false, + "route_transit_gateway_ingress": false, + "route_vpc_zone_ingress": false, + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "routes": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + } + } + ], + "load_balancers": [], + "transit_connections": null, + "transit_gateways": null, + "iks_clusters": [] +} \ No newline at end of file diff --git a/test/data/optimize_sg_icmp_types/conn_spec.json b/test/data/optimize_sg_icmp_types/conn_spec.json new file mode 100644 index 00000000..f9c8648c --- /dev/null +++ b/test/data/optimize_sg_icmp_types/conn_spec.json @@ -0,0 +1,359 @@ +{ + "externals": { + "e1": "0.0.0.0/31" + }, + "required-connections": [ + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 0 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 3 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 4 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 8 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 11 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 12 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 13 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 14 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 15 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 16 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 0 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 3 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 4 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 5 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 8 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 11 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 12 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 13 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 14 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 15 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP", + "type": 16 + } + ] + } + ] +} diff --git a/test/data/optimize_sg_icmp_types/details.txt b/test/data/optimize_sg_icmp_types/details.txt new file mode 100644 index 00000000..c13db0ec --- /dev/null +++ b/test/data/optimize_sg_icmp_types/details.txt @@ -0,0 +1,28 @@ +vsi1 --> 0.0.0.0/31 (icmp type:0) +vsi1 --> 0.0.0.0/31 (icmp type:3) +vsi1 --> 0.0.0.0/31 (icmp type:4) +vsi1 --> 0.0.0.0/31 (icmp type:5) +vsi1 --> 0.0.0.0/31 (icmp type:8) +vsi1 --> 0.0.0.0/31 (icmp type:11) +vsi1 --> 0.0.0.0/31 (icmp type:12) +vsi1 --> 0.0.0.0/31 (icmp type:13) +vsi1 --> 0.0.0.0/31 (icmp type:14) +vsi1 --> 0.0.0.0/31 (icmp type:15) +vsi1 --> 0.0.0.0/31 (icmp type:16) + +vsi1 --> vsi2 (icmp type:0) +vsi1 --> vsi2 (icmp type:3) +vsi1 --> vsi2 (icmp type:4) +vsi1 --> vsi2 (icmp type:5) +vsi1 --> vsi2 (icmp type:8) +vsi1 --> vsi2 (icmp type:11) +vsi1 --> vsi2 (icmp type:12) +vsi1 --> vsi2 (icmp type:13) +vsi1 --> vsi2 (icmp type:14) +vsi1 --> vsi2 (icmp type:15) +vsi1 --> vsi2 (icmp type:16) + +==================================== + +vsi1 --> 0.0.0.0/31 (icmp) +vsi1 --> vsi2 (icmp) \ No newline at end of file diff --git a/test/data/optimize_sg_protocols_to_all/config_object.json b/test/data/optimize_sg_protocols_to_all/config_object.json new file mode 100644 index 00000000..23a99429 --- /dev/null +++ b/test/data/optimize_sg_protocols_to_all/config_object.json @@ -0,0 +1,2214 @@ +{ + "collector_version": "0.11.0", + "provider": "ibm", + "vpcs": [ + { + "classic_access": false, + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:1", + "cse_source_ips": [ + { + "ip": { + "address": "10.22.217.112" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "ip": { + "address": "10.12.160.153" + }, + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "ip": { + "address": "10.16.253.223" + }, + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "default_network_acl": { + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail" + }, + "default_routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "default_security_group": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "dns": { + "enable_hub": false, + "resolution_binding_count": 0, + "resolver": { + "servers": [ + { + "address": "161.26.0.10" + }, + { + "address": "161.26.0.11" + } + ], + "type": "system", + "configuration": "default" + } + }, + "health_reasons": null, + "health_state": "ok", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "vpc", + "status": "available", + "region": "us-south", + "address_prefixes": [ + { + "cidr": "10.240.0.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": true, + "href": "href:18", + "id": "id:19", + "is_default": true, + "name": "filling-tasty-bacterium-parlor", + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "cidr": "10.240.64.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:20", + "id": "id:21", + "is_default": true, + "name": "relearn-ragweed-goon-feisty", + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "cidr": "10.240.128.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:22", + "id": "id:23", + "is_default": true, + "name": "unruffled-penknife-snowshoe-ninetieth", + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "tags": [] + } + ], + "subnets": [ + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:51.000Z", + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.20.0/24", + "name": "subnet2", + "network_acl": { + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.20.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:33", + "id": "id:34", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:35", + "id": "id:36", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:37", + "id": "id:38", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:39", + "id": "id:40", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.4", + "auto_delete": true, + "created_at": "2024-09-09T09:11:08.000Z", + "href": "href:41", + "id": "id:42", + "lifecycle_state": "stable", + "name": "startle-percent-embellish-squeegee", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.20.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:45", + "id": "id:46", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.10.0/24", + "name": "subnet1", + "network_acl": { + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.10.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:53", + "id": "id:54", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:55", + "id": "id:56", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:57", + "id": "id:58", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:59", + "id": "id:60", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:52.000Z", + "href": "href:61", + "id": "id:62", + "lifecycle_state": "stable", + "name": "tableware-sprawl-shrivel-popper", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.10.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:65", + "id": "id:66", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 249, + "created_at": "2024-09-09T09:10:18.000Z", + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.30.0/24", + "name": "subnet3", + "network_acl": { + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.30.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:73", + "id": "id:74", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:75", + "id": "id:76", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:77", + "id": "id:78", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:79", + "id": "id:80", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:81", + "id": "id:82", + "lifecycle_state": "stable", + "name": "disallow-oxidant-etching-selection", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.5", + "auto_delete": true, + "created_at": "2024-09-09T09:10:36.000Z", + "href": "href:85", + "id": "id:86", + "lifecycle_state": "stable", + "name": "reheat-joyride-little-overprice", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:89", + "id": "id:90", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + } + ], + "public_gateways": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:30", + "floating_ip": { + "address": "52.118.147.142", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1" + }, + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "public_gateway", + "status": "available", + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "floating_ips": [ + { + "address": "52.116.129.168", + "created_at": "2024-09-09T09:11:31.000Z", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + }, + { + "address": "52.118.147.142", + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway", + "crn": "crn:30" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "network_acls": [ + { + "created_at": "2024-09-09T09:10:15.000Z", + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:99", + "id": "id:100", + "name": "acl2-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:97", + "id": "id:98", + "ip_version": "ipv4", + "name": "acl2-out-1", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:101", + "id": "id:102", + "name": "acl2-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:99", + "id": "id:100", + "ip_version": "ipv4", + "name": "acl2-out-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:103", + "id": "id:104", + "name": "acl2-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:101", + "id": "id:102", + "ip_version": "ipv4", + "name": "acl2-in-1", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:103", + "id": "id:104", + "ip_version": "ipv4", + "name": "acl2-in-2", + "source": "10.240.10.0/24", + "protocol": "all" + } + ], + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:107", + "id": "id:108", + "name": "acl1-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "172.217.22.46/32", + "direction": "outbound", + "href": "href:105", + "id": "id:106", + "ip_version": "ipv4", + "name": "acl1-out-1", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:109", + "id": "id:110", + "name": "acl1-out-3" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "outbound", + "href": "href:107", + "id": "id:108", + "ip_version": "ipv4", + "name": "acl1-out-2", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:111", + "id": "id:112", + "name": "acl1-out-4" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:109", + "id": "id:110", + "ip_version": "ipv4", + "name": "acl1-out-3", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:113", + "id": "id:114", + "name": "acl1-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:111", + "id": "id:112", + "ip_version": "ipv4", + "name": "acl1-out-4", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:115", + "id": "id:116", + "name": "acl1-in-2" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:113", + "id": "id:114", + "ip_version": "ipv4", + "name": "acl1-in-1", + "source": "172.217.22.46/32", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:117", + "id": "id:118", + "name": "acl1-in-3" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:115", + "id": "id:116", + "ip_version": "ipv4", + "name": "acl1-in-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:119", + "id": "id:120", + "name": "acl1-in-4" + }, + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:117", + "id": "id:118", + "ip_version": "ipv4", + "name": "acl1-in-3", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:119", + "id": "id:120", + "ip_version": "ipv4", + "name": "acl1-in-4", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + } + ], + "subnets": [ + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:123", + "id": "id:124", + "name": "acl3-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:121", + "id": "id:122", + "ip_version": "ipv4", + "name": "acl3-out-1", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:125", + "id": "id:126", + "name": "acl3-in-1" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:123", + "id": "id:124", + "ip_version": "ipv4", + "name": "acl3-out-2", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:127", + "id": "id:128", + "name": "acl3-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:125", + "id": "id:126", + "ip_version": "ipv4", + "name": "acl3-in-1", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:127", + "id": "id:128", + "ip_version": "ipv4", + "name": "acl3-in-2", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + } + ], + "subnets": [ + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:131", + "id": "id:132", + "name": "allow-outbound" + }, + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "inbound", + "href": "href:129", + "id": "id:130", + "ip_version": "ipv4", + "name": "allow-inbound", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:131", + "id": "id:132", + "ip_version": "ipv4", + "name": "allow-outbound", + "source": "0.0.0.0/0", + "protocol": "all" + } + ], + "subnets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "security_groups": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:133", + "href": "href:134", + "id": "id:135", + "name": "sg1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "href:136", + "id": "id:137", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "href:138", + "id": "id:139", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "href:140", + "id": "id:141", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "inbound", + "href": "href:142", + "id": "id:143", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "fake:href:1", + "id": "fake:id:1", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "icmp" + }, + { + "direction": "inbound", + "href": "fake:href:3", + "id": "fake:id:3", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "port_max": 65535, + "port_min": 1, + "protocol": "tcp" + }, + { + "direction": "inbound", + "href": "fake:href:4", + "id": "fake:id:4", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "port_max": 100, + "port_min": 1, + "protocol": "udp" + }, + { + "direction": "inbound", + "href": "fake:href:5", + "id": "fake:id:5", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "port_max": 150, + "port_min": 50, + "protocol": "udp" + }, + { + "direction": "inbound", + "href": "fake:href:6", + "id": "fake:id:6", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "port_max": 65535, + "port_min": 151, + "protocol": "udp" + } + ], + "targets": [ + { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "fake:href:8", + "id": "fake:id:8", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "icmp" + }, + { + "direction": "outbound", + "href": "fake:href:9", + "id": "fake:id:9", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "port_max": 65535, + "port_min": 1, + "protocol": "tcp" + }, + { + "direction": "outbound", + "href": "fake:href:10", + "id": "fake:id:10", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "port_max": 100, + "port_min": 1, + "protocol": "udp" + }, + { + "direction": "outbound", + "href": "fake:href:11", + "id": "fake:id:11", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "port_max": 150, + "port_min": 50, + "protocol": "udp" + }, + { + "direction": "outbound", + "href": "fake:href:12", + "id": "fake:id:12", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "port_max": 65535, + "port_min": 151, + "protocol": "udp" + }, + { + "direction": "outbound", + "href": "fake:href:13", + "id": "fake:id:13", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + }, + "protocol": "icmp" + }, + { + "direction": "outbound", + "href": "fake:href:14", + "id": "fake:id:14", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + }, + "port_max": 65535, + "port_min": 1, + "protocol": "tcp" + }, + { + "direction": "outbound", + "href": "fake:href:15", + "id": "fake:id:15", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + }, + "port_max": 100, + "port_min": 1, + "protocol": "udp" + }, + { + "direction": "outbound", + "href": "fake:href:16", + "id": "fake:id:16", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + }, + "port_max": 150, + "port_min": 50, + "protocol": "udp" + }, + { + "direction": "outbound", + "href": "fake:href:17", + "id": "fake:id:17", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + }, + "port_max": 65535, + "port_min": 151, + "protocol": "udp" + } + ], + "targets": [ + { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:18", + "href": "fake:href:18", + "id": "fake:id:18", + "name": "test-vpc1--vsi3b", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:19", + "href": "fake:href:19", + "id": "fake:id:19", + "name": "test-vpc1--vsi3a", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "endpoint_gateways": [], + "instances": [ + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:11:07.000Z", + "crn": "crn:144", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:145", + "id": "id:146", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi2", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:11:07.000Z", + "floating_ips": [], + "href": "href:43", + "id": "id:44", + "name": "ni2", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + } + ], + "status": "available", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:52.000Z", + "crn": "crn:157", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:158", + "id": "id:159", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi1", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:52.000Z", + "floating_ips": [ + { + "address": "52.116.129.168", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip" + } + ], + "href": "href:63", + "id": "id:64", + "name": "ni1", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + } + ], + "status": "available", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:166", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:167", + "id": "id:168", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3b", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:18", + "href": "fake:href:18", + "id": "fake:id:18", + "name": "test-vpc1--vsi3b" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:34.000Z", + "crn": "crn:175", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:176", + "id": "id:177", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3a", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:19", + "href": "fake:href:19", + "id": "fake:id:19", + "name": "test-vpc1--vsi3a" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + } + ], + "virtual_nis": null, + "routing_tables": [ + { + "accept_routes_from": [ + { + "resource_type": "vpn_gateway" + }, + { + "resource_type": "vpn_server" + } + ], + "advertise_routes_to": [], + "created_at": "2024-09-09T09:09:51.000Z", + "href": "href:11", + "id": "id:12", + "is_default": true, + "lifecycle_state": "stable", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table", + "route_direct_link_ingress": false, + "route_internet_ingress": false, + "route_transit_gateway_ingress": false, + "route_vpc_zone_ingress": false, + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "routes": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + } + } + ], + "load_balancers": [], + "transit_connections": null, + "transit_gateways": null, + "iks_clusters": [] +} \ No newline at end of file diff --git a/test/data/optimize_sg_protocols_to_all/conn_spec.json b/test/data/optimize_sg_protocols_to_all/conn_spec.json new file mode 100644 index 00000000..32a127fb --- /dev/null +++ b/test/data/optimize_sg_protocols_to_all/conn_spec.json @@ -0,0 +1,169 @@ +{ + "externals": { + "e1": "0.0.0.0/31" + }, + "required-connections": [ + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "ICMP" + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "TCP" + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "UDP", + "min_destination_port": 1, + "max_destination_port": 100 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "UDP", + "min_destination_port": 50, + "max_destination_port": 150 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "UDP", + "min_destination_port": 151, + "max_destination_port": 65535 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "ICMP" + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "TCP" + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "UDP", + "min_destination_port": 1, + "max_destination_port": 100 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "UDP", + "min_destination_port": 50, + "max_destination_port": 150 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + }, + "allowed-protocols": [ + { + "protocol": "UDP", + "min_destination_port": 151, + "max_destination_port": 65535 + } + ] + } + ] +} diff --git a/test/data/optimize_sg_protocols_to_all/details.txt b/test/data/optimize_sg_protocols_to_all/details.txt new file mode 100644 index 00000000..ca29dc0f --- /dev/null +++ b/test/data/optimize_sg_protocols_to_all/details.txt @@ -0,0 +1,16 @@ +vsi1 --> 0.0.0.0/31 (icmp) +vsi1 --> 0.0.0.0/31 (tcp) +vsi1 --> 0.0.0.0/31 (udp ports 1-100) +vsi1 --> 0.0.0.0/31 (udp ports 50-150) +vsi1 --> 0.0.0.0/31 (udp ports 151-65535) + +vsi1 --> vsi2 (icmp) +vsi1 --> vsi2 (tcp) +vsi1 --> vsi2 (udp ports 1-100) +vsi1 --> vsi2 (udp ports 50-150) +vsi1 --> vsi2 (udp ports 151-65535) + +==================================== + +vsi1 --> 0.0.0.0/31 (all protocol) +vsi1 --> vsi2 (all protocol) \ No newline at end of file diff --git a/test/data/optimize_sg_redundant/config_object.json b/test/data/optimize_sg_redundant/config_object.json new file mode 100644 index 00000000..e9dd5c87 --- /dev/null +++ b/test/data/optimize_sg_redundant/config_object.json @@ -0,0 +1,2023 @@ +{ + "collector_version": "0.11.0", + "provider": "ibm", + "vpcs": [ + { + "classic_access": false, + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:1", + "cse_source_ips": [ + { + "ip": { + "address": "10.22.217.112" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "ip": { + "address": "10.12.160.153" + }, + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "ip": { + "address": "10.16.253.223" + }, + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "default_network_acl": { + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail" + }, + "default_routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "default_security_group": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "dns": { + "enable_hub": false, + "resolution_binding_count": 0, + "resolver": { + "servers": [ + { + "address": "161.26.0.10" + }, + { + "address": "161.26.0.11" + } + ], + "type": "system", + "configuration": "default" + } + }, + "health_reasons": null, + "health_state": "ok", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "vpc", + "status": "available", + "region": "us-south", + "address_prefixes": [ + { + "cidr": "10.240.0.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": true, + "href": "href:18", + "id": "id:19", + "is_default": true, + "name": "filling-tasty-bacterium-parlor", + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "cidr": "10.240.64.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:20", + "id": "id:21", + "is_default": true, + "name": "relearn-ragweed-goon-feisty", + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "cidr": "10.240.128.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:22", + "id": "id:23", + "is_default": true, + "name": "unruffled-penknife-snowshoe-ninetieth", + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "tags": [] + } + ], + "subnets": [ + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:51.000Z", + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.20.0/24", + "name": "subnet2", + "network_acl": { + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.20.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:33", + "id": "id:34", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:35", + "id": "id:36", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:37", + "id": "id:38", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:39", + "id": "id:40", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.4", + "auto_delete": true, + "created_at": "2024-09-09T09:11:08.000Z", + "href": "href:41", + "id": "id:42", + "lifecycle_state": "stable", + "name": "startle-percent-embellish-squeegee", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.20.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:45", + "id": "id:46", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.10.0/24", + "name": "subnet1", + "network_acl": { + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.10.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:53", + "id": "id:54", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:55", + "id": "id:56", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:57", + "id": "id:58", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:59", + "id": "id:60", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:52.000Z", + "href": "href:61", + "id": "id:62", + "lifecycle_state": "stable", + "name": "tableware-sprawl-shrivel-popper", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.10.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:65", + "id": "id:66", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 249, + "created_at": "2024-09-09T09:10:18.000Z", + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.30.0/24", + "name": "subnet3", + "network_acl": { + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.30.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:73", + "id": "id:74", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:75", + "id": "id:76", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:77", + "id": "id:78", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:79", + "id": "id:80", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:81", + "id": "id:82", + "lifecycle_state": "stable", + "name": "disallow-oxidant-etching-selection", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.5", + "auto_delete": true, + "created_at": "2024-09-09T09:10:36.000Z", + "href": "href:85", + "id": "id:86", + "lifecycle_state": "stable", + "name": "reheat-joyride-little-overprice", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:89", + "id": "id:90", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + } + ], + "public_gateways": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:30", + "floating_ip": { + "address": "52.118.147.142", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1" + }, + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "public_gateway", + "status": "available", + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "floating_ips": [ + { + "address": "52.116.129.168", + "created_at": "2024-09-09T09:11:31.000Z", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + }, + { + "address": "52.118.147.142", + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway", + "crn": "crn:30" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "network_acls": [ + { + "created_at": "2024-09-09T09:10:15.000Z", + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:99", + "id": "id:100", + "name": "acl2-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:97", + "id": "id:98", + "ip_version": "ipv4", + "name": "acl2-out-1", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:101", + "id": "id:102", + "name": "acl2-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:99", + "id": "id:100", + "ip_version": "ipv4", + "name": "acl2-out-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:103", + "id": "id:104", + "name": "acl2-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:101", + "id": "id:102", + "ip_version": "ipv4", + "name": "acl2-in-1", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:103", + "id": "id:104", + "ip_version": "ipv4", + "name": "acl2-in-2", + "source": "10.240.10.0/24", + "protocol": "all" + } + ], + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:107", + "id": "id:108", + "name": "acl1-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "172.217.22.46/32", + "direction": "outbound", + "href": "href:105", + "id": "id:106", + "ip_version": "ipv4", + "name": "acl1-out-1", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:109", + "id": "id:110", + "name": "acl1-out-3" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "outbound", + "href": "href:107", + "id": "id:108", + "ip_version": "ipv4", + "name": "acl1-out-2", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:111", + "id": "id:112", + "name": "acl1-out-4" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:109", + "id": "id:110", + "ip_version": "ipv4", + "name": "acl1-out-3", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:113", + "id": "id:114", + "name": "acl1-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:111", + "id": "id:112", + "ip_version": "ipv4", + "name": "acl1-out-4", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:115", + "id": "id:116", + "name": "acl1-in-2" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:113", + "id": "id:114", + "ip_version": "ipv4", + "name": "acl1-in-1", + "source": "172.217.22.46/32", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:117", + "id": "id:118", + "name": "acl1-in-3" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:115", + "id": "id:116", + "ip_version": "ipv4", + "name": "acl1-in-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:119", + "id": "id:120", + "name": "acl1-in-4" + }, + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:117", + "id": "id:118", + "ip_version": "ipv4", + "name": "acl1-in-3", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:119", + "id": "id:120", + "ip_version": "ipv4", + "name": "acl1-in-4", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + } + ], + "subnets": [ + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:123", + "id": "id:124", + "name": "acl3-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:121", + "id": "id:122", + "ip_version": "ipv4", + "name": "acl3-out-1", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:125", + "id": "id:126", + "name": "acl3-in-1" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:123", + "id": "id:124", + "ip_version": "ipv4", + "name": "acl3-out-2", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:127", + "id": "id:128", + "name": "acl3-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:125", + "id": "id:126", + "ip_version": "ipv4", + "name": "acl3-in-1", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:127", + "id": "id:128", + "ip_version": "ipv4", + "name": "acl3-in-2", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + } + ], + "subnets": [ + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:131", + "id": "id:132", + "name": "allow-outbound" + }, + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "inbound", + "href": "href:129", + "id": "id:130", + "ip_version": "ipv4", + "name": "allow-inbound", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:131", + "id": "id:132", + "ip_version": "ipv4", + "name": "allow-outbound", + "source": "0.0.0.0/0", + "protocol": "all" + } + ], + "subnets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "security_groups": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:133", + "href": "href:134", + "id": "id:135", + "name": "sg1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "href:136", + "id": "id:137", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "href:138", + "id": "id:139", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "href:140", + "id": "id:141", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "inbound", + "href": "href:142", + "id": "id:143", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:3", + "href": "fake:href:3", + "id": "fake:id:3", + "name": "test-vpc1--vsi2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "fake:href:1", + "id": "fake:id:1", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "all" + } + ], + "targets": [ + { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "fake:href:4", + "id": "fake:id:4", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/30" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "fake:href:5", + "id": "fake:id:5", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "fake:href:6", + "id": "fake:id:6", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:3", + "href": "fake:href:3", + "id": "fake:id:3", + "name": "test-vpc1--vsi2" + }, + "protocol": "all" + } + ], + "targets": [ + { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi3b", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:8", + "href": "fake:href:8", + "id": "fake:id:8", + "name": "test-vpc1--vsi3a", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "endpoint_gateways": [], + "instances": [ + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:11:07.000Z", + "crn": "crn:144", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:145", + "id": "id:146", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi2", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:11:07.000Z", + "floating_ips": [], + "href": "href:43", + "id": "id:44", + "name": "ni2", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:3", + "href": "fake:href:3", + "id": "fake:id:3", + "name": "test-vpc1--vsi2" + } + ], + "status": "available", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:52.000Z", + "crn": "crn:157", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:158", + "id": "id:159", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi1", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:52.000Z", + "floating_ips": [ + { + "address": "52.116.129.168", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip" + } + ], + "href": "href:63", + "id": "id:64", + "name": "ni1", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + } + ], + "status": "available", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:166", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:167", + "id": "id:168", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3b", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi3b" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:34.000Z", + "crn": "crn:175", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:176", + "id": "id:177", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3a", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:8", + "href": "fake:href:8", + "id": "fake:id:8", + "name": "test-vpc1--vsi3a" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + } + ], + "virtual_nis": null, + "routing_tables": [ + { + "accept_routes_from": [ + { + "resource_type": "vpn_gateway" + }, + { + "resource_type": "vpn_server" + } + ], + "advertise_routes_to": [], + "created_at": "2024-09-09T09:09:51.000Z", + "href": "href:11", + "id": "id:12", + "is_default": true, + "lifecycle_state": "stable", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table", + "route_direct_link_ingress": false, + "route_internet_ingress": false, + "route_transit_gateway_ingress": false, + "route_vpc_zone_ingress": false, + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "routes": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + } + } + ], + "load_balancers": [], + "transit_connections": null, + "transit_gateways": null, + "iks_clusters": [] +} \ No newline at end of file diff --git a/test/data/optimize_sg_redundant/conn_spec.json b/test/data/optimize_sg_redundant/conn_spec.json new file mode 100644 index 00000000..ef2331cd --- /dev/null +++ b/test/data/optimize_sg_redundant/conn_spec.json @@ -0,0 +1,48 @@ +{ + "externals": { + "e1": "0.0.0.0/30", + "e2": "0.0.0.0/31" + }, + "required-connections": [ + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + } + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e2", + "type": "external" + } + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + } + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "vsi2", + "type": "instance" + } + } + ] +} diff --git a/test/data/optimize_sg_redundant/details.txt b/test/data/optimize_sg_redundant/details.txt new file mode 100644 index 00000000..70573b2d --- /dev/null +++ b/test/data/optimize_sg_redundant/details.txt @@ -0,0 +1,10 @@ +vsi1 --> 0.0.0.0/30 (protocol all) +vsi1 --> 0.0.0.0/31 (protocol all) + +vsi1 --> vsi2 (protocol all) +vsi1 --> vsi2 (protocol all) + +==================================== + +vsi1 --> 0.0.0.0/30 (all protocol) +vsi1 --> vsi2 (all protocol) \ No newline at end of file diff --git a/test/data/optimize_sg_t/config_object.json b/test/data/optimize_sg_t/config_object.json new file mode 100644 index 00000000..347bd139 --- /dev/null +++ b/test/data/optimize_sg_t/config_object.json @@ -0,0 +1,2009 @@ +{ + "collector_version": "0.11.0", + "provider": "ibm", + "vpcs": [ + { + "classic_access": false, + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:1", + "cse_source_ips": [ + { + "ip": { + "address": "10.22.217.112" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "ip": { + "address": "10.12.160.153" + }, + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "ip": { + "address": "10.16.253.223" + }, + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "default_network_acl": { + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail" + }, + "default_routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "default_security_group": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "dns": { + "enable_hub": false, + "resolution_binding_count": 0, + "resolver": { + "servers": [ + { + "address": "161.26.0.10" + }, + { + "address": "161.26.0.11" + } + ], + "type": "system", + "configuration": "default" + } + }, + "health_reasons": null, + "health_state": "ok", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "vpc", + "status": "available", + "region": "us-south", + "address_prefixes": [ + { + "cidr": "10.240.0.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": true, + "href": "href:18", + "id": "id:19", + "is_default": true, + "name": "filling-tasty-bacterium-parlor", + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "cidr": "10.240.64.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:20", + "id": "id:21", + "is_default": true, + "name": "relearn-ragweed-goon-feisty", + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "cidr": "10.240.128.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:22", + "id": "id:23", + "is_default": true, + "name": "unruffled-penknife-snowshoe-ninetieth", + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "tags": [] + } + ], + "subnets": [ + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:51.000Z", + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.20.0/24", + "name": "subnet2", + "network_acl": { + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.20.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:33", + "id": "id:34", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:35", + "id": "id:36", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:37", + "id": "id:38", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:39", + "id": "id:40", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.4", + "auto_delete": true, + "created_at": "2024-09-09T09:11:08.000Z", + "href": "href:41", + "id": "id:42", + "lifecycle_state": "stable", + "name": "startle-percent-embellish-squeegee", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.20.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:45", + "id": "id:46", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.10.0/24", + "name": "subnet1", + "network_acl": { + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.10.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:53", + "id": "id:54", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:55", + "id": "id:56", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:57", + "id": "id:58", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:59", + "id": "id:60", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:52.000Z", + "href": "href:61", + "id": "id:62", + "lifecycle_state": "stable", + "name": "tableware-sprawl-shrivel-popper", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.10.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:65", + "id": "id:66", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 249, + "created_at": "2024-09-09T09:10:18.000Z", + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.30.0/24", + "name": "subnet3", + "network_acl": { + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.30.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:73", + "id": "id:74", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:75", + "id": "id:76", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:77", + "id": "id:78", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:79", + "id": "id:80", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:81", + "id": "id:82", + "lifecycle_state": "stable", + "name": "disallow-oxidant-etching-selection", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.5", + "auto_delete": true, + "created_at": "2024-09-09T09:10:36.000Z", + "href": "href:85", + "id": "id:86", + "lifecycle_state": "stable", + "name": "reheat-joyride-little-overprice", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:89", + "id": "id:90", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + } + ], + "public_gateways": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:30", + "floating_ip": { + "address": "52.118.147.142", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1" + }, + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "public_gateway", + "status": "available", + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "floating_ips": [ + { + "address": "52.116.129.168", + "created_at": "2024-09-09T09:11:31.000Z", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + }, + { + "address": "52.118.147.142", + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway", + "crn": "crn:30" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "network_acls": [ + { + "created_at": "2024-09-09T09:10:15.000Z", + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:99", + "id": "id:100", + "name": "acl2-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:97", + "id": "id:98", + "ip_version": "ipv4", + "name": "acl2-out-1", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:101", + "id": "id:102", + "name": "acl2-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:99", + "id": "id:100", + "ip_version": "ipv4", + "name": "acl2-out-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:103", + "id": "id:104", + "name": "acl2-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:101", + "id": "id:102", + "ip_version": "ipv4", + "name": "acl2-in-1", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:103", + "id": "id:104", + "ip_version": "ipv4", + "name": "acl2-in-2", + "source": "10.240.10.0/24", + "protocol": "all" + } + ], + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:107", + "id": "id:108", + "name": "acl1-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "172.217.22.46/32", + "direction": "outbound", + "href": "href:105", + "id": "id:106", + "ip_version": "ipv4", + "name": "acl1-out-1", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:109", + "id": "id:110", + "name": "acl1-out-3" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "outbound", + "href": "href:107", + "id": "id:108", + "ip_version": "ipv4", + "name": "acl1-out-2", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:111", + "id": "id:112", + "name": "acl1-out-4" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:109", + "id": "id:110", + "ip_version": "ipv4", + "name": "acl1-out-3", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:113", + "id": "id:114", + "name": "acl1-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:111", + "id": "id:112", + "ip_version": "ipv4", + "name": "acl1-out-4", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:115", + "id": "id:116", + "name": "acl1-in-2" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:113", + "id": "id:114", + "ip_version": "ipv4", + "name": "acl1-in-1", + "source": "172.217.22.46/32", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:117", + "id": "id:118", + "name": "acl1-in-3" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:115", + "id": "id:116", + "ip_version": "ipv4", + "name": "acl1-in-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:119", + "id": "id:120", + "name": "acl1-in-4" + }, + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:117", + "id": "id:118", + "ip_version": "ipv4", + "name": "acl1-in-3", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:119", + "id": "id:120", + "ip_version": "ipv4", + "name": "acl1-in-4", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + } + ], + "subnets": [ + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:123", + "id": "id:124", + "name": "acl3-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:121", + "id": "id:122", + "ip_version": "ipv4", + "name": "acl3-out-1", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:125", + "id": "id:126", + "name": "acl3-in-1" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:123", + "id": "id:124", + "ip_version": "ipv4", + "name": "acl3-out-2", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:127", + "id": "id:128", + "name": "acl3-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:125", + "id": "id:126", + "ip_version": "ipv4", + "name": "acl3-in-1", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:127", + "id": "id:128", + "ip_version": "ipv4", + "name": "acl3-in-2", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + } + ], + "subnets": [ + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:131", + "id": "id:132", + "name": "allow-outbound" + }, + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "inbound", + "href": "href:129", + "id": "id:130", + "ip_version": "ipv4", + "name": "allow-inbound", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:131", + "id": "id:132", + "ip_version": "ipv4", + "name": "allow-outbound", + "source": "0.0.0.0/0", + "protocol": "all" + } + ], + "subnets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "security_groups": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:133", + "href": "href:134", + "id": "id:135", + "name": "sg1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "href:136", + "id": "id:137", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "href:138", + "id": "id:139", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "href:140", + "id": "id:141", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "inbound", + "href": "href:142", + "id": "id:143", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:1", + "href": "fake:href:1", + "id": "fake:id:1", + "name": "test-vpc1--vsi2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:5", + "href": "fake:href:5", + "id": "fake:id:5", + "name": "test-vpc1--vsi1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "fake:href:2", + "id": "fake:id:2", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "port_max": 10, + "port_min": 1, + "protocol": "tcp" + }, + { + "direction": "outbound", + "href": "fake:href:3", + "id": "fake:id:3", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.2/31" + }, + "port_max": 20, + "port_min": 1, + "protocol": "tcp" + }, + { + "direction": "outbound", + "href": "fake:href:4", + "id": "fake:id:4", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.4/30" + }, + "port_max": 10, + "port_min": 1, + "protocol": "tcp" + } + ], + "targets": [ + { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi3b", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi3a", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "endpoint_gateways": [], + "instances": [ + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:11:07.000Z", + "crn": "crn:144", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:145", + "id": "id:146", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi2", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:11:07.000Z", + "floating_ips": [], + "href": "href:43", + "id": "id:44", + "name": "ni2", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:1", + "href": "fake:href:1", + "id": "fake:id:1", + "name": "test-vpc1--vsi2" + } + ], + "status": "available", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:52.000Z", + "crn": "crn:157", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:158", + "id": "id:159", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi1", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:52.000Z", + "floating_ips": [ + { + "address": "52.116.129.168", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip" + } + ], + "href": "href:63", + "id": "id:64", + "name": "ni1", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:5", + "href": "fake:href:5", + "id": "fake:id:5", + "name": "test-vpc1--vsi1" + } + ], + "status": "available", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:166", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:167", + "id": "id:168", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3b", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi3b" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:34.000Z", + "crn": "crn:175", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:176", + "id": "id:177", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3a", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi3a" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + } + ], + "virtual_nis": null, + "routing_tables": [ + { + "accept_routes_from": [ + { + "resource_type": "vpn_gateway" + }, + { + "resource_type": "vpn_server" + } + ], + "advertise_routes_to": [], + "created_at": "2024-09-09T09:09:51.000Z", + "href": "href:11", + "id": "id:12", + "is_default": true, + "lifecycle_state": "stable", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table", + "route_direct_link_ingress": false, + "route_internet_ingress": false, + "route_transit_gateway_ingress": false, + "route_vpc_zone_ingress": false, + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "routes": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + } + } + ], + "load_balancers": [], + "transit_connections": null, + "transit_gateways": null, + "iks_clusters": [] +} \ No newline at end of file diff --git a/test/data/optimize_sg_t/conn_spec.json b/test/data/optimize_sg_t/conn_spec.json new file mode 100644 index 00000000..469de1d7 --- /dev/null +++ b/test/data/optimize_sg_t/conn_spec.json @@ -0,0 +1,60 @@ +{ + "externals": { + "e1": "0.0.0.0/31", + "e2": "0.0.0.2/31", + "e3": "0.0.0.4/30" + }, + "required-connections": [ + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "TCP", + "min_destination_port": 1, + "max_destination_port": 10 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e2", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "TCP", + "min_destination_port": 1, + "max_destination_port": 20 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e3", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "TCP", + "min_destination_port": 1, + "max_destination_port": 10 + } + ] + } + ] +} diff --git a/test/data/optimize_sg_t/details.txt b/test/data/optimize_sg_t/details.txt new file mode 100644 index 00000000..f0569c96 --- /dev/null +++ b/test/data/optimize_sg_t/details.txt @@ -0,0 +1,8 @@ +vsi1 --> 0.0.0.0/31 (tcp ports 1-10) +vsi1 --> 0.0.0.2/31 (tcp ports 1-20) +vsi1 --> 0.0.0.4/30 (tcp ports 1-10) + +==================================== + +vsi1 --> 0.0.0.0/29 (tcp ports 1-10) +vsi1 --> 0.0.0.2/31 (tcp ports 1-20) \ No newline at end of file diff --git a/test/data/optimize_sg_t_all/config_object.json b/test/data/optimize_sg_t_all/config_object.json new file mode 100644 index 00000000..45eaa62d --- /dev/null +++ b/test/data/optimize_sg_t_all/config_object.json @@ -0,0 +1,2007 @@ +{ + "collector_version": "0.11.0", + "provider": "ibm", + "vpcs": [ + { + "classic_access": false, + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:1", + "cse_source_ips": [ + { + "ip": { + "address": "10.22.217.112" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "ip": { + "address": "10.12.160.153" + }, + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "ip": { + "address": "10.16.253.223" + }, + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "default_network_acl": { + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail" + }, + "default_routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "default_security_group": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "dns": { + "enable_hub": false, + "resolution_binding_count": 0, + "resolver": { + "servers": [ + { + "address": "161.26.0.10" + }, + { + "address": "161.26.0.11" + } + ], + "type": "system", + "configuration": "default" + } + }, + "health_reasons": null, + "health_state": "ok", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "vpc", + "status": "available", + "region": "us-south", + "address_prefixes": [ + { + "cidr": "10.240.0.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": true, + "href": "href:18", + "id": "id:19", + "is_default": true, + "name": "filling-tasty-bacterium-parlor", + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "cidr": "10.240.64.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:20", + "id": "id:21", + "is_default": true, + "name": "relearn-ragweed-goon-feisty", + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "cidr": "10.240.128.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:22", + "id": "id:23", + "is_default": true, + "name": "unruffled-penknife-snowshoe-ninetieth", + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "tags": [] + } + ], + "subnets": [ + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:51.000Z", + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.20.0/24", + "name": "subnet2", + "network_acl": { + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.20.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:33", + "id": "id:34", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:35", + "id": "id:36", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:37", + "id": "id:38", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:39", + "id": "id:40", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.4", + "auto_delete": true, + "created_at": "2024-09-09T09:11:08.000Z", + "href": "href:41", + "id": "id:42", + "lifecycle_state": "stable", + "name": "startle-percent-embellish-squeegee", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.20.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:45", + "id": "id:46", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.10.0/24", + "name": "subnet1", + "network_acl": { + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.10.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:53", + "id": "id:54", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:55", + "id": "id:56", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:57", + "id": "id:58", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:59", + "id": "id:60", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:52.000Z", + "href": "href:61", + "id": "id:62", + "lifecycle_state": "stable", + "name": "tableware-sprawl-shrivel-popper", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.10.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:65", + "id": "id:66", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 249, + "created_at": "2024-09-09T09:10:18.000Z", + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.30.0/24", + "name": "subnet3", + "network_acl": { + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.30.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:73", + "id": "id:74", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:75", + "id": "id:76", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:77", + "id": "id:78", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:79", + "id": "id:80", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:81", + "id": "id:82", + "lifecycle_state": "stable", + "name": "disallow-oxidant-etching-selection", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.5", + "auto_delete": true, + "created_at": "2024-09-09T09:10:36.000Z", + "href": "href:85", + "id": "id:86", + "lifecycle_state": "stable", + "name": "reheat-joyride-little-overprice", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:89", + "id": "id:90", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + } + ], + "public_gateways": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:30", + "floating_ip": { + "address": "52.118.147.142", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1" + }, + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "public_gateway", + "status": "available", + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "floating_ips": [ + { + "address": "52.116.129.168", + "created_at": "2024-09-09T09:11:31.000Z", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + }, + { + "address": "52.118.147.142", + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway", + "crn": "crn:30" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "network_acls": [ + { + "created_at": "2024-09-09T09:10:15.000Z", + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:99", + "id": "id:100", + "name": "acl2-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:97", + "id": "id:98", + "ip_version": "ipv4", + "name": "acl2-out-1", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:101", + "id": "id:102", + "name": "acl2-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:99", + "id": "id:100", + "ip_version": "ipv4", + "name": "acl2-out-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:103", + "id": "id:104", + "name": "acl2-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:101", + "id": "id:102", + "ip_version": "ipv4", + "name": "acl2-in-1", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:103", + "id": "id:104", + "ip_version": "ipv4", + "name": "acl2-in-2", + "source": "10.240.10.0/24", + "protocol": "all" + } + ], + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:107", + "id": "id:108", + "name": "acl1-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "172.217.22.46/32", + "direction": "outbound", + "href": "href:105", + "id": "id:106", + "ip_version": "ipv4", + "name": "acl1-out-1", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:109", + "id": "id:110", + "name": "acl1-out-3" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "outbound", + "href": "href:107", + "id": "id:108", + "ip_version": "ipv4", + "name": "acl1-out-2", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:111", + "id": "id:112", + "name": "acl1-out-4" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:109", + "id": "id:110", + "ip_version": "ipv4", + "name": "acl1-out-3", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:113", + "id": "id:114", + "name": "acl1-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:111", + "id": "id:112", + "ip_version": "ipv4", + "name": "acl1-out-4", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:115", + "id": "id:116", + "name": "acl1-in-2" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:113", + "id": "id:114", + "ip_version": "ipv4", + "name": "acl1-in-1", + "source": "172.217.22.46/32", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:117", + "id": "id:118", + "name": "acl1-in-3" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:115", + "id": "id:116", + "ip_version": "ipv4", + "name": "acl1-in-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:119", + "id": "id:120", + "name": "acl1-in-4" + }, + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:117", + "id": "id:118", + "ip_version": "ipv4", + "name": "acl1-in-3", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:119", + "id": "id:120", + "ip_version": "ipv4", + "name": "acl1-in-4", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + } + ], + "subnets": [ + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:123", + "id": "id:124", + "name": "acl3-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:121", + "id": "id:122", + "ip_version": "ipv4", + "name": "acl3-out-1", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:125", + "id": "id:126", + "name": "acl3-in-1" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:123", + "id": "id:124", + "ip_version": "ipv4", + "name": "acl3-out-2", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:127", + "id": "id:128", + "name": "acl3-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:125", + "id": "id:126", + "ip_version": "ipv4", + "name": "acl3-in-1", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:127", + "id": "id:128", + "ip_version": "ipv4", + "name": "acl3-in-2", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + } + ], + "subnets": [ + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:131", + "id": "id:132", + "name": "allow-outbound" + }, + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "inbound", + "href": "href:129", + "id": "id:130", + "ip_version": "ipv4", + "name": "allow-inbound", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:131", + "id": "id:132", + "ip_version": "ipv4", + "name": "allow-outbound", + "source": "0.0.0.0/0", + "protocol": "all" + } + ], + "subnets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "security_groups": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:133", + "href": "href:134", + "id": "id:135", + "name": "sg1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "href:136", + "id": "id:137", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "href:138", + "id": "id:139", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "href:140", + "id": "id:141", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "inbound", + "href": "href:142", + "id": "id:143", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:1", + "href": "fake:href:1", + "id": "fake:id:1", + "name": "test-vpc1--vsi2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:5", + "href": "fake:href:5", + "id": "fake:id:5", + "name": "test-vpc1--vsi1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "fake:href:2", + "id": "fake:id:2", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "port_max": 10, + "port_min": 1, + "protocol": "tcp" + }, + { + "direction": "outbound", + "href": "fake:href:3", + "id": "fake:id:3", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.2/31" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "fake:href:4", + "id": "fake:id:4", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.4/30" + }, + "port_max": 10, + "port_min": 1, + "protocol": "tcp" + } + ], + "targets": [ + { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi3b", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi3a", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "endpoint_gateways": [], + "instances": [ + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:11:07.000Z", + "crn": "crn:144", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:145", + "id": "id:146", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi2", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:11:07.000Z", + "floating_ips": [], + "href": "href:43", + "id": "id:44", + "name": "ni2", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:1", + "href": "fake:href:1", + "id": "fake:id:1", + "name": "test-vpc1--vsi2" + } + ], + "status": "available", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:52.000Z", + "crn": "crn:157", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:158", + "id": "id:159", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi1", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:52.000Z", + "floating_ips": [ + { + "address": "52.116.129.168", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip" + } + ], + "href": "href:63", + "id": "id:64", + "name": "ni1", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:5", + "href": "fake:href:5", + "id": "fake:id:5", + "name": "test-vpc1--vsi1" + } + ], + "status": "available", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:166", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:167", + "id": "id:168", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3b", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:6", + "href": "fake:href:6", + "id": "fake:id:6", + "name": "test-vpc1--vsi3b" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:34.000Z", + "crn": "crn:175", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:176", + "id": "id:177", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3a", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi3a" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + } + ], + "virtual_nis": null, + "routing_tables": [ + { + "accept_routes_from": [ + { + "resource_type": "vpn_gateway" + }, + { + "resource_type": "vpn_server" + } + ], + "advertise_routes_to": [], + "created_at": "2024-09-09T09:09:51.000Z", + "href": "href:11", + "id": "id:12", + "is_default": true, + "lifecycle_state": "stable", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table", + "route_direct_link_ingress": false, + "route_internet_ingress": false, + "route_transit_gateway_ingress": false, + "route_vpc_zone_ingress": false, + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "routes": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + } + } + ], + "load_balancers": [], + "transit_connections": null, + "transit_gateways": null, + "iks_clusters": [] +} \ No newline at end of file diff --git a/test/data/optimize_sg_t_all/conn_spec.json b/test/data/optimize_sg_t_all/conn_spec.json new file mode 100644 index 00000000..e4b6b3a9 --- /dev/null +++ b/test/data/optimize_sg_t_all/conn_spec.json @@ -0,0 +1,53 @@ +{ + "externals": { + "e1": "0.0.0.0/31", + "e2": "0.0.0.2/31", + "e3": "0.0.0.4/30" + }, + "required-connections": [ + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e1", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "TCP", + "min_destination_port": 1, + "max_destination_port": 10 + } + ] + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e2", + "type": "external" + } + }, + { + "src": { + "name": "vsi1", + "type": "instance" + }, + "dst": { + "name": "e3", + "type": "external" + }, + "allowed-protocols": [ + { + "protocol": "TCP", + "min_destination_port": 1, + "max_destination_port": 10 + } + ] + } + ] +} diff --git a/test/data/optimize_sg_t_all/details.txt b/test/data/optimize_sg_t_all/details.txt new file mode 100644 index 00000000..0de517d7 --- /dev/null +++ b/test/data/optimize_sg_t_all/details.txt @@ -0,0 +1,8 @@ +vsi1 --> 0.0.0.0/31 (tcp ports 1-10) +vsi1 --> 0.0.0.2/31 (all protocols) +vsi1 --> 0.0.0.4/30 (tcp ports 1-10) + +==================================== + +vsi1 --> 0.0.0.0/29 (tcp ports 1-10) +vsi1 --> 0.0.0.2/31 (all protocols) \ No newline at end of file diff --git a/test/main_test_list.go b/test/main_test_list.go index 57e61c77..e0af4153 100644 --- a/test/main_test_list.go +++ b/test/main_test_list.go @@ -24,6 +24,8 @@ const ( aclTgMultipleConfig = "%s/acl_tg_multiple/config_object.json" aclTgMultipleSpec = "%s/acl_tg_multiple/conn_spec.json" + optimizeSGProtocolsToAllConfig = "%s/optimize_sg_protocols_to_all/config_object.json" + sgProtocolsConfig = "%s/sg_protocols/config_object.json" sgProtocolsSpec = "%s/sg_protocols/conn_spec.json" @@ -34,6 +36,7 @@ const ( sgTgMultipleSpec = "%s/sg_tg_multiple/conn_spec.json" tfOutputFmt = "tf" + vsi1 = "vsi1" ) func allMainTests() []testCase { @@ -311,7 +314,89 @@ func synthSGTestsList() []testCase { } } -// Note: spec files in data folder are used to create the config object files (acl_testing4 config) +// Note1: spec files in data folder are used to create the config object files (acl_testing4 config) +// Note2: each data folder has a details.txt file with the test explanation func optimizeSGTestsLists() []testCase { - return []testCase{} + return []testCase{ + { + testName: "optimize_sg_icmp_codes", + args: &command{ + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_icmp_codes/config_object.json", + outputFile: "%s/optimize_sg_icmp_codes/sg_expected.tf", + firewallName: vsi1, + }, + }, + { + testName: "optimize_sg_icmp_types", + args: &command{ + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_icmp_types/config_object.json", + outputFile: "%s/optimize_sg_icmp_types/sg_expected.tf", + firewallName: vsi1, + }, + }, + { + testName: "optimize_sg_protocols_to_all_tf", + args: &command{ + cmd: optimize, + subcmd: sg, + config: optimizeSGProtocolsToAllConfig, + outputFile: "%s/optimize_sg_protocols_to_all_tf/sg_expected.tf", + firewallName: vsi1, + }, + }, + { + testName: "optimize_sg_protocols_to_all_csv", + args: &command{ + cmd: optimize, + subcmd: sg, + config: optimizeSGProtocolsToAllConfig, + outputFile: "%s/optimize_sg_protocols_to_all_csv/sg_expected.csv", + firewallName: vsi1, + }, + }, + { + testName: "optimize_sg_protocols_to_all_md", + args: &command{ + cmd: optimize, + subcmd: sg, + config: optimizeSGProtocolsToAllConfig, + outputFile: "%s/optimize_sg_protocols_to_all_md/sg_expected.md", + firewallName: vsi1, + }, + }, + { + testName: "optimize_sg_redundant", + args: &command{ + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_redundant/config_object.json", + outputFile: "%s/optimize_sg_redundant/sg_expected.tf", + firewallName: vsi1, + }, + }, + { + testName: "optimize_sg_t", + args: &command{ + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_t/config_object.json", + outputFile: "%s/optimize_sg_t/sg_expected.tf", + firewallName: vsi1, + }, + }, + { + testName: "optimize_sg_t_all", + args: &command{ + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_t_all/config_object.json", + outputFile: "%s/optimize_sg_t_all/sg_expected.tf", + firewallName: vsi1, + }, + }, + } } diff --git a/test/tests_defs.go b/test/tests_defs.go index e5a32ebd..8baea0f4 100644 --- a/test/tests_defs.go +++ b/test/tests_defs.go @@ -35,9 +35,10 @@ const ( defaultDirectoryPermission = 0o755 - synth string = "synth" - acl string = "acl" - sg string = "sg" + synth string = "synth" + optimize string = "optimize" + acl string = "acl" + sg string = "sg" ) func (c *command) Args(dataFolder, resultsFolder string) []string { From 28a55eceefc8fef35eb2483434cd659d7e1aea85 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 30 Sep 2024 16:22:38 +0300 Subject: [PATCH 55/79] wip --- pkg/io/tfio/acl.go | 4 +- pkg/io/tfio/sg.go | 4 +- pkg/optimize/compressRules.go | 9 +- pkg/optimize/sg.go | 76 ++++++---- pkg/optimize/sgRulesToIPToSpan.go | 4 + pkg/optimize/sgRulesToSGToSpan.go | 10 +- pkg/optimize/sgSpanToSGRules.go | 2 +- pkg/utils/utils.go | 8 -- .../optimize_sg_icmp_codes/sg_expected.tf | 68 +++++++++ .../optimize_sg_icmp_types/sg_expected.tf | 67 +++++++++ .../sg_expected.csv | 7 + .../sg_expected.md | 8 ++ .../sg_expected.tf | 78 ++++++++++ .../optimize_sg_redundant/sg_expected.tf | 55 +++++++ test/expected/optimize_sg_t/sg_expected.tf | 76 ++++++++++ .../expected/optimize_sg_t_all/sg_expected.tf | 68 +++++++++ test/main_test.go | 136 +++++++++--------- test/main_test_list.go | 56 ++++---- test/update_test.go | 40 +++--- 19 files changed, 606 insertions(+), 170 deletions(-) create mode 100644 test/expected/optimize_sg_icmp_codes/sg_expected.tf create mode 100644 test/expected/optimize_sg_icmp_types/sg_expected.tf create mode 100644 test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv create mode 100644 test/expected/optimize_sg_protocols_to_all_md/sg_expected.md create mode 100644 test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf create mode 100644 test/expected/optimize_sg_redundant/sg_expected.tf create mode 100644 test/expected/optimize_sg_t/sg_expected.tf create mode 100644 test/expected/optimize_sg_t_all/sg_expected.tf diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index 7f641d3b..d71b8d56 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -65,7 +65,7 @@ func aclRule(rule *ir.ACLRule, name string) (tf.Block, error) { {Name: "destination", Value: quote(rule.Destination.String())}, } - comment := "" + comment := "\n" if rule.Explanation != "" { comment = fmt.Sprintf("# %v", rule.Explanation) } @@ -109,7 +109,7 @@ func aclCollection(t *ir.ACLCollection, vpc string) (*tf.ConfigFile, error) { var acls = make([]tf.Block, len(sortedACLs)) i := 0 for _, subnet := range sortedACLs { - comment := "" + comment := "\n" vpcName := ir.VpcFromScopedResource(subnet) acl := t.ACLs[vpcName][subnet] if len(sortedACLs) > 1 { // not a single nacl diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 793c5c7a..dafcaa6d 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -93,8 +93,8 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { func sg(sgName, vpcName string) (tf.Block, error) { tfSGName := ir.ChangeScoping(sgName) comment := fmt.Sprintf("\n### SG attached to %s", sgName) - if sgName == tfSGName { // its optimization - comment = "" + if sgName == tfSGName { // optimization mode + comment = "\n" } if err := verifyName(tfSGName); err != nil { return tf.Block{}, err diff --git a/pkg/optimize/compressRules.go b/pkg/optimize/compressRules.go index 67757fc8..6f9bb4d8 100644 --- a/pkg/optimize/compressRules.go +++ b/pkg/optimize/compressRules.go @@ -7,7 +7,6 @@ package optimize import ( "github.com/np-guard/models/pkg/netset" - "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) func compressSpansToSG(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { @@ -18,9 +17,9 @@ func compressSpansToSG(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { // delete other protocols rules if all protocol rule exists func deleteOtherProtocolIfAllProtocolExists(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { for _, sgName := range spans.all { - delete(spans.tcp, *sgName) - delete(spans.udp, *sgName) - delete(spans.icmp, *sgName) + delete(spans.tcp, sgName) + delete(spans.udp, sgName) + delete(spans.icmp, sgName) } return spans } @@ -34,7 +33,7 @@ func compressThreeProtocolsToAllProtocol(spans *sgSpansToSGPerProtocol) *sgSpans delete(spans.tcp, sgName) delete(spans.udp, sgName) delete(spans.icmp, sgName) - spans.all = append(spans.all, utils.Ptr(sgName)) + spans.all = append(spans.all, sgName) } } } diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index 35092850..fc39861e 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0 package optimize import ( + "fmt" "log" "github.com/np-guard/models/pkg/ds" @@ -40,7 +41,7 @@ type ( tcp map[ir.SGName]*interval.CanonicalSet udp map[ir.SGName]*interval.CanonicalSet icmp map[ir.SGName]*netset.ICMPSet - all []*ir.SGName + all []ir.SGName } sgSpansToIPPerProtocol struct { @@ -71,42 +72,57 @@ func (s *SGOptimizer) VpcNames() []string { } // Optimize attempts to reduce the number of SG rules -// the algorithm attempts to reduce both inbound and outbound rules separately -// A message is printed to the log at the end of the algorithm +// if -n was supplied, it will attempt to reduce the number of rules only in it +// otherwise, it will attempt to reduce the number of rules in all SGs func (s *SGOptimizer) Optimize() (ir.Collection, error) { - for vpcName := range s.sgCollection.SGs { - var sg *ir.SG - var ok bool - if sg, ok = s.sgCollection.SGs[vpcName][s.sgName]; !ok { - continue + if s.sgName != "" { + for _, vpcName := range utils.SortedMapKeys(s.sgCollection.SGs) { + if _, ok := s.sgCollection.SGs[vpcName][s.sgName]; ok { + s.OptimizeSG(vpcName, s.sgName) + return s.sgCollection, nil + } } - reducedRules := 0 + return nil, fmt.Errorf("could no find %s sg", s.sgName) + } - // reduce inbound rules first - newInboundRules := s.reduceSGRules(sg.InboundRules, ir.Inbound) - if len(sg.InboundRules) > len(newInboundRules) { - reducedRules += len(sg.InboundRules) - len(newInboundRules) - s.sgCollection.SGs[vpcName][s.sgName].InboundRules = newInboundRules + for _, vpcName := range utils.SortedMapKeys(s.sgCollection.SGs) { + for _, sgName := range utils.SortedMapKeys(s.sgCollection.SGs[vpcName]) { + s.OptimizeSG(vpcName, sgName) } + } + return s.sgCollection, nil +} - // reduce outbound rules second - newOutboundRules := s.reduceSGRules(sg.OutboundRules, ir.Outbound) - if len(sg.OutboundRules) > len(newOutboundRules) { - reducedRules += len(sg.OutboundRules) - len(newOutboundRules) - s.sgCollection.SGs[vpcName][s.sgName].OutboundRules = newOutboundRules - } +// Optimize attempts to reduce the number of SG rules +// the algorithm attempts to reduce both inbound and outbound rules separately +// A message is printed to the log at the end of the algorithm +func (s *SGOptimizer) OptimizeSG(vpcName string, sgName ir.SGName) { + sg := s.sgCollection.SGs[vpcName][sgName] + reducedRules := 0 + + // reduce inbound rules first + newInboundRules := s.reduceSGRules(sg.InboundRules, ir.Inbound) + if len(sg.InboundRules) > len(newInboundRules) { + reducedRules += len(sg.InboundRules) - len(newInboundRules) + s.sgCollection.SGs[vpcName][sgName].InboundRules = newInboundRules + } - // print a message to the log - switch { - case reducedRules == 0: - log.Printf("no rules were reduced in sg %s", string(s.sgName)) - case reducedRules == 1: - log.Printf("1 rule was reduced in sg %s", string(s.sgName)) - default: - log.Printf("%d rules were reduced in sg %s", reducedRules, string(s.sgName)) - } + // reduce outbound rules second + newOutboundRules := s.reduceSGRules(sg.OutboundRules, ir.Outbound) + if len(sg.OutboundRules) > len(newOutboundRules) { + reducedRules += len(sg.OutboundRules) - len(newOutboundRules) + s.sgCollection.SGs[vpcName][sgName].OutboundRules = newOutboundRules + } + + // print a message to the log + switch { + case reducedRules == 0: + log.Printf("no rules were reduced in sg %s\n", string(sgName)) + case reducedRules == 1: + log.Printf("1 rule was reduced in sg %s\n", string(sgName)) + default: + log.Printf("%d rules were reduced in sg %s\n", reducedRules, string(sgName)) } - return s.sgCollection, nil } // reduceSGRules attempts to reduce the number of rules with different remote types separately diff --git a/pkg/optimize/sgRulesToIPToSpan.go b/pkg/optimize/sgRulesToIPToSpan.go index ed8611fa..af994076 100644 --- a/pkg/optimize/sgRulesToIPToSpan.go +++ b/pkg/optimize/sgRulesToIPToSpan.go @@ -104,10 +104,13 @@ func updateSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleSet T, ruleIP *nets // b. the non overlapping part will enter the new map with the same value he had. func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlock, ruleSet T) (s, res map[*netset.IPBlock]T) { res = make(map[*netset.IPBlock]T, 0) + uncovered := ruleIP.Copy() for ipblock := range span { if !ipblock.Overlap(ruleIP) { continue } + uncovered = uncovered.Subtract(ipblock) + overlappingIPs := ruleIP.Subtract(ipblock) for _, ip := range overlappingIPs.Split() { res[ip] = span[ipblock].Copy().Union(ruleSet) @@ -118,5 +121,6 @@ func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlo } delete(span, ipblock) } + res[uncovered] = ruleSet.Copy() return span, res } diff --git a/pkg/optimize/sgRulesToSGToSpan.go b/pkg/optimize/sgRulesToSGToSpan.go index 7e780a81..d71c6df8 100644 --- a/pkg/optimize/sgRulesToSGToSpan.go +++ b/pkg/optimize/sgRulesToSGToSpan.go @@ -6,6 +6,8 @@ SPDX-License-Identifier: Apache-2.0 package optimize import ( + "fmt" + "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" @@ -46,17 +48,19 @@ func icmpRulesToSGToSpan(rules []*ir.SGRule) map[ir.SGName]*netset.ICMPSet { if result[remote] == nil { result[remote] = netset.EmptyICMPSet() } - result[remote].Union(netset.NewICMPSet(p)) + result[remote] = result[remote].Union(netset.NewICMPSet(p)) + + fmt.Println("i=", i, ": num partitions=", len(result[remote].Partitions())) } return result } // all protocol rules to a span of SG names slice -func allProtocolRulesToSGToSpan(rules []*ir.SGRule) []*ir.SGName { +func allProtocolRulesToSGToSpan(rules []*ir.SGRule) []ir.SGName { result := make(map[ir.SGName]struct{}) for i := range rules { remote := rules[i].Remote.(ir.SGName) result[remote] = struct{}{} } - return utils.ToPtrSlice(utils.SortedMapKeys(result)) + return utils.SortedMapKeys(result) } diff --git a/pkg/optimize/sgSpanToSGRules.go b/pkg/optimize/sgSpanToSGRules.go index 0eb66ab1..b3cc640d 100644 --- a/pkg/optimize/sgSpanToSGRules.go +++ b/pkg/optimize/sgSpanToSGRules.go @@ -38,7 +38,7 @@ func icmpSGSpanToSGRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direct } // span (slice of SGs) to SG rules -func protocolAllSGSpanToSGRules(span []*ir.SGName, direction ir.Direction) []*ir.SGRule { +func protocolAllSGSpanToSGRules(span []ir.SGName, direction ir.Direction) []*ir.SGRule { result := make([]*ir.SGRule, len(span)) for i, sgName := range span { result[i] = ir.NewSGRule(direction, sgName, netp.AnyProtocol{}, netset.GetCidrAll(), "") diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index c867fc55..e3923aa5 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -50,14 +50,6 @@ func Int64PointerToIntPointer(v *int64) *int { return Ptr(int(*v)) } -func ToPtrSlice[T any](s []T) []*T { - res := make([]*T, len(s)) - for i := range s { - res[i] = Ptr(s[i]) - } - return res -} - // m1 does not have any key of m2 func MergeSetMaps[T comparable, K ds.Set[K]](m1, m2 map[T]K) map[T]K { for key, val := range m2 { diff --git a/test/expected/optimize_sg_icmp_codes/sg_expected.tf b/test/expected/optimize_sg_icmp_codes/sg_expected.tf new file mode 100644 index 00000000..41db042e --- /dev/null +++ b/test/expected/optimize_sg_icmp_codes/sg_expected.tf @@ -0,0 +1,68 @@ +resource "ibm_is_security_group" "sg1" { + name = "sg-sg1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi1" { + name = "sg-test-vpc1--vsi1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = ibm_is_security_group.test-vpc1--vsi2.id + icmp { + type = 5 + } +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/31" + icmp { + } +} + + +resource "ibm_is_security_group" "test-vpc1--vsi2" { + name = "sg-test-vpc1--vsi2" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { + group = ibm_is_security_group.test-vpc1--vsi2.id + direction = "inbound" + remote = ibm_is_security_group.test-vpc1--vsi1.id + icmp { + type = 5 + } +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3a" { + name = "sg-test-vpc1--vsi3a" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3b" { + name = "sg-test-vpc1--vsi3b" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { + name = "sg-wombat-hesitate-scorn-subprime" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "inbound" + remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id +} diff --git a/test/expected/optimize_sg_icmp_types/sg_expected.tf b/test/expected/optimize_sg_icmp_types/sg_expected.tf new file mode 100644 index 00000000..2795bc56 --- /dev/null +++ b/test/expected/optimize_sg_icmp_types/sg_expected.tf @@ -0,0 +1,67 @@ +resource "ibm_is_security_group" "sg1" { + name = "sg-sg1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi1" { + name = "sg-test-vpc1--vsi1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = ibm_is_security_group.test-vpc1--vsi2.id + icmp { + } +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/31" + icmp { + type = 0 + } +} + + +resource "ibm_is_security_group" "test-vpc1--vsi2" { + name = "sg-test-vpc1--vsi2" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { + group = ibm_is_security_group.test-vpc1--vsi2.id + direction = "inbound" + remote = ibm_is_security_group.test-vpc1--vsi1.id + icmp { + } +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3a" { + name = "sg-test-vpc1--vsi3a" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3b" { + name = "sg-test-vpc1--vsi3b" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { + name = "sg-wombat-hesitate-scorn-subprime" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "inbound" + remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id +} diff --git a/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv b/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv new file mode 100644 index 00000000..773f874b --- /dev/null +++ b/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv @@ -0,0 +1,7 @@ +SG,Direction,Remote type,Remote,Protocol,Protocol params,Description +test-vpc1--vsi1,Outbound,Security group,test-vpc1--vsi2,ALL,, +test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,TCP,ports 1-1, +test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,UDP,ports 1-1, +test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,ICMP,"Type: Any, Code: Any", +test-vpc1--vsi2,Inbound,Security group,test-vpc1--vsi1,ALL,, +wombat-hesitate-scorn-subprime,Inbound,Security group,wombat-hesitate-scorn-subprime,ALL,, diff --git a/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md b/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md new file mode 100644 index 00000000..4fdc42e0 --- /dev/null +++ b/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md @@ -0,0 +1,8 @@ + | SG | Direction | Remote type | Remote | Protocol | Protocol params | Description | + | :--- | :--- | :--- | :--- | :--- | :--- | :--- | + | test-vpc1--vsi1 | Outbound | Security group | test-vpc1--vsi2 | ALL | | | + | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | TCP | ports 1-1 | | + | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | UDP | ports 1-1 | | + | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | ICMP | Type: Any, Code: Any | | + | test-vpc1--vsi2 | Inbound | Security group | test-vpc1--vsi1 | ALL | | | + | wombat-hesitate-scorn-subprime | Inbound | Security group | wombat-hesitate-scorn-subprime | ALL | | | diff --git a/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf new file mode 100644 index 00000000..d8324ff5 --- /dev/null +++ b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf @@ -0,0 +1,78 @@ +resource "ibm_is_security_group" "sg1" { + name = "sg-sg1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi1" { + name = "sg-test-vpc1--vsi1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = ibm_is_security_group.test-vpc1--vsi2.id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/31" + tcp { + port_max = 1 + } +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-2" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/31" + udp { + port_max = 1 + } +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-3" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/31" + icmp { + } +} + + +resource "ibm_is_security_group" "test-vpc1--vsi2" { + name = "sg-test-vpc1--vsi2" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { + group = ibm_is_security_group.test-vpc1--vsi2.id + direction = "inbound" + remote = ibm_is_security_group.test-vpc1--vsi1.id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3a" { + name = "sg-test-vpc1--vsi3a" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3b" { + name = "sg-test-vpc1--vsi3b" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { + name = "sg-wombat-hesitate-scorn-subprime" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "inbound" + remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id +} diff --git a/test/expected/optimize_sg_redundant/sg_expected.tf b/test/expected/optimize_sg_redundant/sg_expected.tf new file mode 100644 index 00000000..15bd1e64 --- /dev/null +++ b/test/expected/optimize_sg_redundant/sg_expected.tf @@ -0,0 +1,55 @@ +resource "ibm_is_security_group" "sg1" { + name = "sg-sg1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi1" { + name = "sg-test-vpc1--vsi1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = ibm_is_security_group.test-vpc1--vsi2.id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi2" { + name = "sg-test-vpc1--vsi2" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { + group = ibm_is_security_group.test-vpc1--vsi2.id + direction = "inbound" + remote = ibm_is_security_group.test-vpc1--vsi1.id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3a" { + name = "sg-test-vpc1--vsi3a" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3b" { + name = "sg-test-vpc1--vsi3b" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { + name = "sg-wombat-hesitate-scorn-subprime" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "inbound" + remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id +} diff --git a/test/expected/optimize_sg_t/sg_expected.tf b/test/expected/optimize_sg_t/sg_expected.tf new file mode 100644 index 00000000..32fd2e3b --- /dev/null +++ b/test/expected/optimize_sg_t/sg_expected.tf @@ -0,0 +1,76 @@ +resource "ibm_is_security_group" "sg1" { + name = "sg-sg1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "sg1-0" { + group = ibm_is_security_group.sg1.id + direction = "inbound" + remote = "0.0.0.0/0" +} +resource "ibm_is_security_group_rule" "sg1-1" { + group = ibm_is_security_group.sg1.id + direction = "outbound" + remote = "0.0.0.0/0" +} + + +resource "ibm_is_security_group" "test-vpc1--vsi1" { + name = "sg-test-vpc1--vsi1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/30" + tcp { + port_max = 1 + } +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.2/31" + tcp { + port_max = 1 + } +} + + +resource "ibm_is_security_group" "test-vpc1--vsi2" { + name = "sg-test-vpc1--vsi2" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3a" { + name = "sg-test-vpc1--vsi3a" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3b" { + name = "sg-test-vpc1--vsi3b" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { + name = "sg-wombat-hesitate-scorn-subprime" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "inbound" + remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-1" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "outbound" + remote = "0.0.0.0/0" +} diff --git a/test/expected/optimize_sg_t_all/sg_expected.tf b/test/expected/optimize_sg_t_all/sg_expected.tf new file mode 100644 index 00000000..f932cb58 --- /dev/null +++ b/test/expected/optimize_sg_t_all/sg_expected.tf @@ -0,0 +1,68 @@ +resource "ibm_is_security_group" "sg1" { + name = "sg-sg1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "sg1-0" { + group = ibm_is_security_group.sg1.id + direction = "inbound" + remote = "0.0.0.0/0" +} +resource "ibm_is_security_group_rule" "sg1-1" { + group = ibm_is_security_group.sg1.id + direction = "outbound" + remote = "0.0.0.0/0" +} + + +resource "ibm_is_security_group" "test-vpc1--vsi1" { + name = "sg-test-vpc1--vsi1" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/29" + tcp { + port_max = 1 + } +} + + +resource "ibm_is_security_group" "test-vpc1--vsi2" { + name = "sg-test-vpc1--vsi2" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3a" { + name = "sg-test-vpc1--vsi3a" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "test-vpc1--vsi3b" { + name = "sg-test-vpc1--vsi3b" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} + + +resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { + name = "sg-wombat-hesitate-scorn-subprime" + resource_group = local.sg_synth_resource_group_id + vpc = local.sg_synth_test-vpc1_id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "inbound" + remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id +} +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-1" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "outbound" + remote = "0.0.0.0/0" +} diff --git a/test/main_test.go b/test/main_test.go index aabe832d..998995de 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -5,84 +5,84 @@ SPDX-License-Identifier: Apache-2.0 package test -import ( - "os" - "path/filepath" - "regexp" - "strings" - "testing" +// import ( +// "os" +// "path/filepath" +// "regexp" +// "strings" +// "testing" - "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" -) +// "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" +// ) -func TestMain(t *testing.T) { - for _, tt := range allMainTests() { - t.Run(tt.testName, func(t *testing.T) { - // create a sub folder - if err := os.MkdirAll(filepath.Join(resultsFolder, tt.testName), defaultDirectoryPermission); err != nil { - t.Fatalf("Bad test %s; error creating folder for results: %v", tt.testName, err) - } +// func TestMain(t *testing.T) { +// for _, tt := range allMainTests() { +// t.Run(tt.testName, func(t *testing.T) { +// // create a sub folder +// if err := os.MkdirAll(filepath.Join(resultsFolder, tt.testName), defaultDirectoryPermission); err != nil { +// t.Fatalf("Bad test %s; error creating folder for results: %v", tt.testName, err) +// } - // run command - if err := subcmds.Main(tt.args.Args(dataFolder, resultsFolder)); err != nil { - t.Fatalf("Bad test %s; unexpected err: %v", tt.testName, err) - } +// // run command +// if err := subcmds.Main(tt.args.Args(dataFolder, resultsFolder)); err != nil { +// t.Fatalf("Bad test %s; unexpected err: %v", tt.testName, err) +// } - // compare results - compareTestResults(t, tt.testName) - }) - } - removeGeneratedFiles() -} +// // compare results +// compareTestResults(t, tt.testName) +// }) +// } +// removeGeneratedFiles() +// } -func compareTestResults(t *testing.T, testName string) { - expectedSubDirPath := filepath.Join(expectedFolder, testName) - expectedDirFiles := readDir(t, expectedSubDirPath) - expectedFileNames := strings.Join(expectedDirFiles, ", ") +// func compareTestResults(t *testing.T, testName string) { +// expectedSubDirPath := filepath.Join(expectedFolder, testName) +// expectedDirFiles := readDir(t, expectedSubDirPath) +// expectedFileNames := strings.Join(expectedDirFiles, ", ") - resultsSubDirPath := filepath.Join(resultsFolder, testName) - resultsDirFiles := readDir(t, resultsSubDirPath) - resultsFileNames := strings.Join(resultsDirFiles, ", ") +// resultsSubDirPath := filepath.Join(resultsFolder, testName) +// resultsDirFiles := readDir(t, resultsSubDirPath) +// resultsFileNames := strings.Join(resultsDirFiles, ", ") - if len(expectedDirFiles) != len(resultsDirFiles) { - t.Fatalf("Bad test: %s; incorrect number of files created.\nexpected: %s\ngot: %s", testName, expectedFileNames, resultsFileNames) - } +// if len(expectedDirFiles) != len(resultsDirFiles) { +// t.Fatalf("Bad test: %s; incorrect number of files created.\nexpected: %s\ngot: %s", testName, expectedFileNames, resultsFileNames) +// } - for _, file := range expectedDirFiles { - if readFile(t, filepath.Join(expectedSubDirPath, file), testName) != readFile(t, filepath.Join(resultsSubDirPath, file), testName) { - t.Fatalf("Bad test %s; The %s file is different than expected", testName, file) - } - } -} +// for _, file := range expectedDirFiles { +// if readFile(t, filepath.Join(expectedSubDirPath, file), testName) != readFile(t, filepath.Join(resultsSubDirPath, file), testName) { +// t.Fatalf("Bad test %s; The %s file is different than expected", testName, file) +// } +// } +// } -func readDir(t *testing.T, dirName string) []string { - entries, err := os.ReadDir(dirName) - if err != nil { - t.Fatalf("Bad test %s; error reading folder: %s", dirName, err) - } +// func readDir(t *testing.T, dirName string) []string { +// entries, err := os.ReadDir(dirName) +// if err != nil { +// t.Fatalf("Bad test %s; error reading folder: %s", dirName, err) +// } - result := make([]string, len(entries)) - for i := range entries { - result[i] = entries[i].Name() - } - return result -} +// result := make([]string, len(entries)) +// for i := range entries { +// result[i] = entries[i].Name() +// } +// return result +// } -func readFile(t *testing.T, file, testName string) string { - buf, err := os.ReadFile(file) - if err != nil { - t.Fatalf("Bad test: %s; error reading file %s: %v", testName, file, err) - } - return shrinkWhitespace(string(buf)) -} +// func readFile(t *testing.T, file, testName string) string { +// buf, err := os.ReadFile(file) +// if err != nil { +// t.Fatalf("Bad test: %s; error reading file %s: %v", testName, file, err) +// } +// return shrinkWhitespace(string(buf)) +// } -func shrinkWhitespace(s string) string { - return regexp.MustCompile(`[ \t]+`).ReplaceAllString(s, " ") -} +// func shrinkWhitespace(s string) string { +// return regexp.MustCompile(`[ \t]+`).ReplaceAllString(s, " ") +// } -func removeGeneratedFiles() { - err := os.RemoveAll(resultsFolder) - if err != nil { - panic(err) - } -} +// func removeGeneratedFiles() { +// err := os.RemoveAll(resultsFolder) +// if err != nil { +// panic(err) +// } +// } diff --git a/test/main_test_list.go b/test/main_test_list.go index e0af4153..a2f0982c 100644 --- a/test/main_test_list.go +++ b/test/main_test_list.go @@ -36,7 +36,7 @@ const ( sgTgMultipleSpec = "%s/sg_tg_multiple/conn_spec.json" tfOutputFmt = "tf" - vsi1 = "vsi1" + vsi1 = "test-vpc1--vsi1" ) func allMainTests() []testCase { @@ -321,61 +321,55 @@ func optimizeSGTestsLists() []testCase { { testName: "optimize_sg_icmp_codes", args: &command{ - cmd: optimize, - subcmd: sg, - config: "%s/optimize_sg_icmp_codes/config_object.json", - outputFile: "%s/optimize_sg_icmp_codes/sg_expected.tf", - firewallName: vsi1, + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_icmp_codes/config_object.json", + outputFile: "%s/optimize_sg_icmp_codes/sg_expected.tf", }, }, { testName: "optimize_sg_icmp_types", args: &command{ - cmd: optimize, - subcmd: sg, - config: "%s/optimize_sg_icmp_types/config_object.json", - outputFile: "%s/optimize_sg_icmp_types/sg_expected.tf", - firewallName: vsi1, + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_icmp_types/config_object.json", + outputFile: "%s/optimize_sg_icmp_types/sg_expected.tf", }, }, { testName: "optimize_sg_protocols_to_all_tf", args: &command{ - cmd: optimize, - subcmd: sg, - config: optimizeSGProtocolsToAllConfig, - outputFile: "%s/optimize_sg_protocols_to_all_tf/sg_expected.tf", - firewallName: vsi1, + cmd: optimize, + subcmd: sg, + config: optimizeSGProtocolsToAllConfig, + outputFile: "%s/optimize_sg_protocols_to_all_tf/sg_expected.tf", }, }, { testName: "optimize_sg_protocols_to_all_csv", args: &command{ - cmd: optimize, - subcmd: sg, - config: optimizeSGProtocolsToAllConfig, - outputFile: "%s/optimize_sg_protocols_to_all_csv/sg_expected.csv", - firewallName: vsi1, + cmd: optimize, + subcmd: sg, + config: optimizeSGProtocolsToAllConfig, + outputFile: "%s/optimize_sg_protocols_to_all_csv/sg_expected.csv", }, }, { testName: "optimize_sg_protocols_to_all_md", args: &command{ - cmd: optimize, - subcmd: sg, - config: optimizeSGProtocolsToAllConfig, - outputFile: "%s/optimize_sg_protocols_to_all_md/sg_expected.md", - firewallName: vsi1, + cmd: optimize, + subcmd: sg, + config: optimizeSGProtocolsToAllConfig, + outputFile: "%s/optimize_sg_protocols_to_all_md/sg_expected.md", }, }, { testName: "optimize_sg_redundant", args: &command{ - cmd: optimize, - subcmd: sg, - config: "%s/optimize_sg_redundant/config_object.json", - outputFile: "%s/optimize_sg_redundant/sg_expected.tf", - firewallName: vsi1, + cmd: optimize, + subcmd: sg, + config: "%s/optimize_sg_redundant/config_object.json", + outputFile: "%s/optimize_sg_redundant/sg_expected.tf", }, }, { diff --git a/test/update_test.go b/test/update_test.go index 209921cf..7687fabe 100644 --- a/test/update_test.go +++ b/test/update_test.go @@ -5,26 +5,26 @@ SPDX-License-Identifier: Apache-2.0 package test -// import ( -// "os" -// "path/filepath" -// "testing" +import ( + "os" + "path/filepath" + "testing" -// "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" -// ) + "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" +) -// func TestUpdate(t *testing.T) { -// for _, tt := range allMainTests() { -// t.Run(tt.testName, func(t *testing.T) { -// // create a sub folder -// if err := os.MkdirAll(filepath.Join(expectedFolder, tt.testName), defaultDirectoryPermission); err != nil { -// t.Errorf("Bad test %s: %s", tt.testName, err) -// } +func TestUpdate(t *testing.T) { + for _, tt := range allMainTests() { + t.Run(tt.testName, func(t *testing.T) { + // create a sub folder + if err := os.MkdirAll(filepath.Join(expectedFolder, tt.testName), defaultDirectoryPermission); err != nil { + t.Errorf("Bad test %s: %s", tt.testName, err) + } -// err := subcmds.Main(tt.args.Args(dataFolder, expectedFolder)) -// if err != nil { -// t.Errorf("Bad test %s: %s", tt.testName, err) -// } -// }) -// } -// } + err := subcmds.Main(tt.args.Args(dataFolder, expectedFolder)) + if err != nil { + t.Errorf("Bad test %s: %s", tt.testName, err) + } + }) + } +} From 4919d003da77eb6511bde04412a60fad5afd55a3 Mon Sep 17 00:00:00 2001 From: Yair Slobodin <154875779+YairSlobodin1@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:52:05 +0300 Subject: [PATCH 56/79] Read sgs (#192) --- pkg/io/confio/parse_sgs.go | 178 ++++++++++++++++++++++++++++++++++++- pkg/ir/sg.go | 2 + pkg/utils/utils.go | 16 ++++ 3 files changed, 194 insertions(+), 2 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index b7892297..91853903 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -5,8 +5,182 @@ SPDX-License-Identifier: Apache-2.0 package confio -import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +import ( + "fmt" + "log" + "github.com/IBM/vpc-go-sdk/vpcv1" + + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" +) + +// ReadSG translates SGs from a config_object file to map[ir.SGName]*SG func ReadSGs(filename string) (*ir.SGCollection, error) { - return nil, nil + config, err := readModel(filename) + if err != nil { + return nil, err + } + + result := ir.NewSGCollection() + for i, sg := range config.SecurityGroupList { + inbound, outbound, err := translateSGRules(&sg.SecurityGroup) + if err != nil { + return nil, err + } + if sg.Name == nil || sg.VPC == nil || sg.VPC.Name == nil { + log.Printf("Warning: missing SG/VPC name in sg at index %d\n", i) + continue + } + vpcName := *sg.VPC.Name + if result.SGs[vpcName] == nil { + result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) + } + result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} + } + return result, nil +} + +// parse security rules, splitted into ingress and egress rules +func translateSGRules(sg *vpcv1.SecurityGroup) (ingressRules, egressRules []*ir.SGRule, err error) { + for index := range sg.Rules { + rule, err := translateSGRule(sg, index) + if err != nil { + return nil, nil, err + } + if rule.Direction == ir.Inbound { + ingressRules = append(ingressRules, rule) + } else { + egressRules = append(egressRules, rule) + } + } + return ingressRules, egressRules, nil +} + +// translateSGRule translates a security group rule to ir.SGRule +func translateSGRule(sg *vpcv1.SecurityGroup, index int) (sgRule *ir.SGRule, err error) { + switch r := sg.Rules[index].(type) { + case *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll: + return translateSGRuleProtocolAll(r) + case *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp: + return translateSGRuleProtocolTCPUDP(r) + case *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp: + return translateSGRuleProtocolIcmp(r) + } + return nil, fmt.Errorf("error parsing rule number %d in sg %s in VPC %s", index, *sg.Name, *sg.VPC.Name) +} + +func translateSGRuleProtocolAll(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll) (sgRule *ir.SGRule, err error) { + direction, err := translateDirection(*rule.Direction) + if err != nil { + return nil, err + } + remote, err := translateRemote(rule.Remote) + if err != nil { + return nil, err + } + local, err := translateLocal(rule.Local) + if err != nil { + return nil, err + } + return &ir.SGRule{Direction: direction, Remote: remote, Protocol: netp.AnyProtocol{}, Local: local}, nil +} + +func translateSGRuleProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (sgRule *ir.SGRule, err error) { + direction, err := translateDirection(*rule.Direction) + if err != nil { + return nil, err + } + remote, err := translateRemote(rule.Remote) + if err != nil { + return nil, err + } + local, err := translateLocal(rule.Local) + if err != nil { + return nil, err + } + protocol, err := translateProtocolTCPUDP(rule) + if err != nil { + return nil, err + } + return &ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil +} + +func translateSGRuleProtocolIcmp(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp) (sgRule *ir.SGRule, err error) { + direction, err := translateDirection(*rule.Direction) + if err != nil { + return nil, err + } + remote, err := translateRemote(rule.Remote) + if err != nil { + return nil, err + } + local, err := translateLocal(rule.Local) + if err != nil { + return nil, err + } + protocol, err := netp.ICMPFromTypeAndCode64(rule.Type, rule.Code) + if err != nil { + return nil, err + } + return &ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil +} + +func translateDirection(direction string) (ir.Direction, error) { + if direction == "inbound" { + return ir.Inbound, nil + } else if direction == "outbound" { + return ir.Outbound, nil + } + return ir.Inbound, fmt.Errorf("SG rule direction must be either inbound or outbound") +} + +func translateRemote(remote vpcv1.SecurityGroupRuleRemoteIntf) (ir.RemoteType, error) { + if r, ok := remote.(*vpcv1.SecurityGroupRuleRemote); ok { + switch { + case r.CIDRBlock != nil: + return netset.IPBlockFromCidr(*r.CIDRBlock) + case r.Address != nil: + return netset.IPBlockFromIPAddress(*r.Address) + case r.Name != nil: + return ir.SGName(*r.Name), nil + } + } + return nil, fmt.Errorf("unexpected SG rule remote") +} + +func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, error) { + var err error + var ipAddrs *netset.IPBlock + if l, ok := local.(*vpcv1.SecurityGroupRuleLocal); ok { + if l.CIDRBlock != nil { + ipAddrs, err = netset.IPBlockFromCidr(*l.CIDRBlock) + } + if l.Address != nil { + ipAddrs, err = netset.IPBlockFromIPAddress(*l.CIDRBlock) + } + if err != nil { + return nil, err + } + return verifyLocalValue(ipAddrs) + } + return nil, fmt.Errorf("error parsing Local field") +} + +// temporary - first version of optimization requires local = 0.0.0.0/32 +func verifyLocalValue(ipAddrs *netset.IPBlock) (*netset.IPBlock, error) { + if !ipAddrs.Equal(netset.GetCidrAll()) { + return nil, fmt.Errorf("only 0.0.0.0/32 CIDR block is supported for local values") + } + return ipAddrs, nil +} + +func translateProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (netp.Protocol, error) { + isTCP := *rule.Protocol == vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudpProtocolTCPConst + minDstPort := utils.GetProperty(rule.PortMin, netp.MinPort) + maxDstPort := utils.GetProperty(rule.PortMax, netp.MaxPort) + return netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(minDstPort), int(maxDstPort)) } diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 0011b011..e90538d5 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -10,6 +10,7 @@ import ( "reflect" "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) @@ -40,6 +41,7 @@ type SGRule struct { Direction Direction Remote RemoteType Protocol netp.Protocol + Local *netset.IPBlock Explanation string } diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index acf9e3d2..ede1bb67 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -31,3 +31,19 @@ func SortedAllInnerMapsKeys[T, K cmp.Ordered, V any](m map[K]map[T]V) []T { slices.Sort(keys) return keys } + +// GetProperty returns pointer p if it is valid, else it returns the provided default value +// used to get min/max port or icmp type +func GetProperty(p *int64, defaultP int64) int64 { + if p == nil { + return defaultP + } + return *p +} + +func Int64PointerToIntPointer(v *int64) *int { + if v == nil { + return nil + } + return Ptr(int(*v)) +} From 2de0e771a168ecfe5ca8fcdaffd7e7307b84b732 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 1 Oct 2024 19:17:22 +0300 Subject: [PATCH 57/79] wip --- pkg/optimize/compressRules.go | 2 +- pkg/optimize/sg.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/optimize/compressRules.go b/pkg/optimize/compressRules.go index 6f9bb4d8..687ed963 100644 --- a/pkg/optimize/compressRules.go +++ b/pkg/optimize/compressRules.go @@ -43,7 +43,7 @@ func compressThreeProtocolsToAllProtocol(spans *sgSpansToSGPerProtocol) *sgSpans // observation: It pays to switch to all protocol rule when we have rules that cover all other protocols // on exactly the same cidr (only one protocol can exceed). -func compressToAllProtocolRule(span *sgSpansToIPPerProtocol) *sgSpansToIPPerProtocol { +func compressSpansToIP(span *sgSpansToIPPerProtocol) *sgSpansToIPPerProtocol { t := 0 u := 0 i := 0 diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index fc39861e..b30df27f 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -160,7 +160,7 @@ func reduceSGRulesToSG(spans *sgSpansToSGPerProtocol, direction ir.Direction) [] } func reduceSGRulesToIPAddrs(spans *sgSpansToIPPerProtocol, direction ir.Direction) []*ir.SGRule { - spans = compressToAllProtocolRule(spans) + spans = compressSpansToIP(spans) // spans to SG rules tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) From 02cae44c748a332434c595ad4e89d1032f7fd581 Mon Sep 17 00:00:00 2001 From: Yair Slobodin <154875779+YairSlobodin1@users.noreply.github.com> Date: Wed, 2 Oct 2024 11:43:53 +0300 Subject: [PATCH 58/79] Optimize output and flags (#193) --- cmd/subcmds/optimize.go | 24 +++++++++++- cmd/subcmds/optimizeOutput.go | 14 ------- cmd/subcmds/optimizeSG.go | 23 +++--------- cmd/subcmds/output.go | 57 +++++++++++++---------------- cmd/subcmds/outputFormat.go | 6 +-- cmd/subcmds/root.go | 46 +++++++++++++---------- cmd/subcmds/synth.go | 11 +++++- cmd/subcmds/unmarshal.go | 7 ++++ cmd/subcmds/validateFlags.go | 24 ++++++++++++ pkg/io/confio/parse_acls.go | 12 ++++++ pkg/io/csvio/sg.go | 18 +++++---- pkg/io/mdio/sg.go | 18 +++++---- pkg/io/tfio/acl.go | 8 +++- pkg/io/tfio/sg.go | 53 ++++++++++++++++----------- pkg/ir/acl.go | 69 +++++++++++++++++++---------------- pkg/ir/common.go | 23 +++++++----- pkg/ir/sg.go | 63 ++++++++++++++++++-------------- pkg/optimize/common.go | 13 +++++++ pkg/optimize/sg.go | 18 ++++++++- pkg/synth/common.go | 1 + 20 files changed, 311 insertions(+), 197 deletions(-) delete mode 100644 cmd/subcmds/optimizeOutput.go create mode 100644 cmd/subcmds/validateFlags.go create mode 100644 pkg/io/confio/parse_acls.go create mode 100644 pkg/optimize/common.go diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index 877662a9..353a86eb 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -5,7 +5,14 @@ SPDX-License-Identifier: Apache-2.0 package subcmds -import "github.com/spf13/cobra" +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" +) func NewOptimizeCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ @@ -14,7 +21,22 @@ func NewOptimizeCommand(args *inArgs) *cobra.Command { Long: `optimization of existing SG (nACLS are not supported yet)`, } + // sub cmds cmd.AddCommand(NewOptimizeSGCommand(args)) return cmd } + +func optimization(cmd *cobra.Command, args *inArgs, newOptimizer func(ir.Collection, string) optimize.Optimizer, isSG bool) error { + cmd.SilenceUsage = true // if we got this far, flags are syntactically correct, so no need to print usage + collection, err := parseCollection(args, isSG) + if err != nil { + return fmt.Errorf("could not parse config file %v: %w", args.configFile, err) + } + optimizer := newOptimizer(collection, args.firewallName) + optimizedCollection, err := optimizer.Optimize() + if err != nil { + return err + } + return writeOutput(args, optimizedCollection, collection.VpcNames(), false) +} diff --git a/cmd/subcmds/optimizeOutput.go b/cmd/subcmds/optimizeOutput.go deleted file mode 100644 index af92e337..00000000 --- a/cmd/subcmds/optimizeOutput.go +++ /dev/null @@ -1,14 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package subcmds - -import ( - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -) - -func writeOptimizeOutput(_ *inArgs, _ ir.Collection) error { - return nil -} diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index 57ee6c32..7b5fe908 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -6,14 +6,13 @@ SPDX-License-Identifier: Apache-2.0 package subcmds import ( - "fmt" - "github.com/spf13/cobra" - "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" ) +const sgNameFlag = "sg-name" + func NewOptimizeSGCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "sg", @@ -21,24 +20,12 @@ func NewOptimizeSGCommand(args *inArgs) *cobra.Command { Long: `OptimizeSG attempts to reduce the number of security group rules in a SG without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return optimization(cmd, args) + return optimization(cmd, args, optimize.NewSGOptimizer, true) }, } - cmd.Flags().StringVarP(&args.sgName, sgNameFlag, "s", "", "which SG to optimize") - _ = cmd.MarkFlagRequired(sgNameFlag) // Todo: delete this line. if sgName flag is not supplied - optimize all SGs + // flags + cmd.PersistentFlags().StringVarP(&args.firewallName, sgNameFlag, "n", "", "which security group to optimize") return cmd } - -func optimization(cmd *cobra.Command, args *inArgs) error { - cmd.SilenceUsage = true // if we got this far, flags are syntactically correct, so no need to print usage - sgs, err := confio.ReadSGs(args.configFile) - if err != nil { - return fmt.Errorf("could not parse config file %v: %w", args.configFile, err) - } - if optimize.ReduceSGRules(sgs, args.sgName) != nil { - return err - } - return writeOptimizeOutput(args, sgs) -} diff --git a/cmd/subcmds/output.go b/cmd/subcmds/output.go index aa817b7e..b3f71013 100644 --- a/cmd/subcmds/output.go +++ b/cmd/subcmds/output.go @@ -16,33 +16,27 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/io/csvio" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/mdio" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio" - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) const defaultFilePermission = 0o644 const defaultDirectoryPermission = 0o755 -func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error { - if err := updateOutputFormat(args); err != nil { - return err - } - if args.outputDir != "" && args.outputFmt == apiOutputFormat { - return fmt.Errorf("-d cannot be used with format json") - } +func writeOutput(args *inArgs, collection ir.Collection, vpcNames []string, isSynth bool) error { if args.outputDir != "" { // create the directory if needed if err := os.MkdirAll(args.outputDir, defaultDirectoryPermission); err != nil { return err } } - if err := writeLocals(args, collection, vpcNames); err != nil { + + if err := writeLocals(args, vpcNames, collection); err != nil { return err } var data *bytes.Buffer var err error if args.outputDir == "" { - if data, err = writeCollection(args, collection, ""); err != nil { + if data, err = writeCollection(args, collection, "", isSynth); err != nil { return err } return writeToFile(args.outputFile, data) @@ -55,7 +49,7 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error if args.prefix != "" { args.outputFile = args.outputDir + "/" + args.prefix + "_" + suffix } - if data, err = writeCollection(args, collection, vpc); err != nil { + if data, err = writeCollection(args, collection, vpc, isSynth); err != nil { return err } if err := writeToFile(args.outputFile, data); err != nil { @@ -65,9 +59,9 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error return nil } -func writeCollection(args *inArgs, collection ir.Collection, vpc string) (*bytes.Buffer, error) { +func writeCollection(args *inArgs, collection ir.Collection, vpc string, isSynth bool) (*bytes.Buffer, error) { var data bytes.Buffer - writer, err := pickWriter(args, &data) + writer, err := pickWriter(args, &data, isSynth) if err != nil { return nil, err } @@ -77,15 +71,7 @@ func writeCollection(args *inArgs, collection ir.Collection, vpc string) (*bytes return &data, nil } -func writeToFile(outputFile string, data *bytes.Buffer) error { - if outputFile == "" { - fmt.Println(data.String()) - return nil - } - return os.WriteFile(outputFile, data.Bytes(), defaultFilePermission) -} - -func pickWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { +func pickWriter(args *inArgs, data *bytes.Buffer, isSynth bool) (ir.Writer, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: @@ -94,24 +80,31 @@ func pickWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { return csvio.NewWriter(w), nil case mdOutputFormat: return mdio.NewWriter(w), nil - case apiOutputFormat: - return confio.NewWriter(w, args.configFile) - default: - return nil, fmt.Errorf("bad output format: %q", args.outputFmt) + case jsonOutputFormat: + if isSynth { + return confio.NewWriter(w, args.configFile) + } } + return nil, fmt.Errorf("bad output format: %q", args.outputFmt) } -func writeLocals(args *inArgs, collection ir.Collection, vpcNames []ir.ID) error { - if !args.locals { +func writeToFile(outputFile string, data *bytes.Buffer) error { + if outputFile == "" { + fmt.Println(data.String()) return nil } - if args.outputFmt != tfOutputFormat { - return fmt.Errorf("--locals flag requires setting the output format to tf") - } + return os.WriteFile(outputFile, data.Bytes(), defaultFilePermission) +} - _, isACLCollection := collection.(*ir.ACLCollection) +func writeLocals(args *inArgs, vpcNames []ir.ID, collection ir.Collection) error { + if !args.locals { + return nil + } var data *bytes.Buffer var err error + + _, isACLCollection := collection.(*ir.ACLCollection) + if data, err = tfio.WriteLocals(vpcNames, isACLCollection); err != nil { return err } diff --git a/cmd/subcmds/outputFormat.go b/cmd/subcmds/outputFormat.go index 51a36c60..f435c43a 100644 --- a/cmd/subcmds/outputFormat.go +++ b/cmd/subcmds/outputFormat.go @@ -14,11 +14,11 @@ const ( tfOutputFormat = "tf" csvOutputFormat = "csv" mdOutputFormat = "md" - apiOutputFormat = "json" + jsonOutputFormat = "json" defaultOutputFormat = csvOutputFormat ) -var outputFormats = []string{tfOutputFormat, csvOutputFormat, mdOutputFormat, apiOutputFormat} +var outputFormats = []string{tfOutputFormat, csvOutputFormat, mdOutputFormat, jsonOutputFormat} func updateOutputFormat(args *inArgs) error { var err error @@ -40,7 +40,7 @@ func inferFormatUsingFilename(filename string) (string, error) { case strings.HasSuffix(filename, ".md"): return mdOutputFormat, nil case strings.HasSuffix(filename, ".json"): - return apiOutputFormat, nil + return jsonOutputFormat, nil default: return "", fmt.Errorf("bad output format") } diff --git a/cmd/subcmds/root.go b/cmd/subcmds/root.go index 1f47e591..98ff7973 100644 --- a/cmd/subcmds/root.go +++ b/cmd/subcmds/root.go @@ -14,56 +14,62 @@ import ( const ( configFlag = "config" - specFlag = "spec" outputFmtFlag = "format" outputFileFlag = "output-file" outputDirFlag = "output-dir" prefixFlag = "prefix" - sgNameFlag = "sg-name" singleACLFlag = "single" localsFlag = "locals" ) type inArgs struct { - configFile string - specFile string - outputFmt string - outputFile string - outputDir string - prefix string - sgName string - singleacl bool - locals bool + configFile string + specFile string + outputFmt string + outputFile string + outputDir string + prefix string + firewallName string + singleacl bool + locals bool } func NewRootCommand() *cobra.Command { args := &inArgs{} + // allow PersistentPreRunE + cobra.EnableTraverseRunHooks = true + rootCmd := &cobra.Command{ Use: "vpcgen", - Short: "Tool for automatic synthesis of VPC network configurations", - Long: `Tool for automatic synthesis of VPC network configurations, namely Network ACLs and Security Groups.`, + Short: "A tool for synthesizing and optimizing VPC network configurations", + Long: `A tool for synthesizing and optimizing VPC network configurations, namely Network ACLs and Security Groups.`, + PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { + return validateFlags(args) + }, } + // flags rootCmd.PersistentFlags().StringVarP(&args.configFile, configFlag, "c", "", "JSON file containing a configuration object of existing resources") rootCmd.PersistentFlags().StringVarP(&args.outputFmt, outputFmtFlag, "f", "", "Output format; "+mustBeOneOf(outputFormats)) rootCmd.PersistentFlags().StringVarP(&args.outputFile, outputFileFlag, "o", "", "Write all generated resources to the specified file.") - rootCmd.PersistentFlags().StringVarP(&args.outputDir, outputDirFlag, "d", "", - "Write generated resources to files in the specified directory, one file per VPC.") - rootCmd.PersistentFlags().StringVarP(&args.prefix, prefixFlag, "p", "", "The prefix of the files that will be created.") rootCmd.PersistentFlags().BoolVarP(&args.locals, localsFlag, "l", false, "whether to generate a locals.tf file (only possible when the output format is tf)") - rootCmd.PersistentFlags().SortFlags = false + // flags set for all commands + rootCmd.PersistentFlags().SortFlags = false _ = rootCmd.MarkPersistentFlagRequired(configFlag) - rootCmd.MarkFlagsMutuallyExclusive(outputFileFlag, outputDirFlag) + // sub cmds rootCmd.AddCommand(NewSynthCommand(args)) rootCmd.AddCommand(NewOptimizeCommand(args)) - rootCmd.CompletionOptions.HiddenDefaultCmd = true - rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) // disable help command. should use --help flag instead + // prevent Cobra from creating a default 'completion' command + rootCmd.CompletionOptions.DisableDefaultCmd = true + + // disable help command. should use --help flag instead + rootCmd.SetHelpCommand(&cobra.Command{Hidden: true}) return rootCmd } diff --git a/cmd/subcmds/synth.go b/cmd/subcmds/synth.go index ef0f81d4..83eb348a 100644 --- a/cmd/subcmds/synth.go +++ b/cmd/subcmds/synth.go @@ -13,6 +13,8 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) +const specFlag = "spec" + func NewSynthCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "synth", @@ -21,9 +23,16 @@ func NewSynthCommand(args *inArgs) *cobra.Command { --config and --spec parameters must be supplied.`, } + // flags cmd.PersistentFlags().StringVarP(&args.specFile, specFlag, "s", "", "JSON file containing spec file") + cmd.PersistentFlags().StringVarP(&args.outputDir, outputDirFlag, "d", "", + "Write generated resources to files in the specified directory, one file per VPC.") + cmd.PersistentFlags().StringVarP(&args.prefix, prefixFlag, "p", "", "The prefix of the files that will be created.") + + // flags settings _ = cmd.MarkPersistentFlagRequired(specFlag) + // sub cmds cmd.AddCommand(NewSynthACLCommand(args)) cmd.AddCommand(NewSynthSGCommand(args)) @@ -41,5 +50,5 @@ func synthesis(cmd *cobra.Command, args *inArgs, newSynthesizer func(*ir.Spec, b if err != nil { return err } - return writeOutput(args, collection, utils.MapKeys(spec.Defs.ConfigDefs.VPCs)) + return writeOutput(args, collection, utils.MapKeys(spec.Defs.ConfigDefs.VPCs), true) } diff --git a/cmd/subcmds/unmarshal.go b/cmd/subcmds/unmarshal.go index 5fa7c720..fcb1f76e 100644 --- a/cmd/subcmds/unmarshal.go +++ b/cmd/subcmds/unmarshal.go @@ -26,3 +26,10 @@ func unmarshal(args *inArgs) (*ir.Spec, error) { return model, nil } + +func parseCollection(args *inArgs, isSG bool) (ir.Collection, error) { + if isSG { + return confio.ReadSGs(args.configFile) + } + return confio.ReadACLs(args.configFile) +} diff --git a/cmd/subcmds/validateFlags.go b/cmd/subcmds/validateFlags.go new file mode 100644 index 00000000..be56f6fd --- /dev/null +++ b/cmd/subcmds/validateFlags.go @@ -0,0 +1,24 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package subcmds + +import "fmt" + +func validateFlags(args *inArgs) error { + if args.outputDir != "" && args.outputFile != "" { + return fmt.Errorf("specifying both -d and -o is not allowed") + } + if err := updateOutputFormat(args); err != nil { + return err + } + if args.outputDir != "" && args.outputFmt == jsonOutputFormat { + return fmt.Errorf("-d cannot be used with format json") + } + if args.locals && args.outputFmt != tfOutputFormat { + return fmt.Errorf("--locals flag requires setting the output format to tf") + } + return nil +} diff --git a/pkg/io/confio/parse_acls.go b/pkg/io/confio/parse_acls.go new file mode 100644 index 00000000..13481978 --- /dev/null +++ b/pkg/io/confio/parse_acls.go @@ -0,0 +1,12 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package confio + +import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + +func ReadACLs(_ string) (*ir.ACLCollection, error) { + return nil, nil +} diff --git a/pkg/io/csvio/sg.go b/pkg/io/csvio/sg.go index ed91a1ef..35c74f8b 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/csvio/sg.go @@ -20,14 +20,18 @@ func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { if err := w.w.WriteAll(sgHeader()); err != nil { return err } - for _, sgName := range collection.SortedSGNames(vpc) { - vpcName := ir.VpcFromScopedResource(string(sgName)) - sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) - if err != nil { - return err + for _, vpcName := range collection.VpcNames() { + if vpc != vpcName && vpc != "" { + continue } - if err := w.w.WriteAll(sgTable); err != nil { - return err + for _, sgName := range collection.SortedSGNames(vpcName) { + sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) + if err != nil { + return err + } + if err := w.w.WriteAll(sgTable); err != nil { + return err + } } } return nil diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go index 3277b3fa..0fcbf734 100644 --- a/pkg/io/mdio/sg.go +++ b/pkg/io/mdio/sg.go @@ -20,14 +20,18 @@ func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { if err := w.writeAll(sgHeader()); err != nil { return err } - for _, sgName := range collection.SortedSGNames(vpc) { - vpcName := ir.VpcFromScopedResource(string(sgName)) - sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) - if err != nil { - return err + for _, vpcName := range collection.VpcNames() { + if vpc != vpcName && vpc != "" { + continue } - if err := w.writeAll(sgTable); err != nil { - return err + for _, sgName := range collection.SortedSGNames(vpcName) { + sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) + if err != nil { + return err + } + if err := w.writeAll(sgTable); err != nil { + return err + } } } return nil diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index b0dd23e8..7f641d3b 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -64,8 +64,14 @@ func aclRule(rule *ir.ACLRule, name string) (tf.Block, error) { {Name: "source", Value: quote(rule.Source.String())}, {Name: "destination", Value: quote(rule.Destination.String())}, } + + comment := "" + if rule.Explanation != "" { + comment = fmt.Sprintf("# %v", rule.Explanation) + } + return tf.Block{Name: "rules", - Comment: fmt.Sprintf("# %v", rule.Explanation), + Comment: comment, Arguments: arguments, Blocks: aclProtocol(rule.Protocol), }, nil diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 747be97d..793c5c7a 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -72,10 +72,15 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { return tf.Block{}, err } + comment := "" + if rule.Explanation != "" { + comment = fmt.Sprintf("# %v", rule.Explanation) + } + return tf.Block{ Name: "resource", Labels: []string{quote("ibm_is_security_group_rule"), ir.ChangeScoping(quote(ruleName))}, - Comment: fmt.Sprintf("# %v", rule.Explanation), + Comment: comment, Arguments: []tf.Argument{ {Name: "group", Value: group}, {Name: "direction", Value: quote(direction(rule.Direction))}, @@ -85,42 +90,48 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { }, nil } -func sg(sgName, comment string) (tf.Block, error) { - vpcName := ir.VpcFromScopedResource(sgName) - sgName = ir.ChangeScoping(sgName) - if err := verifyName(sgName); err != nil { +func sg(sgName, vpcName string) (tf.Block, error) { + tfSGName := ir.ChangeScoping(sgName) + comment := fmt.Sprintf("\n### SG attached to %s", sgName) + if sgName == tfSGName { // its optimization + comment = "" + } + if err := verifyName(tfSGName); err != nil { return tf.Block{}, err } return tf.Block{ Name: "resource", //nolint:revive // obvious false positive - Labels: []string{quote("ibm_is_security_group"), ir.ChangeScoping(quote(sgName))}, + Labels: []string{quote("ibm_is_security_group"), quote(tfSGName)}, Comment: comment, Arguments: []tf.Argument{ - {Name: "name", Value: quote("sg-" + sgName)}, + {Name: "name", Value: quote("sg-" + tfSGName)}, {Name: "resource_group", Value: "local.sg_synth_resource_group_id"}, {Name: "vpc", Value: fmt.Sprintf("local.sg_synth_%s_id", vpcName)}, }, }, nil } -func sgCollection(t *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { - var resources []tf.Block //nolint:prealloc // nontrivial to calculate, and an unlikely performance bottleneck - for _, sgName := range t.SortedSGNames(vpc) { - comment := "" - vpcName := ir.VpcFromScopedResource(string(sgName)) - rules := t.SGs[vpcName][sgName].AllRules() - comment = fmt.Sprintf("\n### SG attached to %v", sgName) - sg, err := sg(sgName.String(), comment) - if err != nil { - return nil, err +func sgCollection(collection *ir.SGCollection, vpc string) (*tf.ConfigFile, error) { + var resources []tf.Block + + for _, vpcName := range collection.VpcNames() { + if vpc != vpcName && vpc != "" { + continue } - resources = append(resources, sg) - for i, rule := range rules { - rule, err := sgRule(rule, sgName, i) + for _, sgName := range collection.SortedSGNames(vpcName) { + rules := collection.SGs[vpcName][sgName].AllRules() + sg, err := sg(sgName.String(), vpcName) if err != nil { return nil, err } - resources = append(resources, rule) + resources = append(resources, sg) + for i, rule := range rules { + rule, err := sgRule(rule, sgName, i) + if err != nil { + return nil, err + } + resources = append(resources, rule) + } } } return &tf.ConfigFile{ diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index b1de36c3..e13b91bb 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -15,36 +15,38 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) -type Action string +type ( + Action string + + ACLRule struct { + Action Action + Direction Direction + Source *netset.IPBlock + Destination *netset.IPBlock + Protocol netp.Protocol + Explanation string + } + + ACL struct { + Subnet string + Internal []*ACLRule + External []*ACLRule + } + + ACLCollection struct { + ACLs map[ID]map[string]*ACL + } + + ACLWriter interface { + WriteACL(aclColl *ACLCollection, vpc string) error + } +) const ( Allow Action = "allow" Deny Action = "deny" ) -type ACLRule struct { - Action Action - Direction Direction - Source *netset.IPBlock - Destination *netset.IPBlock - Protocol netp.Protocol - Explanation string -} - -type ACL struct { - Subnet string - Internal []*ACLRule - External []*ACLRule -} - -type ACLCollection struct { - ACLs map[ID]map[string]*ACL -} - -type ACLWriter interface { - WriteACL(aclColl *ACLCollection, vpc string) error -} - func (r *ACLRule) isRedundant(rules []*ACLRule) bool { for _, rule := range rules { if rule.mustSupersede(r) { @@ -105,24 +107,27 @@ func NewACLCollection() *ACLCollection { return &ACLCollection{ACLs: map[ID]map[string]*ACL{}} } -func NewACL() *ACL { - return &ACL{Internal: []*ACLRule{}, External: []*ACLRule{}} +func NewACL(subnet string) *ACL { + return &ACL{Subnet: subnet, Internal: []*ACLRule{}, External: []*ACLRule{}} } -func (c *ACLCollection) LookupOrCreate(name string) *ACL { - vpcName := VpcFromScopedResource(name) - if acl, ok := c.ACLs[vpcName][name]; ok { +func (c *ACLCollection) LookupOrCreate(subnet string) *ACL { + vpcName := VpcFromScopedResource(subnet) + if acl, ok := c.ACLs[vpcName][subnet]; ok { return acl } - newACL := NewACL() - newACL.Subnet = name + newACL := NewACL(subnet) if c.ACLs[vpcName] == nil { c.ACLs[vpcName] = make(map[string]*ACL) } - c.ACLs[vpcName][name] = newACL + c.ACLs[vpcName][subnet] = newACL return newACL } +func (c *ACLCollection) VpcNames() []string { + return utils.SortedMapKeys(c.ACLs) +} + func (c *ACLCollection) Write(w Writer, vpc string) error { return w.WriteACL(c, vpc) } diff --git a/pkg/ir/common.go b/pkg/ir/common.go index e10b1265..a89aeae8 100644 --- a/pkg/ir/common.go +++ b/pkg/ir/common.go @@ -5,18 +5,21 @@ SPDX-License-Identifier: Apache-2.0 package ir -type Direction string +type ( + Direction string + + Collection interface { + Write(writer Writer, vpc string) error + VpcNames() []string + } + + Writer interface { + ACLWriter + SGWriter + } +) const ( Outbound Direction = "outbound" Inbound Direction = "inbound" ) - -type Writer interface { - ACLWriter - SGWriter -} - -type Collection interface { - Write(writer Writer, vpc string) error -} diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index e90538d5..2317a4ec 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -26,37 +26,40 @@ const ( SGResourceFileShareMountTarget SGResource = "fsmt" ) -type SGName string +type ( + SGName string -func (s SGName) String() string { - return string(s) -} + RemoteType interface { + fmt.Stringer + // *netset.IPBlock | SGName + } -type RemoteType interface { - fmt.Stringer - // *netset.IPBlock | SGName -} + SGRule struct { + Direction Direction + Remote RemoteType + Protocol netp.Protocol + Local *netset.IPBlock + Explanation string + } -type SGRule struct { - Direction Direction - Remote RemoteType - Protocol netp.Protocol - Local *netset.IPBlock - Explanation string -} + SG struct { + SGName SGName + InboundRules []*SGRule + OutboundRules []*SGRule + Attached []ID + } -type SG struct { - InboundRules []*SGRule - OutboundRules []*SGRule - Attached []ID -} + SGCollection struct { + SGs map[ID]map[SGName]*SG + } -type SGCollection struct { - SGs map[ID]map[SGName]*SG -} + SGWriter interface { + WriteSG(sgColl *SGCollection, vpc string) error + } +) -type SGWriter interface { - WriteSG(sgColl *SGCollection, vpc string) error +func (s SGName) String() string { + return string(s) } func (r *SGRule) isRedundant(rules []*SGRule) bool { @@ -76,8 +79,8 @@ func (r *SGRule) mustSupersede(other *SGRule) bool { return res } -func NewSG() *SG { - return &SG{InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Attached: []ID{}} +func NewSG(sgName SGName) *SG { + return &SG{SGName: sgName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Attached: []ID{}} } func NewSGCollection() *SGCollection { @@ -89,7 +92,7 @@ func (c *SGCollection) LookupOrCreate(name SGName) *SG { if sg, ok := c.SGs[vpcName][name]; ok { return sg } - newSG := NewSG() + newSG := NewSG(name) if c.SGs[vpcName] == nil { c.SGs[vpcName] = make(map[SGName]*SG) } @@ -110,6 +113,10 @@ func (a *SG) AllRules() []*SGRule { return append(a.InboundRules, a.OutboundRules...) } +func (c *SGCollection) VpcNames() []string { + return utils.SortedMapKeys(c.SGs) +} + func (c *SGCollection) Write(w Writer, vpc string) error { return w.WriteSG(c, vpc) } diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go new file mode 100644 index 00000000..010c2239 --- /dev/null +++ b/pkg/optimize/common.go @@ -0,0 +1,13 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package optimize + +import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + +type Optimizer interface { + // attempts to reduce number of SG/nACL rules + Optimize() (ir.Collection, error) +} diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg.go index f3301962..3288d2a7 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg.go @@ -9,6 +9,20 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func ReduceSGRules(_ *ir.SGCollection, _ string) error { - return nil +type SGOptimizer struct { + sgCollection *ir.SGCollection + sgName ir.SGName + sgVPC *string +} + +func NewSGOptimizer(collection ir.Collection, sgName string) Optimizer { + components := ir.ScopingComponents(sgName) + if len(components) == 1 { + return &SGOptimizer{sgCollection: collection.(*ir.SGCollection), sgName: ir.SGName(sgName), sgVPC: nil} + } + return &SGOptimizer{sgCollection: collection.(*ir.SGCollection), sgName: ir.SGName(components[1]), sgVPC: &components[0]} +} + +func (s *SGOptimizer) Optimize() (ir.Collection, error) { + return s.sgCollection, nil } diff --git a/pkg/synth/common.go b/pkg/synth/common.go index e6e516f3..a9b7b51f 100644 --- a/pkg/synth/common.go +++ b/pkg/synth/common.go @@ -15,6 +15,7 @@ import ( type ( Synthesizer interface { + // generates SGs/nACLs Synth() (ir.Collection, error) } From 11effb77d7433383b3a61fc607607cb7f1436552 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 7 Oct 2024 13:15:45 +0300 Subject: [PATCH 59/79] fix merging --- cmd/subcmds/synthACL.go | 3 --- cmd/subcmds/synthSG.go | 3 --- pkg/ir/acl.go | 4 ++-- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/cmd/subcmds/synthACL.go b/cmd/subcmds/synthACL.go index 96c6aea3..4aee4040 100644 --- a/cmd/subcmds/synthACL.go +++ b/cmd/subcmds/synthACL.go @@ -19,9 +19,6 @@ func NewSynthACLCommand(args *inArgs) *cobra.Command { Endpoints in the required-connectivity specification may be subnets, subnet segments, CIDR segments and externals.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - if err := validateFlags(args); err != nil { - return err - } return synthesis(cmd, args, synth.NewACLSynthesizer, args.singleacl) }, } diff --git a/cmd/subcmds/synthSG.go b/cmd/subcmds/synthSG.go index 215324ca..88bb4a56 100644 --- a/cmd/subcmds/synthSG.go +++ b/cmd/subcmds/synthSG.go @@ -19,9 +19,6 @@ func NewSynthSGCommand(args *inArgs) *cobra.Command { Endpoints in the required-connectivity specification may be Instances (VSIs), Network Interfaces, VPEs and externals.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - if err := validateFlags(args); err != nil { - return err - } return synthesis(cmd, args, synth.NewSGSynthesizer, false) }, } diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index ace507ab..e13b91bb 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -48,8 +48,8 @@ const ( ) func (r *ACLRule) isRedundant(rules []*ACLRule) bool { - for i := range rules { - if rules[i].mustSupersede(r) { + for _, rule := range rules { + if rule.mustSupersede(r) { return true } } From 2bb071974414ceb97148f52b7122eaaecb47873b Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 8 Oct 2024 18:35:42 +0300 Subject: [PATCH 60/79] models new version, cubes, wip --- cmd/subcmds/optimizeSG.go | 4 +- go.mod | 2 +- go.sum | 4 +- pkg/io/confio/parse_sgs.go | 2 +- pkg/optimize/common.go | 56 +- pkg/optimize/compressRules.go | 74 - pkg/optimize/ip.go | 81 - pkg/optimize/ipSpanToSGRules.go | 147 - pkg/optimize/sg/ipCubesToRules.go | 152 + pkg/optimize/sg/optimizeSG_test.go | 57 + pkg/optimize/sg/reduceCubes.go | 118 + pkg/optimize/sg/rulesToCubes.go | 106 + pkg/optimize/{ => sg}/sg.go | 108 +- .../sgCubesToRules.go} | 24 +- pkg/optimize/sgRulesToIPToSpan.go | 126 - pkg/optimize/sgRulesToSGToSpan.go | 66 - .../optimize_sg_icmp_codes/config_object.json | 2169 -------------- .../optimize_sg_icmp_codes/conn_spec.json | 143 - test/data/optimize_sg_icmp_codes/details.txt | 14 - .../optimize_sg_icmp_types/config_object.json | 2493 ----------------- .../optimize_sg_icmp_types/conn_spec.json | 359 --- test/data/optimize_sg_icmp_types/details.txt | 28 - .../optimize_sg_icmp_codes/sg_expected.tf | 70 - .../optimize_sg_icmp_types/sg_expected.tf | 67 - test/main_test_list.go | 18 - 25 files changed, 554 insertions(+), 5934 deletions(-) delete mode 100644 pkg/optimize/compressRules.go delete mode 100644 pkg/optimize/ip.go delete mode 100644 pkg/optimize/ipSpanToSGRules.go create mode 100644 pkg/optimize/sg/ipCubesToRules.go create mode 100644 pkg/optimize/sg/optimizeSG_test.go create mode 100644 pkg/optimize/sg/reduceCubes.go create mode 100644 pkg/optimize/sg/rulesToCubes.go rename pkg/optimize/{ => sg}/sg.go (59%) rename pkg/optimize/{sgSpanToSGRules.go => sg/sgCubesToRules.go} (52%) delete mode 100644 pkg/optimize/sgRulesToIPToSpan.go delete mode 100644 pkg/optimize/sgRulesToSGToSpan.go delete mode 100644 test/data/optimize_sg_icmp_codes/config_object.json delete mode 100644 test/data/optimize_sg_icmp_codes/conn_spec.json delete mode 100644 test/data/optimize_sg_icmp_codes/details.txt delete mode 100644 test/data/optimize_sg_icmp_types/config_object.json delete mode 100644 test/data/optimize_sg_icmp_types/conn_spec.json delete mode 100644 test/data/optimize_sg_icmp_types/details.txt delete mode 100644 test/expected/optimize_sg_icmp_codes/sg_expected.tf delete mode 100644 test/expected/optimize_sg_icmp_types/sg_expected.tf diff --git a/cmd/subcmds/optimizeSG.go b/cmd/subcmds/optimizeSG.go index 7b5fe908..9606234b 100644 --- a/cmd/subcmds/optimizeSG.go +++ b/cmd/subcmds/optimizeSG.go @@ -8,7 +8,7 @@ package subcmds import ( "github.com/spf13/cobra" - "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" + sgoptimizer "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize/sg" ) const sgNameFlag = "sg-name" @@ -20,7 +20,7 @@ func NewOptimizeSGCommand(args *inArgs) *cobra.Command { Long: `OptimizeSG attempts to reduce the number of security group rules in a SG without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return optimization(cmd, args, optimize.NewSGOptimizer, true) + return optimization(cmd, args, sgoptimizer.NewSGOptimizer, true) }, } diff --git a/go.mod b/go.mod index 2a404e56..78ec72e8 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/IBM/vpc-go-sdk v0.60.0 github.com/np-guard/cloud-resource-collector v0.15.0 - github.com/np-guard/models v0.5.0 + github.com/np-guard/models v0.5.1-0.20241008132809-1e27bae86fe4 github.com/spf13/cobra v1.8.1 ) diff --git a/go.sum b/go.sum index e4aac127..a83a5162 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/np-guard/cloud-resource-collector v0.15.0 h1:jkmxql6D1uBr/qmSOsBzUgeDxlUXSCe7dBKfqfK+QZ4= github.com/np-guard/cloud-resource-collector v0.15.0/go.mod h1:klCHnNnuuVcCtGQHA7R1a8fqnvfMCk/5Jdld6V7sN2A= -github.com/np-guard/models v0.5.0 h1:P37gCg3RD23hZHymFWtthrF+mGIwyHJkWy0wIWIzokQ= -github.com/np-guard/models v0.5.0/go.mod h1:29M8utxinyUpYaDuIuOyCcMBf7EsMWZcIrRWCjFm0Bw= +github.com/np-guard/models v0.5.1-0.20241008132809-1e27bae86fe4 h1:wsf8U4t74ouuhLqdvxrf247pcjCPlrDhEggpUeskiHo= +github.com/np-guard/models v0.5.1-0.20241008132809-1e27bae86fe4/go.mod h1:29M8utxinyUpYaDuIuOyCcMBf7EsMWZcIrRWCjFm0Bw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index 91853903..e1528913 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -122,7 +122,7 @@ func translateSGRuleProtocolIcmp(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleP if err != nil { return nil, err } - protocol, err := netp.ICMPFromTypeAndCode64(rule.Type, rule.Code) + protocol, err := netp.ICMPFromTypeAndCode64WithoutRFCValidation(rule.Type, rule.Code) if err != nil { return nil, err } diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index e802dbdd..d4ba3e45 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -9,7 +9,6 @@ import ( "sort" "github.com/np-guard/models/pkg/ds" - "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" @@ -22,12 +21,59 @@ type Optimizer interface { } // each IPBlock is a single CIDR. The CIDRs are disjoint. -func sortPartitionsByIPAddrs[T any](p []ds.Pair[*netset.IPBlock, T]) []ds.Pair[*netset.IPBlock, T] { - cmp := func(i, j int) bool { return p[i].Left.FirstIPAddress() < p[j].Left.FirstIPAddress() } +func SortPartitionsByIPAddrs[T any](p []ds.Pair[*netset.IPBlock, T]) []ds.Pair[*netset.IPBlock, T] { + cmp := func(i, j int) bool { + if p[i].Left.FirstIPAddress() == p[j].Left.FirstIPAddress() { + return p[i].Left.LastIPAddress() < p[j].Left.LastIPAddress() + } + return p[i].Left.FirstIPAddress() < p[j].Left.FirstIPAddress() + } sort.Slice(p, cmp) return p } -func allPorts(ports *interval.CanonicalSet) bool { - return ports.Equal(netp.AllPorts().ToSet()) +func LessIPBlock(this, other *netset.IPBlock) bool { + if this.FirstIPAddress() == this.FirstIPAddress() { + return this.LastIPAddress() < other.LastIPAddress() + } + return this.FirstIPAddress() < other.FirstIPAddress() +} + +func IcmpsetPartitions(icmpset *netset.ICMPSet) []netp.ICMP { + result := make([]netp.ICMP, 0) + if icmpset.IsAll() { + icmp, _ := netp.ICMPFromTypeAndCode64WithoutRFCValidation(nil, nil) + return []netp.ICMP{icmp} + } + + for _, cube := range icmpset.Partitions() { + for _, typeInterval := range cube.Left.Intervals() { + for _, icmpType := range typeInterval.Elements() { + if cube.Right.Equal(netset.AllICMPCodes()) { + icmp, _ := netp.ICMPFromTypeAndCode64WithoutRFCValidation(&icmpType, nil) + result = append(result, icmp) + continue + } + for _, codeInterval := range cube.Right.Intervals() { + for _, icmpCode := range codeInterval.Elements() { + icmp, _ := netp.ICMPFromTypeAndCode64WithoutRFCValidation(&icmpType, &icmpCode) + result = append(result, icmp) + } + } + } + } + } + return result +} + +func IcmpRuleToIcmpSet(icmp netp.ICMP) *netset.ICMPSet { + if icmp.TypeCode == nil { + return netset.AllICMPSet() + } + icmpType := int64(icmp.TypeCode.Type) + if icmp.TypeCode.Code == nil { + return netset.NewICMPSet(icmpType, icmpType, int64(netp.MinICMPCode), int64(netp.MaxICMPCode)) + } + icmpCode := int64(*icmp.TypeCode.Code) + return netset.NewICMPSet(icmpType, icmpType, icmpCode, icmpCode) } diff --git a/pkg/optimize/compressRules.go b/pkg/optimize/compressRules.go deleted file mode 100644 index 687ed963..00000000 --- a/pkg/optimize/compressRules.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package optimize - -import ( - "github.com/np-guard/models/pkg/netset" -) - -func compressSpansToSG(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { - spans = deleteOtherProtocolIfAllProtocolExists(spans) - return compressThreeProtocolsToAllProtocol(spans) -} - -// delete other protocols rules if all protocol rule exists -func deleteOtherProtocolIfAllProtocolExists(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { - for _, sgName := range spans.all { - delete(spans.tcp, sgName) - delete(spans.udp, sgName) - delete(spans.icmp, sgName) - } - return spans -} - -// merge tcp, udp and icmp rules into all protocol rule -func compressThreeProtocolsToAllProtocol(spans *sgSpansToSGPerProtocol) *sgSpansToSGPerProtocol { - for sgName, tcpPorts := range spans.tcp { - if udpPorts, ok := spans.udp[sgName]; ok { - if ic, ok := spans.icmp[sgName]; ok { - if ic.Equal(netset.AllICMPSet()) && allPorts(tcpPorts) && allPorts(udpPorts) { // all tcp&udp ports and all icmp types&codes - delete(spans.tcp, sgName) - delete(spans.udp, sgName) - delete(spans.icmp, sgName) - spans.all = append(spans.all, sgName) - } - } - } - } - return spans -} - -// observation: It pays to switch to all protocol rule when we have rules that cover all other protocols -// on exactly the same cidr (only one protocol can exceed). -func compressSpansToIP(span *sgSpansToIPPerProtocol) *sgSpansToIPPerProtocol { - t := 0 - u := 0 - i := 0 - - for t != len(span.tcp) && u != len(span.udp) && i != len(span.icmp) { - if !allPorts(span.tcp[t].Right) { - t++ - continue - } - if !allPorts(span.udp[u].Right) { - u++ - continue - } - if !span.icmp[i].Right.Equal(netset.AllICMPSet()) { - i++ - continue - } - - if span.tcp[t].Left.Equal(span.udp[u].Left) && span.tcp[t].Left.Equal(span.icmp[i].Left) { - span.all = span.all.Union(span.tcp[t].Left.Copy()) - span.tcp = append(span.tcp[:t], span.tcp[t+1:]...) - span.udp = append(span.udp[:u], span.udp[u+1:]...) - span.icmp = append(span.icmp[:i], span.icmp[i+1:]...) - } - } - - return span -} diff --git a/pkg/optimize/ip.go b/pkg/optimize/ip.go deleted file mode 100644 index c1a844af..00000000 --- a/pkg/optimize/ip.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package optimize - -import ( - "log" - "strings" - - "github.com/np-guard/models/pkg/netset" -) - -// temporary file, should be implemented in models repo -const commaSeparator = ", " - -// given a and b single disjoint cidrs, a 0 { - prevIPBlock := span[i-1].Left - currIPBlock := span[i].Left - if !touching(prevIPBlock, currIPBlock) { // the cidrs are not touching - hole := IPBlockFromRange(NextIP(prevIPBlock), BeforeIP(currIPBlock)) - if !hole.IsSubset(allSpan) { // there in no all rule covering the hole - for _, r := range rules { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } - rules = []ds.Pair[*netset.IPBlock, *interval.Interval]{} - } - } - } - - activePorts := interval.NewCanonicalSet() - for _, r := range rules { - if !r.Right.ToSet().IsSubset(span[i].Right) { // create rules - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.End())) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } else { - activePorts.AddInterval(*r.Right) - } - } - - // new rules - for _, ports := range span[i].Right.Intervals() { - if !ports.ToSet().IsSubset(activePorts) { // it is not contained in other rules - r := ds.Pair[*netset.IPBlock, *interval.Interval]{Left: FirstIPAddress(span[i].Left), Right: &ports} - rules = append(rules, r) - } - } - } - - // create the rest of the rules - for _, r := range rules { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.Start())) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } - - return result -} - -// problem: where should I end the rule? -// func createTcpudpRules(rules []ds.Pair[*netset.IPBlock, *interval.Interval], span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], -// direction ir.Direction, isTCP bool) (res []ir.SGRule) { -// res = make([]ir.SGRule, 0) -// for _, r := range rules { -// p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.Start())) -// for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { -// res = append(res, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) -// } -// } -// return res -// } - -func icmpSpanToSGRules(span []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allSpan *netset.IPBlock, direction ir.Direction) []*ir.SGRule { - rules := []ds.Pair[*netset.IPBlock, *netp.ICMP]{} - result := make([]*ir.SGRule, 0) - - for i := range span { - if i > 0 { - prevIPBlock := span[i-1].Left - currIPBlock := span[i].Left - if !touching(prevIPBlock, currIPBlock) { // the cidrs are not touching - hole := IPBlockFromRange(NextIP(prevIPBlock), BeforeIP(currIPBlock)) - if !hole.IsSubset(allSpan) { // there in no all rule covering the hole - for _, r := range rules { - p, _ := netp.NewICMP(r.Right.TypeCode) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } - rules = []ds.Pair[*netset.IPBlock, *netp.ICMP]{} - } - } - } - - activeICMP := netset.EmptyICMPSet() - for _, r := range rules { - ruleIcmpSet := netset.NewICMPSet(*r.Right) - if !ruleIcmpSet.IsSubset(span[i].Right) { // create rules - p, _ := netp.NewICMP(r.Right.TypeCode) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[i-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } else { - activeICMP.Union(ruleIcmpSet) - } - } - - // new rules - for _, p := range span[i].Right.Partitions() { - if !netset.NewICMPSet(p).IsSubset(activeICMP) { - r := ds.Pair[*netset.IPBlock, *netp.ICMP]{Left: FirstIPAddress(span[i].Left), Right: &p} - rules = append(rules, r) - } - } - } - - // create the rest of the rules - for _, r := range rules { - p, _ := netp.NewICMP(r.Right.TypeCode) - for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } - - return result -} diff --git a/pkg/optimize/sg/ipCubesToRules.go b/pkg/optimize/sg/ipCubesToRules.go new file mode 100644 index 00000000..e38acb9d --- /dev/null +++ b/pkg/optimize/sg/ipCubesToRules.go @@ -0,0 +1,152 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package sgoptimizer + +import ( + "github.com/np-guard/models/pkg/ds" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" +) + +func allProtocolIPCubesIPToRules(cubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { + result := make([]*ir.SGRule, 0) + for _, cidr := range cubes.SplitToCidrs() { + result = append(result, ir.NewSGRule(direction, cidr, netp.AnyProtocol{}, netset.GetCidrAll(), "")) + } + return result +} + +func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], allProtocolCubes *netset.IPBlock, + direction ir.Direction, isTCP bool) []*ir.SGRule { + activeRules := make(map[*netset.IPBlock]*interval.Interval) // start ip and ports + result := make([]*ir.SGRule, 0) + + for i := range cubes { + if i > 0 && !continuation(cubes[i-1], cubes[i], allProtocolCubes) { + for ipb, ports := range activeRules { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) + ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) + for _, cidr := range ipRange.SplitToCidrs() { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + delete(activeRules, ipb) + } + } + + // rules whose ports are not in the current cube will not remain active + activePorts := interval.NewCanonicalSet() + for ipb, ports := range activeRules { + if !ports.ToSet().IsSubset(cubes[i].Right) { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) + ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) + for _, cidr := range ipRange.SplitToCidrs() { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } else { + activePorts.AddInterval(*ports) + } + } + + // if the cube contains ports that are not contained in active rules, new rules will be created + for _, ports := range cubes[i].Right.Intervals() { + if !ports.ToSet().IsSubset(activePorts) { + activeRules[cubes[i].Left.FirstIPAddressObject()] = &ports + } + } + } + + // create the rest of the rules + for ipb, ports := range activeRules { + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) + ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[len(cubes)-1].Left.LastIPAddressObject()) + for _, cidr := range ipRange.SplitToCidrs() { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + + return result +} + +// problem: where should I end the rule? +// func createTcpudpRules(rules []ds.Pair[*netset.IPBlock, *interval.Interval], span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], +// direction ir.Direction, isTCP bool) (res []ir.SGRule) { +// res = make([]ir.SGRule, 0) +// for _, r := range rules { +// p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.Start())) +// for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { +// res = append(res, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) +// } +// } +// return res +// } + +func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allProtocolCubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { + activeRules := make(map[*netset.IPBlock]*netp.ICMP) + result := make([]*ir.SGRule, 0) + + for i := range cubes { + if i > 0 && !continuation(cubes[i-1], cubes[i], allProtocolCubes) { + for ipb, icmp := range activeRules { + p, _ := netp.NewICMP(icmp.TypeCode) + ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) + for _, cidr := range ipRange.SplitToCidrs() { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + delete(activeRules, ipb) + } + } + + // rules whose icmp value is not in the current cube will not remain active + activeICMP := netset.EmptyICMPSet() + for ipb, icmp := range activeRules { + ruleIcmpSet := optimize.IcmpRuleToIcmpSet(*icmp) + if !ruleIcmpSet.IsSubset(cubes[i].Right) { // create rules + p, _ := netp.NewICMPWithoutRFCValidation(icmp.TypeCode) + ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) + for _, cidr := range ipRange.SplitToCidrs() { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } else { + activeICMP.Union(ruleIcmpSet) + } + } + + // new rules + for _, p := range optimize.IcmpsetPartitions(cubes[i].Right) { + if !optimize.IcmpRuleToIcmpSet(p).IsSubset(activeICMP) { + activeRules[cubes[i].Left.FirstIPAddressObject()] = &p + } + } + } + + // create the rest of the rules + for ipb, icmp := range activeRules { + p, _ := netp.NewICMP(icmp.TypeCode) + ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[len(cubes)-1].Left.LastIPAddressObject()) + for _, cidr := range ipRange.SplitToCidrs() { + result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + } + } + + return result +} + +func continuation[T ds.Set[T]](prevPair, currPair ds.Pair[*netset.IPBlock, T], allProtocolCubes *netset.IPBlock) bool { + prevIPBlock := prevPair.Left + currIPBlock := currPair.Left + touching, _ := prevIPBlock.TouchingIPRanges(currIPBlock) + if touching { + return true + } + startH, _ := prevIPBlock.NextIP() + endH, _ := currIPBlock.PreviousIP() + hole, _ := netset.IPBlockFromIPRange(startH, endH) + return hole.IsSubset(allProtocolCubes) +} diff --git a/pkg/optimize/sg/optimizeSG_test.go b/pkg/optimize/sg/optimizeSG_test.go new file mode 100644 index 00000000..544fa53f --- /dev/null +++ b/pkg/optimize/sg/optimizeSG_test.go @@ -0,0 +1,57 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package sgoptimizer_test + +import ( + "log" + "testing" + + "github.com/np-guard/models/pkg/ds" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" +) + +func TestOps(t *testing.T) { + sgRules := make([]*ir.SGRule, 0) + p1, _ := netp.NewTCPUDP(true, 1, 100, 1, 10) + p2, _ := netp.NewTCPUDP(true, 1, 100, 1, 20) + + ipb1, _ := netset.IPBlockFromCidrOrAddress("0.0.0.0") + ipb2, _ := netset.IPBlockFromCidrOrAddress("0.0.0.0/31") + + sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb1, p1, netset.GetCidrAll(), "")) + sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb2, p2, netset.GetCidrAll(), "")) + + res := tcpudpRulesToIPCubes(sgRules) + for i, pair := range res { + log.Println("pair ", i, ": ipblock: ", pair.Left.String(), ", ports: ", pair.Right.String()) + } + + sgRules = []*ir.SGRule{} + sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb2, p1, netset.GetCidrAll(), "")) + sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb1, p2, netset.GetCidrAll(), "")) + + res = tcpudpRulesToIPCubes(sgRules) + for i, pair := range res { + log.Println("pair ", i, ": ipblock: ", pair.Left.String(), ", ports: ", pair.Right.String()) + } + + t.Log("Hi") +} + +func tcpudpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.PortSet] { + cubes := ds.NewProductLeft[*netset.IPBlock, *netset.PortSet]() + for _, rule := range rules { + ipb := rule.Remote.(*netset.IPBlock) // already checked + portsSet := rule.Protocol.(netp.TCPUDP) // already checked + r := ds.CartesianPairLeft(ipb, portsSet.DstPorts().ToSet()) + cubes = cubes.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.PortSet]) + } + return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) +} diff --git a/pkg/optimize/sg/reduceCubes.go b/pkg/optimize/sg/reduceCubes.go new file mode 100644 index 00000000..3489ed49 --- /dev/null +++ b/pkg/optimize/sg/reduceCubes.go @@ -0,0 +1,118 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package sgoptimizer + +import ( + "slices" + + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" +) + +func reduceSGCubes(spans *sgCubesPerProtocol) *sgCubesPerProtocol { + spans = deleteOtherProtocolIfAllProtocolExists(spans) + return compressThreeProtocolsToAllProtocol(spans) +} + +// delete other protocols rules if all protocol rule exists +func deleteOtherProtocolIfAllProtocolExists(spans *sgCubesPerProtocol) *sgCubesPerProtocol { + for _, sgName := range spans.all { + delete(spans.tcp, sgName) + delete(spans.udp, sgName) + delete(spans.icmp, sgName) + } + return spans +} + +// merge tcp, udp and icmp rules into all protocol rule +func compressThreeProtocolsToAllProtocol(spans *sgCubesPerProtocol) *sgCubesPerProtocol { + for sgName, tcpPorts := range spans.tcp { + if udpPorts, ok := spans.udp[sgName]; ok { + if ic, ok := spans.icmp[sgName]; ok { + if ic.IsAll() && tcpPorts.Equal(netset.AllPorts()) && udpPorts.Equal(netset.AllPorts()) { + delete(spans.tcp, sgName) + delete(spans.udp, sgName) + delete(spans.icmp, sgName) + spans.all = append(spans.all, sgName) + } + } + } + } + return spans +} + +// observation: It pays to switch to all protocol rule when we have rules that cover all other protocols +// on exactly the same cidr (only one protocol can exceed). +func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { + tcpPtr := 0 + udpPtr := 0 + icmpPtr := 0 + + var changed bool + for tcpPtr < len(cubes.tcp) && udpPtr < len(cubes.udp) && icmpPtr < len(cubes.icmp) { + if !cubes.tcp[tcpPtr].Right.Equal(netset.AllPorts()) { + tcpPtr++ + continue + } + if !cubes.udp[udpPtr].Right.Equal(netset.AllPorts()) { + udpPtr++ + continue + } + if !cubes.icmp[icmpPtr].Right.IsAll() { + icmpPtr++ + continue + } + + cubes, changed = reduce(cubes, tcpPtr, udpPtr, icmpPtr) + if changed { + continue + } + + tcpIP := cubes.tcp[tcpPtr].Left + udpIP := cubes.udp[udpPtr].Left + icmpIP := cubes.icmp[icmpPtr].Left + + if udpIP.IsSubset(tcpIP) && icmpIP.IsSubset(tcpIP) { + if optimize.LessIPBlock(udpIP, icmpIP) { + udpPtr++ + } else { + icmpPtr++ + } + continue + } + + } + return cubes +} + +func reduce(cubes *ipCubesPerProtocol, tcpPtr, udpPtr, icmpPtr int) (*ipCubesPerProtocol, bool) { + tcpIP := cubes.tcp[tcpPtr].Left + udpIP := cubes.udp[udpPtr].Left + icmpIP := cubes.icmp[icmpPtr].Left + + if udpIP.IsSubset(tcpIP) && udpIP.Equal(icmpIP) { + cubes.all = cubes.all.Union(udpIP) + slices.Delete(cubes.udp, udpPtr, udpPtr+1) + slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) + if tcpIP.Equal(udpIP) { + slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) + } + // continue + } + + if tcpIP.IsSubset(udpIP) && tcpIP.Equal(icmpIP) { + cubes.all = cubes.all.Union(udpIP) + slices.Delete(cubes.udp, udpPtr, udpPtr+1) + slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) + if tcpIP.Equal(udpIP) { + slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) + } + // continue + } + + return cubes, false +} diff --git a/pkg/optimize/sg/rulesToCubes.go b/pkg/optimize/sg/rulesToCubes.go new file mode 100644 index 00000000..84e28bd1 --- /dev/null +++ b/pkg/optimize/sg/rulesToCubes.go @@ -0,0 +1,106 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package sgoptimizer + +import ( + "github.com/np-guard/models/pkg/ds" + "github.com/np-guard/models/pkg/interval" + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" + "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" +) + +// calculate all cubes +func rulesToIPCubes(rules *rulesPerProtocol) *ipCubesPerProtocol { + tcpCubes := tcpudpRulesToIPCubes(rules.tcp) + udpCubes := tcpudpRulesToIPCubes(rules.udp) + icmpCubes := icmpRulesToIPCubes(rules.icmp) + allCubes := allProtocolRulesToIPCubes(rules.all) + return &ipCubesPerProtocol{tcp: tcpCubes, udp: udpCubes, icmp: icmpCubes, all: allCubes} +} + +func rulesToSGCubes(rules *rulesPerProtocol) *sgCubesPerProtocol { + tcpSpan := tcpudpRulesToSGToPortsSpan(rules.tcp) + udpSpan := tcpudpRulesToSGToPortsSpan(rules.udp) + icmpSpan := icmpRulesToSGToSpan(rules.icmp) + allSpan := allProtocolRulesToSGToSpan(rules.all) + return &sgCubesPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} +} + +// all protocol rules to cubes +func allProtocolRulesToIPCubes(rules []*ir.SGRule) *netset.IPBlock { + res := netset.NewIPBlock() + for i := range rules { + res.Union(rules[i].Remote.(*netset.IPBlock)) + } + return res +} + +func allProtocolRulesToSGToSpan(rules []*ir.SGRule) []ir.SGName { + result := make(map[ir.SGName]struct{}) + for i := range rules { + remote := rules[i].Remote.(ir.SGName) + result[remote] = struct{}{} + } + return utils.SortedMapKeys(result) +} + +// tcp/udp rules (separately) to cubes (IPBlock X portset). +func tcpudpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.PortSet] { + cubes := ds.NewProductLeft[*netset.IPBlock, *netset.PortSet]() + for _, rule := range rules { + ipb := rule.Remote.(*netset.IPBlock) // already checked + p := rule.Protocol.(netp.TCPUDP) // already checked + r := ds.CartesianPairLeft(ipb, p.DstPorts().ToSet()) + cubes = cubes.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.PortSet]) + } + return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) +} + +// tcp/udp rules to cubes -- map where the key is the SG name and the value is the protocol ports +func tcpudpRulesToSGToPortsSpan(rules []*ir.SGRule) map[ir.SGName]*netset.PortSet { + result := make(map[ir.SGName]*netset.PortSet) + for _, rule := range rules { + p := rule.Protocol.(netp.TCPUDP) // already checked + remote := rule.Remote.(ir.SGName) // already checked + if result[remote] == nil { + result[remote] = interval.NewCanonicalSet() + } + result[remote].AddInterval(p.DstPorts()) + } + return result +} + +// icmp rules to cubes (IPBlock X icmp set). +func icmpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.ICMPSet] { + cubes := ds.NewProductLeft[*netset.IPBlock, *netset.ICMPSet]() + for _, rule := range rules { + ipb := rule.Remote.(*netset.IPBlock) // already checked + p := rule.Protocol.(netp.ICMP) // already checked + icmpSet := optimize.IcmpRuleToIcmpSet(p) + r := ds.CartesianPairLeft(ipb, icmpSet) + cubes = cubes.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.ICMPSet]) + } + return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) +} + +// icmp rules to cubes -- map where the key is the SG name and the value is icmpset +func icmpRulesToSGToSpan(rules []*ir.SGRule) map[ir.SGName]*netset.ICMPSet { + result := make(map[ir.SGName]*netset.ICMPSet) + for _, rule := range rules { + p := rule.Protocol.(netp.ICMP) // already checked + remote := rule.Remote.(ir.SGName) // already checked + if result[remote] == nil { + result[remote] = netset.EmptyICMPSet() + } + icmpSet := optimize.IcmpRuleToIcmpSet(p) + result[remote] = result[remote].Union(icmpSet) + } + return result +} diff --git a/pkg/optimize/sg.go b/pkg/optimize/sg/sg.go similarity index 59% rename from pkg/optimize/sg.go rename to pkg/optimize/sg/sg.go index 10529236..7ddbafd3 100644 --- a/pkg/optimize/sg.go +++ b/pkg/optimize/sg/sg.go @@ -3,76 +3,71 @@ Copyright 2023- IBM Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package optimize +package sgoptimizer import ( "fmt" "log" "github.com/np-guard/models/pkg/ds" - "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) type ( - SGOptimizer struct { + sgOptimizer struct { sgCollection *ir.SGCollection sgName ir.SGName sgVPC *string } - sgRuleGroups struct { - rulesToSG *sgRulesPerProtocol - rulesToIPAddrs *sgRulesPerProtocol + ruleGroups struct { + sgRemoteRules *rulesPerProtocol + ipRemoteRules *rulesPerProtocol } - sgRulesPerProtocol struct { + rulesPerProtocol struct { tcp []*ir.SGRule udp []*ir.SGRule icmp []*ir.SGRule all []*ir.SGRule } - sgSpansToSGPerProtocol struct { - tcp map[ir.SGName]*interval.CanonicalSet - udp map[ir.SGName]*interval.CanonicalSet + sgCubesPerProtocol struct { + tcp map[ir.SGName]*netset.PortSet + udp map[ir.SGName]*netset.PortSet icmp map[ir.SGName]*netset.ICMPSet all []ir.SGName } - sgSpansToIPPerProtocol struct { - tcp []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] - udp []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] + ipCubesPerProtocol struct { + tcp []ds.Pair[*netset.IPBlock, *netset.PortSet] + udp []ds.Pair[*netset.IPBlock, *netset.PortSet] icmp []ds.Pair[*netset.IPBlock, *netset.ICMPSet] all *netset.IPBlock } ) -func NewSGOptimizer(collection ir.Collection, sgName string) Optimizer { +func NewSGOptimizer(collection ir.Collection, sgName string) optimize.Optimizer { components := ir.ScopingComponents(sgName) if len(components) == 1 { - return &SGOptimizer{sgCollection: collection.(*ir.SGCollection), sgName: ir.SGName(sgName), sgVPC: nil} + return &sgOptimizer{sgCollection: collection.(*ir.SGCollection), sgName: ir.SGName(sgName), sgVPC: nil} } - return &SGOptimizer{sgCollection: collection.(*ir.SGCollection), sgName: ir.SGName(components[1]), sgVPC: &components[0]} -} - -// returns a sorted slice of the vpc names -func (s *SGOptimizer) VpcNames() []string { - return utils.SortedMapKeys(s.sgCollection.SGs) + return &sgOptimizer{sgCollection: collection.(*ir.SGCollection), sgName: ir.SGName(components[1]), sgVPC: &components[0]} } // Optimize attempts to reduce the number of SG rules -// if -n was supplied, it will attempt to reduce the number of rules only in it +// if -n was supplied, it will attempt to reduce the number of rules only in the requested SG // otherwise, it will attempt to reduce the number of rules in all SGs -func (s *SGOptimizer) Optimize() (ir.Collection, error) { +func (s *sgOptimizer) Optimize() (ir.Collection, error) { if s.sgName != "" { for _, vpcName := range utils.SortedMapKeys(s.sgCollection.SGs) { if _, ok := s.sgCollection.SGs[vpcName][s.sgName]; ok { - s.OptimizeSG(vpcName, s.sgName) + s.optimizeSG(vpcName, s.sgName) return s.sgCollection, nil } } @@ -81,28 +76,28 @@ func (s *SGOptimizer) Optimize() (ir.Collection, error) { for _, vpcName := range utils.SortedMapKeys(s.sgCollection.SGs) { for _, sgName := range utils.SortedMapKeys(s.sgCollection.SGs[vpcName]) { - s.OptimizeSG(vpcName, sgName) + s.optimizeSG(vpcName, sgName) } } return s.sgCollection, nil } -// Optimize attempts to reduce the number of SG rules +// optimizeSG attempts to reduce the number of SG rules // the algorithm attempts to reduce both inbound and outbound rules separately // A message is printed to the log at the end of the algorithm -func (s *SGOptimizer) OptimizeSG(vpcName string, sgName ir.SGName) { +func (s *sgOptimizer) optimizeSG(vpcName string, sgName ir.SGName) { sg := s.sgCollection.SGs[vpcName][sgName] reducedRules := 0 // reduce inbound rules first - newInboundRules := s.reduceSGRules(sg.InboundRules, ir.Inbound) + newInboundRules := s.reduceRules(sg.InboundRules, ir.Inbound) if len(sg.InboundRules) > len(newInboundRules) { reducedRules += len(sg.InboundRules) - len(newInboundRules) s.sgCollection.SGs[vpcName][sgName].InboundRules = newInboundRules } // reduce outbound rules second - newOutboundRules := s.reduceSGRules(sg.OutboundRules, ir.Outbound) + newOutboundRules := s.reduceRules(sg.OutboundRules, ir.Outbound) if len(sg.OutboundRules) > len(newOutboundRules) { reducedRules += len(sg.OutboundRules) - len(newOutboundRules) s.sgCollection.SGs[vpcName][sgName].OutboundRules = newOutboundRules @@ -120,57 +115,58 @@ func (s *SGOptimizer) OptimizeSG(vpcName string, sgName ir.SGName) { } // reduceSGRules attempts to reduce the number of rules with different remote types separately -func (s *SGOptimizer) reduceSGRules(rules []*ir.SGRule, direction ir.Direction) []*ir.SGRule { +func (s *sgOptimizer) reduceRules(rules []*ir.SGRule, direction ir.Direction) []*ir.SGRule { // separate all rules to groups of (protocol X remote) ruleGroups := divideSGRules(rules) // rules with SG as a remote - optimizedRulesToSG := reduceSGRulesToSG(sgRulesToSGToSpans(ruleGroups.rulesToSG), direction) - if len(ruleGroups.rulesToSG.allRules()) < len(optimizedRulesToSG) { - optimizedRulesToSG = ruleGroups.rulesToSG.allRules() + optimizedRulesToSG := reduceRulesSGRemote(rulesToSGCubes(ruleGroups.sgRemoteRules), direction) + originlRulesToSG := ruleGroups.sgRemoteRules.allRules() + if len(originlRulesToSG) < len(optimizedRulesToSG) { // failed to reduce number of rules + optimizedRulesToSG = originlRulesToSG } // rules with IPBlock as a remote - optimizedRulesToIPAddrs := reduceSGRulesToIPAddrs(sgRulesToIPAddrsToSpans(ruleGroups.rulesToIPAddrs), direction) - if len(ruleGroups.rulesToIPAddrs.allRules()) < len(optimizedRulesToSG) { - optimizedRulesToIPAddrs = ruleGroups.rulesToIPAddrs.allRules() + optimizedRulesToIPAddrs := reduceRulesIPRemote(rulesToIPCubes(ruleGroups.ipRemoteRules), direction) + originalRulesToIPAddrs := ruleGroups.ipRemoteRules.allRules() + if len(originalRulesToIPAddrs) < len(optimizedRulesToSG) { // failed to reduce number of rules + optimizedRulesToIPAddrs = originalRulesToIPAddrs } - // append both slices together return append(optimizedRulesToSG, optimizedRulesToIPAddrs...) } -func reduceSGRulesToSG(spans *sgSpansToSGPerProtocol, direction ir.Direction) []*ir.SGRule { - spans = compressSpansToSG(spans) +func reduceRulesSGRemote(cubes *sgCubesPerProtocol, direction ir.Direction) []*ir.SGRule { + cubes = reduceSGCubes(cubes) - // convert spans to SG rules - tcpRules := tcpudpSGSpanToSGRules(spans.tcp, direction, true) - udpRules := tcpudpSGSpanToSGRules(spans.udp, direction, false) - icmpRules := icmpSGSpanToSGRules(spans.icmp, direction) - allRules := protocolAllSGSpanToSGRules(spans.all, direction) + // cubes to SG rules + tcpRules := tcpudpSGCubesToRules(cubes.tcp, direction, true) + udpRules := tcpudpSGCubesToRules(cubes.udp, direction, false) + icmpRules := icmpSGCubesToRules(cubes.icmp, direction) + allRules := protocolAllCubesToRules(cubes.all, direction) // return all rules return append(tcpRules, append(udpRules, append(icmpRules, allRules...)...)...) } -func reduceSGRulesToIPAddrs(spans *sgSpansToIPPerProtocol, direction ir.Direction) []*ir.SGRule { - spans = compressSpansToIP(spans) +func reduceRulesIPRemote(cubes *ipCubesPerProtocol, direction ir.Direction) []*ir.SGRule { + cubes = reduceIPCubes(cubes) - // spans to SG rules - tcpRules := tcpudpIPSpanToSGRules(spans.tcp, spans.all, direction, true) - udpRules := tcpudpIPSpanToSGRules(spans.udp, spans.all, direction, false) - icmpRules := icmpSpanToSGRules(spans.icmp, spans.all, direction) - allRules := allSpanIPToSGRules(spans.all, direction) + // cubes to SG rules + tcpRules := tcpudpIPCubesToRules(cubes.tcp, cubes.all, direction, true) + udpRules := tcpudpIPCubesToRules(cubes.udp, cubes.all, direction, false) + icmpRules := icmpIPCubesToRules(cubes.icmp, cubes.all, direction) + allRules := allProtocolIPCubesIPToRules(cubes.all, direction) // return all rules return append(tcpRules, append(udpRules, append(icmpRules, allRules...)...)...) } // divide SGCollection to TCP/UDP/ICMP/ProtocolALL X SGRemote/IPAddrs rules -func divideSGRules(rules []*ir.SGRule) *sgRuleGroups { - rulesToSG := &sgRulesPerProtocol{tcp: make([]*ir.SGRule, 0), udp: make([]*ir.SGRule, 0), +func divideSGRules(rules []*ir.SGRule) *ruleGroups { + rulesToSG := &rulesPerProtocol{tcp: make([]*ir.SGRule, 0), udp: make([]*ir.SGRule, 0), icmp: make([]*ir.SGRule, 0), all: make([]*ir.SGRule, 0)} - rulesToIPAddrs := &sgRulesPerProtocol{tcp: make([]*ir.SGRule, 0), udp: make([]*ir.SGRule, 0), + rulesToIPAddrs := &rulesPerProtocol{tcp: make([]*ir.SGRule, 0), udp: make([]*ir.SGRule, 0), icmp: make([]*ir.SGRule, 0), all: make([]*ir.SGRule, 0)} for _, rule := range rules { @@ -210,9 +206,9 @@ func divideSGRules(rules []*ir.SGRule) *sgRuleGroups { } } } - return &sgRuleGroups{rulesToSG: rulesToSG, rulesToIPAddrs: rulesToIPAddrs} + return &ruleGroups{sgRemoteRules: rulesToSG, ipRemoteRules: rulesToIPAddrs} } -func (s *sgRulesPerProtocol) allRules() []*ir.SGRule { +func (s *rulesPerProtocol) allRules() []*ir.SGRule { return append(s.tcp, append(s.udp, append(s.icmp, s.all...)...)...) } diff --git a/pkg/optimize/sgSpanToSGRules.go b/pkg/optimize/sg/sgCubesToRules.go similarity index 52% rename from pkg/optimize/sgSpanToSGRules.go rename to pkg/optimize/sg/sgCubesToRules.go index b3cc640d..0eb4bd12 100644 --- a/pkg/optimize/sgSpanToSGRules.go +++ b/pkg/optimize/sg/sgCubesToRules.go @@ -3,7 +3,7 @@ Copyright 2023- IBM Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package optimize +package sgoptimizer import ( "github.com/np-guard/models/pkg/interval" @@ -11,13 +11,14 @@ import ( "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" ) -// span (SGName X ports set) to SG rules -func tcpudpSGSpanToSGRules(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []*ir.SGRule { +// cubes (SGName X ports set) to SG rules +func tcpudpSGCubesToRules(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []*ir.SGRule { result := make([]*ir.SGRule, 0) - for sgName, intervals := range span { - for _, dstPorts := range intervals.Intervals() { + for sgName, portSet := range span { + for _, dstPorts := range portSet.Intervals() { p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) result = append(result, ir.NewSGRule(direction, sgName, p, netset.GetCidrAll(), "")) } @@ -25,20 +26,19 @@ func tcpudpSGSpanToSGRules(span map[ir.SGName]*interval.CanonicalSet, direction return result } -// span (SGName X icmp set) to SG rules -func icmpSGSpanToSGRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction) []*ir.SGRule { +// cubes (SGName X icmp set) to SG rules +func icmpSGCubesToRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction) []*ir.SGRule { result := make([]*ir.SGRule, 0) for sgName, icmpSet := range span { - for _, icmp := range icmpSet.Partitions() { - p, _ := netp.NewICMP(icmp.TypeCode) - result = append(result, ir.NewSGRule(direction, sgName, p, netset.GetCidrAll(), "")) + for _, icmp := range optimize.IcmpsetPartitions(icmpSet) { + result = append(result, ir.NewSGRule(direction, sgName, icmp, netset.GetCidrAll(), "")) } } return result } -// span (slice of SGs) to SG rules -func protocolAllSGSpanToSGRules(span []ir.SGName, direction ir.Direction) []*ir.SGRule { +// cubes (slice of SGs) to SG rules +func protocolAllCubesToRules(span []ir.SGName, direction ir.Direction) []*ir.SGRule { result := make([]*ir.SGRule, len(span)) for i, sgName := range span { result[i] = ir.NewSGRule(direction, sgName, netp.AnyProtocol{}, netset.GetCidrAll(), "") diff --git a/pkg/optimize/sgRulesToIPToSpan.go b/pkg/optimize/sgRulesToIPToSpan.go deleted file mode 100644 index af994076..00000000 --- a/pkg/optimize/sgRulesToIPToSpan.go +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package optimize - -import ( - "github.com/np-guard/models/pkg/ds" - "github.com/np-guard/models/pkg/interval" - "github.com/np-guard/models/pkg/netp" - "github.com/np-guard/models/pkg/netset" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" - "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" -) - -// calculate all spans and set them in sgRulesPerProtocol struct -func sgRulesToIPAddrsToSpans(rules *sgRulesPerProtocol) *sgSpansToIPPerProtocol { - tcpSpan := tcpudpRulesToIPAddrsToPortsSpan(rules.tcp) - udpSpan := tcpudpRulesToIPAddrsToPortsSpan(rules.udp) - icmpSpan := icmpRulesToIPAddrsToSpan(rules.icmp) - allSpan := allProtocolRulesToIPAddrsToSpan(rules.all) - return &sgSpansToIPPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} -} - -// all protocol rules to a span. The span will be splitted to disjoint CIDRs -func allProtocolRulesToIPAddrsToSpan(rules []*ir.SGRule) *netset.IPBlock { - res := netset.NewIPBlock() - for i := range rules { - res.Union(rules[i].Remote.(*netset.IPBlock)) - } - return res -} - -// tcp/udp rules (separately) to a span of (IPBlock X protocol ports). -// all IPBlocks are disjoint -func tcpudpRulesToIPAddrsToPortsSpan(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *interval.CanonicalSet] { - span := tcpudpMapSpan(rules) - result := ds.NewProductLeft[*netset.IPBlock, *interval.CanonicalSet]() - for ipblock, portsSet := range span { - r := ds.CartesianPairLeft(ipblock, portsSet) - result = result.Union(r).(*ds.ProductLeft[*netset.IPBlock, *interval.CanonicalSet]) - } - return sortPartitionsByIPAddrs(result.Partitions()) -} - -// icmp rules to a span of (IPBlock X icmp set). -// all IPBlocks are disjoint -func icmpRulesToIPAddrsToSpan(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.ICMPSet] { - span := icmpMapSpan((rules)) - result := ds.NewProductLeft[*netset.IPBlock, *netset.ICMPSet]() - for ipblock, icmpSet := range span { - r := ds.CartesianPairLeft(ipblock, icmpSet) - result = result.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.ICMPSet]) - } - return sortPartitionsByIPAddrs(result.Partitions()) -} - -/* ######################## */ -/* #### HELP FUNCTIONS #### */ -/* ######################## */ - -// tcp/udp rules to a span in a map format, where the key is the IPBlock and the value contains the protocol ports -// all ipblocks are disjoint -func tcpudpMapSpan(rules []*ir.SGRule) map[*netset.IPBlock]*interval.CanonicalSet { - span := make(map[*netset.IPBlock]*interval.CanonicalSet, 0) // all keys are disjoint - for i := range rules { - portsSet := rules[i].Protocol.(netp.TCPUDP).DstPorts().ToSet() // already checked - ruleIP := rules[i].Remote.(*netset.IPBlock) // already checked - span = updateSpan(span, portsSet, ruleIP) - } - return span -} - -// icmp rules to a span in a map format, where the key is the IPBlock and the value contains the icmp set -// all ipblocks are disjoint -func icmpMapSpan(rules []*ir.SGRule) map[*netset.IPBlock]*netset.ICMPSet { - span := make(map[*netset.IPBlock]*netset.ICMPSet, 0) // all keys are disjoint - for i := range rules { - icmpSet := netset.NewICMPSet(rules[i].Protocol.(netp.ICMP)) // already checked - ruleIP := rules[i].Remote.(*netset.IPBlock) // already checked - span = updateSpan(span, icmpSet, ruleIP) - } - return span -} - -// updateSpan gets the current span, and a rule details (IPBlock and a protocol set) -// if the IPBlock is already in the map, the new protocol set will be unioned with the existing one -// otherwise the rule will be added in the `addRuleToSpan` function. -func updateSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleSet T, ruleIP *netset.IPBlock) map[*netset.IPBlock]T { - if protocolSet, ok := span[ruleIP]; ok { - span[ruleIP] = protocolSet.Union(ruleSet) - return span - } - span, newMap := addRuleToSpan(span, ruleIP, ruleSet) - return utils.MergeSetMaps(span, newMap) -} - -// any IPblock that overlaps with the new ipblock: -// 1. will be deleted from the new map -// 2. will be splitted into two parts: the part overlapping with the new ipblock and the part that is not -// a. the overlapping part will enter the new map, where the existing set will be unioned with the new set -// b. the non overlapping part will enter the new map with the same value he had. -func addRuleToSpan[T ds.Set[T]](span map[*netset.IPBlock]T, ruleIP *netset.IPBlock, ruleSet T) (s, res map[*netset.IPBlock]T) { - res = make(map[*netset.IPBlock]T, 0) - uncovered := ruleIP.Copy() - for ipblock := range span { - if !ipblock.Overlap(ruleIP) { - continue - } - uncovered = uncovered.Subtract(ipblock) - - overlappingIPs := ruleIP.Subtract(ipblock) - for _, ip := range overlappingIPs.Split() { - res[ip] = span[ipblock].Copy().Union(ruleSet) - } - notOverlappingIPs := ipblock.Subtract(overlappingIPs) - for _, ip := range notOverlappingIPs.Split() { - res[ip] = span[ipblock].Copy() - } - delete(span, ipblock) - } - res[uncovered] = ruleSet.Copy() - return span, res -} diff --git a/pkg/optimize/sgRulesToSGToSpan.go b/pkg/optimize/sgRulesToSGToSpan.go deleted file mode 100644 index d71c6df8..00000000 --- a/pkg/optimize/sgRulesToSGToSpan.go +++ /dev/null @@ -1,66 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package optimize - -import ( - "fmt" - - "github.com/np-guard/models/pkg/interval" - "github.com/np-guard/models/pkg/netp" - "github.com/np-guard/models/pkg/netset" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" - "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" -) - -// calculate all spans and set them in sgRulesPerProtocol struct -func sgRulesToSGToSpans(rules *sgRulesPerProtocol) *sgSpansToSGPerProtocol { - tcpSpan := tcpudpRulesToSGToPortsSpan(rules.tcp) - udpSpan := tcpudpRulesToSGToPortsSpan(rules.udp) - icmpSpan := icmpRulesToSGToSpan(rules.icmp) - allSpan := allProtocolRulesToSGToSpan(rules.all) - return &sgSpansToSGPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} -} - -// tcp/udp rules to a span -- map where the key is the SG name and the value is the protocol ports -func tcpudpRulesToSGToPortsSpan(rules []*ir.SGRule) map[ir.SGName]*interval.CanonicalSet { - result := make(map[ir.SGName]*interval.CanonicalSet) - for i := range rules { - p := rules[i].Protocol.(netp.TCPUDP) // already checked - remote := rules[i].Remote.(ir.SGName) // already checked - if result[remote] == nil { - result[remote] = interval.NewCanonicalSet() - } - result[remote].AddInterval(p.DstPorts()) - } - return result -} - -// icmp rules to a span -- map where the key is the SG name and the value is icmp set -func icmpRulesToSGToSpan(rules []*ir.SGRule) map[ir.SGName]*netset.ICMPSet { - result := make(map[ir.SGName]*netset.ICMPSet) - for i := range rules { - p := rules[i].Protocol.(netp.ICMP) // already checked - remote := rules[i].Remote.(ir.SGName) // already checked - if result[remote] == nil { - result[remote] = netset.EmptyICMPSet() - } - result[remote] = result[remote].Union(netset.NewICMPSet(p)) - - fmt.Println("i=", i, ": num partitions=", len(result[remote].Partitions())) - } - return result -} - -// all protocol rules to a span of SG names slice -func allProtocolRulesToSGToSpan(rules []*ir.SGRule) []ir.SGName { - result := make(map[ir.SGName]struct{}) - for i := range rules { - remote := rules[i].Remote.(ir.SGName) - result[remote] = struct{}{} - } - return utils.SortedMapKeys(result) -} diff --git a/test/data/optimize_sg_icmp_codes/config_object.json b/test/data/optimize_sg_icmp_codes/config_object.json deleted file mode 100644 index d059fc05..00000000 --- a/test/data/optimize_sg_icmp_codes/config_object.json +++ /dev/null @@ -1,2169 +0,0 @@ -{ - "collector_version": "0.11.0", - "provider": "ibm", - "vpcs": [ - { - "classic_access": false, - "created_at": "2024-09-09T09:09:50.000Z", - "crn": "crn:1", - "cse_source_ips": [ - { - "ip": { - "address": "10.22.217.112" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - } - }, - { - "ip": { - "address": "10.12.160.153" - }, - "zone": { - "href": "href:6", - "name": "us-south-2" - } - }, - { - "ip": { - "address": "10.16.253.223" - }, - "zone": { - "href": "href:7", - "name": "us-south-3" - } - } - ], - "default_network_acl": { - "crn": "crn:8", - "href": "href:9", - "id": "id:10", - "name": "capitol-siren-chirpy-doornail" - }, - "default_routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "default_security_group": { - "crn": "crn:13", - "href": "href:14", - "id": "id:15", - "name": "wombat-hesitate-scorn-subprime" - }, - "dns": { - "enable_hub": false, - "resolution_binding_count": 0, - "resolver": { - "servers": [ - { - "address": "161.26.0.10" - }, - { - "address": "161.26.0.11" - } - ], - "type": "system", - "configuration": "default" - } - }, - "health_reasons": null, - "health_state": "ok", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "vpc", - "status": "available", - "region": "us-south", - "address_prefixes": [ - { - "cidr": "10.240.0.0/18", - "created_at": "2024-09-09T09:09:50.000Z", - "has_subnets": true, - "href": "href:18", - "id": "id:19", - "is_default": true, - "name": "filling-tasty-bacterium-parlor", - "zone": { - "href": "href:5", - "name": "us-south-1" - } - }, - { - "cidr": "10.240.64.0/18", - "created_at": "2024-09-09T09:09:50.000Z", - "has_subnets": false, - "href": "href:20", - "id": "id:21", - "is_default": true, - "name": "relearn-ragweed-goon-feisty", - "zone": { - "href": "href:6", - "name": "us-south-2" - } - }, - { - "cidr": "10.240.128.0/18", - "created_at": "2024-09-09T09:09:50.000Z", - "has_subnets": false, - "href": "href:22", - "id": "id:23", - "is_default": true, - "name": "unruffled-penknife-snowshoe-ninetieth", - "zone": { - "href": "href:7", - "name": "us-south-3" - } - } - ], - "tags": [] - } - ], - "subnets": [ - { - "available_ipv4_address_count": 250, - "created_at": "2024-09-09T09:10:51.000Z", - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "ip_version": "ipv4", - "ipv4_cidr_block": "10.240.20.0/24", - "name": "subnet2", - "network_acl": { - "crn": "crn:27", - "href": "href:28", - "id": "id:29", - "name": "acl2" - }, - "public_gateway": { - "crn": "crn:30", - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_type": "public_gateway" - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "subnet", - "routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "status": "available", - "total_ipv4_address_count": 256, - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "reserved_ips": [ - { - "address": "10.240.20.0", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:33", - "id": "id:34", - "lifecycle_state": "stable", - "name": "ibm-network-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.1", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:35", - "id": "id:36", - "lifecycle_state": "stable", - "name": "ibm-default-gateway", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.2", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:37", - "id": "id:38", - "lifecycle_state": "stable", - "name": "ibm-dns-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.3", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:39", - "id": "id:40", - "lifecycle_state": "stable", - "name": "ibm-reserved-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.4", - "auto_delete": true, - "created_at": "2024-09-09T09:11:08.000Z", - "href": "href:41", - "id": "id:42", - "lifecycle_state": "stable", - "name": "startle-percent-embellish-squeegee", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:43", - "id": "id:44", - "name": "ni2", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.20.255", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:45", - "id": "id:46", - "lifecycle_state": "stable", - "name": "ibm-broadcast-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - } - ], - "tags": [] - }, - { - "available_ipv4_address_count": 250, - "created_at": "2024-09-09T09:10:35.000Z", - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "ip_version": "ipv4", - "ipv4_cidr_block": "10.240.10.0/24", - "name": "subnet1", - "network_acl": { - "crn": "crn:50", - "href": "href:51", - "id": "id:52", - "name": "acl1" - }, - "public_gateway": { - "crn": "crn:30", - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_type": "public_gateway" - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "subnet", - "routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "status": "available", - "total_ipv4_address_count": 256, - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "reserved_ips": [ - { - "address": "10.240.10.0", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:53", - "id": "id:54", - "lifecycle_state": "stable", - "name": "ibm-network-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.1", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:55", - "id": "id:56", - "lifecycle_state": "stable", - "name": "ibm-default-gateway", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.2", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:57", - "id": "id:58", - "lifecycle_state": "stable", - "name": "ibm-dns-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.3", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:59", - "id": "id:60", - "lifecycle_state": "stable", - "name": "ibm-reserved-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.4", - "auto_delete": true, - "created_at": "2024-09-09T09:10:52.000Z", - "href": "href:61", - "id": "id:62", - "lifecycle_state": "stable", - "name": "tableware-sprawl-shrivel-popper", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.10.255", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:65", - "id": "id:66", - "lifecycle_state": "stable", - "name": "ibm-broadcast-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - } - ], - "tags": [] - }, - { - "available_ipv4_address_count": 249, - "created_at": "2024-09-09T09:10:18.000Z", - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "ip_version": "ipv4", - "ipv4_cidr_block": "10.240.30.0/24", - "name": "subnet3", - "network_acl": { - "crn": "crn:70", - "href": "href:71", - "id": "id:72", - "name": "acl3" - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "subnet", - "routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "status": "available", - "total_ipv4_address_count": 256, - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "reserved_ips": [ - { - "address": "10.240.30.0", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:73", - "id": "id:74", - "lifecycle_state": "stable", - "name": "ibm-network-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.1", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:75", - "id": "id:76", - "lifecycle_state": "stable", - "name": "ibm-default-gateway", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.2", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:77", - "id": "id:78", - "lifecycle_state": "stable", - "name": "ibm-dns-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.3", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:79", - "id": "id:80", - "lifecycle_state": "stable", - "name": "ibm-reserved-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.4", - "auto_delete": true, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:81", - "id": "id:82", - "lifecycle_state": "stable", - "name": "disallow-oxidant-etching-selection", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.30.5", - "auto_delete": true, - "created_at": "2024-09-09T09:10:36.000Z", - "href": "href:85", - "id": "id:86", - "lifecycle_state": "stable", - "name": "reheat-joyride-little-overprice", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.30.255", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:89", - "id": "id:90", - "lifecycle_state": "stable", - "name": "ibm-broadcast-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - } - ], - "tags": [] - } - ], - "public_gateways": [ - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:30", - "floating_ip": { - "address": "52.118.147.142", - "crn": "crn:91", - "href": "href:92", - "id": "id:93", - "name": "public-gw1" - }, - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "public_gateway", - "status": "available", - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "tags": [] - } - ], - "floating_ips": [ - { - "address": "52.116.129.168", - "created_at": "2024-09-09T09:11:31.000Z", - "crn": "crn:94", - "href": "href:95", - "id": "id:96", - "name": "vsi1-fip", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "status": "available", - "target": { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "primary_ip": { - "address": "10.240.10.4", - "href": "href:61", - "id": "id:62", - "name": "tableware-sprawl-shrivel-popper", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "tags": [] - }, - { - "address": "52.118.147.142", - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:91", - "href": "href:92", - "id": "id:93", - "name": "public-gw1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "status": "available", - "target": { - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_type": "public_gateway", - "crn": "crn:30" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "tags": [] - } - ], - "network_acls": [ - { - "created_at": "2024-09-09T09:10:15.000Z", - "crn": "crn:27", - "href": "href:28", - "id": "id:29", - "name": "acl2", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:99", - "id": "id:100", - "name": "acl2-out-2" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "0.0.0.0/0", - "direction": "outbound", - "href": "href:97", - "id": "id:98", - "ip_version": "ipv4", - "name": "acl2-out-1", - "source": "10.240.20.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:101", - "id": "id:102", - "name": "acl2-in-1" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.10.0/24", - "direction": "outbound", - "href": "href:99", - "id": "id:100", - "ip_version": "ipv4", - "name": "acl2-out-2", - "source": "10.240.20.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:103", - "id": "id:104", - "name": "acl2-in-2" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.20.0/24", - "direction": "inbound", - "href": "href:101", - "id": "id:102", - "ip_version": "ipv4", - "name": "acl2-in-1", - "source": "0.0.0.0/0", - "protocol": "all" - }, - { - "action": "allow", - "created_at": "2024-09-09T09:10:17.000Z", - "destination": "10.240.20.0/24", - "direction": "inbound", - "href": "href:103", - "id": "id:104", - "ip_version": "ipv4", - "name": "acl2-in-2", - "source": "10.240.10.0/24", - "protocol": "all" - } - ], - "subnets": [ - { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:50", - "href": "href:51", - "id": "id:52", - "name": "acl1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:107", - "id": "id:108", - "name": "acl1-out-2" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "172.217.22.46/32", - "direction": "outbound", - "href": "href:105", - "id": "id:106", - "ip_version": "ipv4", - "name": "acl1-out-1", - "source": "10.240.10.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:109", - "id": "id:110", - "name": "acl1-out-3" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.20.0/24", - "direction": "outbound", - "href": "href:107", - "id": "id:108", - "ip_version": "ipv4", - "name": "acl1-out-2", - "source": "10.240.10.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:111", - "id": "id:112", - "name": "acl1-out-4" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "outbound", - "href": "href:109", - "id": "id:110", - "ip_version": "ipv4", - "name": "acl1-out-3", - "source": "10.240.10.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - }, - { - "action": "allow", - "before": { - "href": "href:113", - "id": "id:114", - "name": "acl1-in-1" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "outbound", - "href": "href:111", - "id": "id:112", - "ip_version": "ipv4", - "name": "acl1-out-4", - "source": "10.240.10.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - }, - { - "action": "allow", - "before": { - "href": "href:115", - "id": "id:116", - "name": "acl1-in-2" - }, - "created_at": "2024-09-09T09:10:17.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:113", - "id": "id:114", - "ip_version": "ipv4", - "name": "acl1-in-1", - "source": "172.217.22.46/32", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:117", - "id": "id:118", - "name": "acl1-in-3" - }, - "created_at": "2024-09-09T09:10:17.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:115", - "id": "id:116", - "ip_version": "ipv4", - "name": "acl1-in-2", - "source": "10.240.20.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:119", - "id": "id:120", - "name": "acl1-in-4" - }, - "created_at": "2024-09-09T09:10:18.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:117", - "id": "id:118", - "ip_version": "ipv4", - "name": "acl1-in-3", - "source": "10.240.30.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - }, - { - "action": "allow", - "created_at": "2024-09-09T09:10:18.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:119", - "id": "id:120", - "ip_version": "ipv4", - "name": "acl1-in-4", - "source": "10.240.30.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - } - ], - "subnets": [ - { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:70", - "href": "href:71", - "id": "id:72", - "name": "acl3", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:123", - "id": "id:124", - "name": "acl3-out-2" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "10.240.10.0/24", - "direction": "outbound", - "href": "href:121", - "id": "id:122", - "ip_version": "ipv4", - "name": "acl3-out-1", - "source": "10.240.30.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - }, - { - "action": "allow", - "before": { - "href": "href:125", - "id": "id:126", - "name": "acl3-in-1" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "10.240.10.0/24", - "direction": "outbound", - "href": "href:123", - "id": "id:124", - "ip_version": "ipv4", - "name": "acl3-out-2", - "source": "10.240.30.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - }, - { - "action": "allow", - "before": { - "href": "href:127", - "id": "id:128", - "name": "acl3-in-2" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "inbound", - "href": "href:125", - "id": "id:126", - "ip_version": "ipv4", - "name": "acl3-in-1", - "source": "10.240.10.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - }, - { - "action": "allow", - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "inbound", - "href": "href:127", - "id": "id:128", - "ip_version": "ipv4", - "name": "acl3-in-2", - "source": "10.240.10.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - } - ], - "subnets": [ - { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:09:50.000Z", - "crn": "crn:8", - "href": "href:9", - "id": "id:10", - "name": "capitol-siren-chirpy-doornail", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:131", - "id": "id:132", - "name": "allow-outbound" - }, - "created_at": "2024-09-09T09:09:50.000Z", - "destination": "0.0.0.0/0", - "direction": "inbound", - "href": "href:129", - "id": "id:130", - "ip_version": "ipv4", - "name": "allow-inbound", - "source": "0.0.0.0/0", - "protocol": "all" - }, - { - "action": "allow", - "created_at": "2024-09-09T09:09:50.000Z", - "destination": "0.0.0.0/0", - "direction": "outbound", - "href": "href:131", - "id": "id:132", - "ip_version": "ipv4", - "name": "allow-outbound", - "source": "0.0.0.0/0", - "protocol": "all" - } - ], - "subnets": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - } - ], - "security_groups": [ - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:133", - "href": "href:134", - "id": "id:135", - "name": "sg1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "inbound", - "href": "href:136", - "id": "id:137", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/0" - }, - "protocol": "all" - }, - { - "direction": "outbound", - "href": "href:138", - "id": "id:139", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/0" - }, - "protocol": "all" - } - ], - "targets": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:09:50.000Z", - "crn": "crn:13", - "href": "href:14", - "id": "id:15", - "name": "wombat-hesitate-scorn-subprime", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "outbound", - "href": "href:140", - "id": "id:141", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/0" - }, - "protocol": "all" - }, - { - "direction": "inbound", - "href": "href:142", - "id": "id:143", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "crn:13", - "href": "href:14", - "id": "id:15", - "name": "wombat-hesitate-scorn-subprime" - }, - "protocol": "all" - } - ], - "targets": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:6", - "href": "fake:href:6", - "id": "fake:id:6", - "name": "test-vpc1--vsi2", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "inbound", - "href": "fake:href:1", - "id": "fake:id:1", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "code": 0, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "inbound", - "href": "fake:href:3", - "id": "fake:id:3", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "code": 1, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "inbound", - "href": "fake:href:4", - "id": "fake:id:4", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "code": 2, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "inbound", - "href": "fake:href:5", - "id": "fake:id:5", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "code": 3, - "protocol": "icmp", - "type": 5 - } - ], - "targets": [ - { - "href": "href:43", - "id": "id:44", - "name": "ni2", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "outbound", - "href": "fake:href:7", - "id": "fake:id:7", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "code": 0, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:8", - "id": "fake:id:8", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "code": 1, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:9", - "id": "fake:id:9", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "code": 2, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:10", - "id": "fake:id:10", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "code": 3, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:11", - "id": "fake:id:11", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:6", - "href": "fake:href:6", - "id": "fake:id:6", - "name": "test-vpc1--vsi2" - }, - "code": 0, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:12", - "id": "fake:id:12", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:6", - "href": "fake:href:6", - "id": "fake:id:6", - "name": "test-vpc1--vsi2" - }, - "code": 1, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:13", - "id": "fake:id:13", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:6", - "href": "fake:href:6", - "id": "fake:id:6", - "name": "test-vpc1--vsi2" - }, - "code": 2, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:14", - "id": "fake:id:14", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:6", - "href": "fake:href:6", - "id": "fake:id:6", - "name": "test-vpc1--vsi2" - }, - "code": 3, - "protocol": "icmp", - "type": 5 - } - ], - "targets": [ - { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:15", - "href": "fake:href:15", - "id": "fake:id:15", - "name": "test-vpc1--vsi3b", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [], - "targets": [ - { - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:16", - "href": "fake:href:16", - "id": "fake:id:16", - "name": "test-vpc1--vsi3a", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [], - "targets": [ - { - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - } - ], - "endpoint_gateways": [], - "instances": [ - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:149" - }, - "href": "href:147", - "id": "id:148", - "name": "falsetto-snowstorm-bankbook-agreement", - "volume": { - "crn": "crn:150", - "href": "href:151", - "id": "id:152", - "name": "prawn-trusting-pasty-dental", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:11:07.000Z", - "crn": "crn:144", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:145", - "id": "id:146", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi2", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:43", - "id": "id:44", - "name": "ni2", - "primary_ip": { - "address": "10.240.20.4", - "href": "href:41", - "id": "id:42", - "name": "startle-percent-embellish-squeegee", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:149" - }, - "href": "href:147", - "id": "id:148", - "name": "falsetto-snowstorm-bankbook-agreement", - "volume": { - "crn": "crn:150", - "href": "href:151", - "id": "id:152", - "name": "prawn-trusting-pasty-dental", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:11:07.000Z", - "floating_ips": [], - "href": "href:43", - "id": "id:44", - "name": "ni2", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.20.4", - "href": "href:41", - "id": "id:42", - "name": "startle-percent-embellish-squeegee", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:6", - "href": "fake:href:6", - "id": "fake:id:6", - "name": "test-vpc1--vsi2" - } - ], - "status": "available", - "subnet": { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - }, - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:162" - }, - "href": "href:160", - "id": "id:161", - "name": "outskirts-oversized-roundish-ludicrous", - "volume": { - "crn": "crn:163", - "href": "href:164", - "id": "id:165", - "name": "family-tackling-foothold-train", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:10:52.000Z", - "crn": "crn:157", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:158", - "id": "id:159", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi1", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "primary_ip": { - "address": "10.240.10.4", - "href": "href:61", - "id": "id:62", - "name": "tableware-sprawl-shrivel-popper", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:162" - }, - "href": "href:160", - "id": "id:161", - "name": "outskirts-oversized-roundish-ludicrous", - "volume": { - "crn": "crn:163", - "href": "href:164", - "id": "id:165", - "name": "family-tackling-foothold-train", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:10:52.000Z", - "floating_ips": [ - { - "address": "52.116.129.168", - "crn": "crn:94", - "href": "href:95", - "id": "id:96", - "name": "vsi1-fip" - } - ], - "href": "href:63", - "id": "id:64", - "name": "ni1", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.10.4", - "href": "href:61", - "id": "id:62", - "name": "tableware-sprawl-shrivel-popper", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - } - ], - "status": "available", - "subnet": { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - }, - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:171" - }, - "href": "href:169", - "id": "id:170", - "name": "camera-yam-headfirst-scabiosa", - "volume": { - "crn": "crn:172", - "href": "href:173", - "id": "id:174", - "name": "sprinkler-avenue-playset-dislodge", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:10:35.000Z", - "crn": "crn:166", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:167", - "id": "id:168", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi3b", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "primary_ip": { - "address": "10.240.30.5", - "href": "href:85", - "id": "id:86", - "name": "reheat-joyride-little-overprice", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:171" - }, - "href": "href:169", - "id": "id:170", - "name": "camera-yam-headfirst-scabiosa", - "volume": { - "crn": "crn:172", - "href": "href:173", - "id": "id:174", - "name": "sprinkler-avenue-playset-dislodge", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:10:34.000Z", - "floating_ips": [], - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.30.5", - "href": "href:85", - "id": "id:86", - "name": "reheat-joyride-little-overprice", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:15", - "href": "fake:href:15", - "id": "fake:id:15", - "name": "test-vpc1--vsi3b" - } - ], - "status": "available", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - }, - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:180" - }, - "href": "href:178", - "id": "id:179", - "name": "cryptic-cork-saponify-lively", - "volume": { - "crn": "crn:181", - "href": "href:182", - "id": "id:183", - "name": "appraisal-mountains-itinerary-twine", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:10:34.000Z", - "crn": "crn:175", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:176", - "id": "id:177", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi3a", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "primary_ip": { - "address": "10.240.30.4", - "href": "href:81", - "id": "id:82", - "name": "disallow-oxidant-etching-selection", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:180" - }, - "href": "href:178", - "id": "id:179", - "name": "cryptic-cork-saponify-lively", - "volume": { - "crn": "crn:181", - "href": "href:182", - "id": "id:183", - "name": "appraisal-mountains-itinerary-twine", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:10:34.000Z", - "floating_ips": [], - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.30.4", - "href": "href:81", - "id": "id:82", - "name": "disallow-oxidant-etching-selection", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:16", - "href": "fake:href:16", - "id": "fake:id:16", - "name": "test-vpc1--vsi3a" - } - ], - "status": "available", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - } - ], - "virtual_nis": null, - "routing_tables": [ - { - "accept_routes_from": [ - { - "resource_type": "vpn_gateway" - }, - { - "resource_type": "vpn_server" - } - ], - "advertise_routes_to": [], - "created_at": "2024-09-09T09:09:51.000Z", - "href": "href:11", - "id": "id:12", - "is_default": true, - "lifecycle_state": "stable", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table", - "route_direct_link_ingress": false, - "route_internet_ingress": false, - "route_transit_gateway_ingress": false, - "route_vpc_zone_ingress": false, - "subnets": [ - { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - }, - { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - }, - { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - ], - "routes": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - } - } - ], - "load_balancers": [], - "transit_connections": null, - "transit_gateways": null, - "iks_clusters": [] -} \ No newline at end of file diff --git a/test/data/optimize_sg_icmp_codes/conn_spec.json b/test/data/optimize_sg_icmp_codes/conn_spec.json deleted file mode 100644 index 83342736..00000000 --- a/test/data/optimize_sg_icmp_codes/conn_spec.json +++ /dev/null @@ -1,143 +0,0 @@ -{ - "externals": { - "e1": "0.0.0.0/31" - }, - "required-connections": [ - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 0 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 1 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 2 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 3 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 0 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 1 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 2 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5, - "code": 3 - } - ] - } - ] -} diff --git a/test/data/optimize_sg_icmp_codes/details.txt b/test/data/optimize_sg_icmp_codes/details.txt deleted file mode 100644 index ac439dbe..00000000 --- a/test/data/optimize_sg_icmp_codes/details.txt +++ /dev/null @@ -1,14 +0,0 @@ -vsi1 --> 0.0.0.0/31 (icmp type:5 code:0) -vsi1 --> 0.0.0.0/31 (icmp type:5 code:1) -vsi1 --> 0.0.0.0/31 (icmp type:5 code:2) -vsi1 --> 0.0.0.0/31 (icmp type:5 code:3) - -vsi1 --> vsi2 (icmp type:5 code:0) -vsi1 --> vsi2 (icmp type:5 code:1) -vsi1 --> vsi2 (icmp type:5 code:2) -vsi1 --> vsi2 (icmp type:5 code:3) - -==================================== - -vsi1 --> 0.0.0.0/31 (icmp type:5) -vsi1 --> vsi2 (icmp type:5) \ No newline at end of file diff --git a/test/data/optimize_sg_icmp_types/config_object.json b/test/data/optimize_sg_icmp_types/config_object.json deleted file mode 100644 index 0511af0e..00000000 --- a/test/data/optimize_sg_icmp_types/config_object.json +++ /dev/null @@ -1,2493 +0,0 @@ -{ - "collector_version": "0.11.0", - "provider": "ibm", - "vpcs": [ - { - "classic_access": false, - "created_at": "2024-09-09T09:09:50.000Z", - "crn": "crn:1", - "cse_source_ips": [ - { - "ip": { - "address": "10.22.217.112" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - } - }, - { - "ip": { - "address": "10.12.160.153" - }, - "zone": { - "href": "href:6", - "name": "us-south-2" - } - }, - { - "ip": { - "address": "10.16.253.223" - }, - "zone": { - "href": "href:7", - "name": "us-south-3" - } - } - ], - "default_network_acl": { - "crn": "crn:8", - "href": "href:9", - "id": "id:10", - "name": "capitol-siren-chirpy-doornail" - }, - "default_routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "default_security_group": { - "crn": "crn:13", - "href": "href:14", - "id": "id:15", - "name": "wombat-hesitate-scorn-subprime" - }, - "dns": { - "enable_hub": false, - "resolution_binding_count": 0, - "resolver": { - "servers": [ - { - "address": "161.26.0.10" - }, - { - "address": "161.26.0.11" - } - ], - "type": "system", - "configuration": "default" - } - }, - "health_reasons": null, - "health_state": "ok", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "vpc", - "status": "available", - "region": "us-south", - "address_prefixes": [ - { - "cidr": "10.240.0.0/18", - "created_at": "2024-09-09T09:09:50.000Z", - "has_subnets": true, - "href": "href:18", - "id": "id:19", - "is_default": true, - "name": "filling-tasty-bacterium-parlor", - "zone": { - "href": "href:5", - "name": "us-south-1" - } - }, - { - "cidr": "10.240.64.0/18", - "created_at": "2024-09-09T09:09:50.000Z", - "has_subnets": false, - "href": "href:20", - "id": "id:21", - "is_default": true, - "name": "relearn-ragweed-goon-feisty", - "zone": { - "href": "href:6", - "name": "us-south-2" - } - }, - { - "cidr": "10.240.128.0/18", - "created_at": "2024-09-09T09:09:50.000Z", - "has_subnets": false, - "href": "href:22", - "id": "id:23", - "is_default": true, - "name": "unruffled-penknife-snowshoe-ninetieth", - "zone": { - "href": "href:7", - "name": "us-south-3" - } - } - ], - "tags": [] - } - ], - "subnets": [ - { - "available_ipv4_address_count": 250, - "created_at": "2024-09-09T09:10:51.000Z", - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "ip_version": "ipv4", - "ipv4_cidr_block": "10.240.20.0/24", - "name": "subnet2", - "network_acl": { - "crn": "crn:27", - "href": "href:28", - "id": "id:29", - "name": "acl2" - }, - "public_gateway": { - "crn": "crn:30", - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_type": "public_gateway" - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "subnet", - "routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "status": "available", - "total_ipv4_address_count": 256, - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "reserved_ips": [ - { - "address": "10.240.20.0", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:33", - "id": "id:34", - "lifecycle_state": "stable", - "name": "ibm-network-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.1", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:35", - "id": "id:36", - "lifecycle_state": "stable", - "name": "ibm-default-gateway", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.2", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:37", - "id": "id:38", - "lifecycle_state": "stable", - "name": "ibm-dns-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.3", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:39", - "id": "id:40", - "lifecycle_state": "stable", - "name": "ibm-reserved-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.20.4", - "auto_delete": true, - "created_at": "2024-09-09T09:11:08.000Z", - "href": "href:41", - "id": "id:42", - "lifecycle_state": "stable", - "name": "startle-percent-embellish-squeegee", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:43", - "id": "id:44", - "name": "ni2", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.20.255", - "auto_delete": false, - "created_at": "2024-09-09T09:10:51.000Z", - "href": "href:45", - "id": "id:46", - "lifecycle_state": "stable", - "name": "ibm-broadcast-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - } - ], - "tags": [] - }, - { - "available_ipv4_address_count": 250, - "created_at": "2024-09-09T09:10:35.000Z", - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "ip_version": "ipv4", - "ipv4_cidr_block": "10.240.10.0/24", - "name": "subnet1", - "network_acl": { - "crn": "crn:50", - "href": "href:51", - "id": "id:52", - "name": "acl1" - }, - "public_gateway": { - "crn": "crn:30", - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_type": "public_gateway" - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "subnet", - "routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "status": "available", - "total_ipv4_address_count": 256, - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "reserved_ips": [ - { - "address": "10.240.10.0", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:53", - "id": "id:54", - "lifecycle_state": "stable", - "name": "ibm-network-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.1", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:55", - "id": "id:56", - "lifecycle_state": "stable", - "name": "ibm-default-gateway", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.2", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:57", - "id": "id:58", - "lifecycle_state": "stable", - "name": "ibm-dns-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.3", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:59", - "id": "id:60", - "lifecycle_state": "stable", - "name": "ibm-reserved-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.10.4", - "auto_delete": true, - "created_at": "2024-09-09T09:10:52.000Z", - "href": "href:61", - "id": "id:62", - "lifecycle_state": "stable", - "name": "tableware-sprawl-shrivel-popper", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.10.255", - "auto_delete": false, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:65", - "id": "id:66", - "lifecycle_state": "stable", - "name": "ibm-broadcast-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - } - ], - "tags": [] - }, - { - "available_ipv4_address_count": 249, - "created_at": "2024-09-09T09:10:18.000Z", - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "ip_version": "ipv4", - "ipv4_cidr_block": "10.240.30.0/24", - "name": "subnet3", - "network_acl": { - "crn": "crn:70", - "href": "href:71", - "id": "id:72", - "name": "acl3" - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "subnet", - "routing_table": { - "href": "href:11", - "id": "id:12", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table" - }, - "status": "available", - "total_ipv4_address_count": 256, - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "reserved_ips": [ - { - "address": "10.240.30.0", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:73", - "id": "id:74", - "lifecycle_state": "stable", - "name": "ibm-network-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.1", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:75", - "id": "id:76", - "lifecycle_state": "stable", - "name": "ibm-default-gateway", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.2", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:77", - "id": "id:78", - "lifecycle_state": "stable", - "name": "ibm-dns-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.3", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:79", - "id": "id:80", - "lifecycle_state": "stable", - "name": "ibm-reserved-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - }, - { - "address": "10.240.30.4", - "auto_delete": true, - "created_at": "2024-09-09T09:10:35.000Z", - "href": "href:81", - "id": "id:82", - "lifecycle_state": "stable", - "name": "disallow-oxidant-etching-selection", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.30.5", - "auto_delete": true, - "created_at": "2024-09-09T09:10:36.000Z", - "href": "href:85", - "id": "id:86", - "lifecycle_state": "stable", - "name": "reheat-joyride-little-overprice", - "owner": "user", - "resource_type": "subnet_reserved_ip", - "target": { - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "resource_type": "network_interface" - } - }, - { - "address": "10.240.30.255", - "auto_delete": false, - "created_at": "2024-09-09T09:10:18.000Z", - "href": "href:89", - "id": "id:90", - "lifecycle_state": "stable", - "name": "ibm-broadcast-address", - "owner": "provider", - "resource_type": "subnet_reserved_ip" - } - ], - "tags": [] - } - ], - "public_gateways": [ - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:30", - "floating_ip": { - "address": "52.118.147.142", - "crn": "crn:91", - "href": "href:92", - "id": "id:93", - "name": "public-gw1" - }, - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "public_gateway", - "status": "available", - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "tags": [] - } - ], - "floating_ips": [ - { - "address": "52.116.129.168", - "created_at": "2024-09-09T09:11:31.000Z", - "crn": "crn:94", - "href": "href:95", - "id": "id:96", - "name": "vsi1-fip", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "status": "available", - "target": { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "primary_ip": { - "address": "10.240.10.4", - "href": "href:61", - "id": "id:62", - "name": "tableware-sprawl-shrivel-popper", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "tags": [] - }, - { - "address": "52.118.147.142", - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:91", - "href": "href:92", - "id": "id:93", - "name": "public-gw1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "status": "available", - "target": { - "href": "href:31", - "id": "id:32", - "name": "public-gw1", - "resource_type": "public_gateway", - "crn": "crn:30" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "tags": [] - } - ], - "network_acls": [ - { - "created_at": "2024-09-09T09:10:15.000Z", - "crn": "crn:27", - "href": "href:28", - "id": "id:29", - "name": "acl2", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:99", - "id": "id:100", - "name": "acl2-out-2" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "0.0.0.0/0", - "direction": "outbound", - "href": "href:97", - "id": "id:98", - "ip_version": "ipv4", - "name": "acl2-out-1", - "source": "10.240.20.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:101", - "id": "id:102", - "name": "acl2-in-1" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.10.0/24", - "direction": "outbound", - "href": "href:99", - "id": "id:100", - "ip_version": "ipv4", - "name": "acl2-out-2", - "source": "10.240.20.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:103", - "id": "id:104", - "name": "acl2-in-2" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.20.0/24", - "direction": "inbound", - "href": "href:101", - "id": "id:102", - "ip_version": "ipv4", - "name": "acl2-in-1", - "source": "0.0.0.0/0", - "protocol": "all" - }, - { - "action": "allow", - "created_at": "2024-09-09T09:10:17.000Z", - "destination": "10.240.20.0/24", - "direction": "inbound", - "href": "href:103", - "id": "id:104", - "ip_version": "ipv4", - "name": "acl2-in-2", - "source": "10.240.10.0/24", - "protocol": "all" - } - ], - "subnets": [ - { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:50", - "href": "href:51", - "id": "id:52", - "name": "acl1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:107", - "id": "id:108", - "name": "acl1-out-2" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "172.217.22.46/32", - "direction": "outbound", - "href": "href:105", - "id": "id:106", - "ip_version": "ipv4", - "name": "acl1-out-1", - "source": "10.240.10.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:109", - "id": "id:110", - "name": "acl1-out-3" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.20.0/24", - "direction": "outbound", - "href": "href:107", - "id": "id:108", - "ip_version": "ipv4", - "name": "acl1-out-2", - "source": "10.240.10.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:111", - "id": "id:112", - "name": "acl1-out-4" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "outbound", - "href": "href:109", - "id": "id:110", - "ip_version": "ipv4", - "name": "acl1-out-3", - "source": "10.240.10.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - }, - { - "action": "allow", - "before": { - "href": "href:113", - "id": "id:114", - "name": "acl1-in-1" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "outbound", - "href": "href:111", - "id": "id:112", - "ip_version": "ipv4", - "name": "acl1-out-4", - "source": "10.240.10.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - }, - { - "action": "allow", - "before": { - "href": "href:115", - "id": "id:116", - "name": "acl1-in-2" - }, - "created_at": "2024-09-09T09:10:17.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:113", - "id": "id:114", - "ip_version": "ipv4", - "name": "acl1-in-1", - "source": "172.217.22.46/32", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:117", - "id": "id:118", - "name": "acl1-in-3" - }, - "created_at": "2024-09-09T09:10:17.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:115", - "id": "id:116", - "ip_version": "ipv4", - "name": "acl1-in-2", - "source": "10.240.20.0/24", - "protocol": "all" - }, - { - "action": "allow", - "before": { - "href": "href:119", - "id": "id:120", - "name": "acl1-in-4" - }, - "created_at": "2024-09-09T09:10:18.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:117", - "id": "id:118", - "ip_version": "ipv4", - "name": "acl1-in-3", - "source": "10.240.30.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - }, - { - "action": "allow", - "created_at": "2024-09-09T09:10:18.000Z", - "destination": "10.240.10.0/24", - "direction": "inbound", - "href": "href:119", - "id": "id:120", - "ip_version": "ipv4", - "name": "acl1-in-4", - "source": "10.240.30.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - } - ], - "subnets": [ - { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:70", - "href": "href:71", - "id": "id:72", - "name": "acl3", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:123", - "id": "id:124", - "name": "acl3-out-2" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "10.240.10.0/24", - "direction": "outbound", - "href": "href:121", - "id": "id:122", - "ip_version": "ipv4", - "name": "acl3-out-1", - "source": "10.240.30.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - }, - { - "action": "allow", - "before": { - "href": "href:125", - "id": "id:126", - "name": "acl3-in-1" - }, - "created_at": "2024-09-09T09:10:15.000Z", - "destination": "10.240.10.0/24", - "direction": "outbound", - "href": "href:123", - "id": "id:124", - "ip_version": "ipv4", - "name": "acl3-out-2", - "source": "10.240.30.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - }, - { - "action": "allow", - "before": { - "href": "href:127", - "id": "id:128", - "name": "acl3-in-2" - }, - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "inbound", - "href": "href:125", - "id": "id:126", - "ip_version": "ipv4", - "name": "acl3-in-1", - "source": "10.240.10.0/24", - "destination_port_max": 443, - "destination_port_min": 443, - "protocol": "tcp", - "source_port_max": 65535, - "source_port_min": 1 - }, - { - "action": "allow", - "created_at": "2024-09-09T09:10:16.000Z", - "destination": "10.240.30.0/24", - "direction": "inbound", - "href": "href:127", - "id": "id:128", - "ip_version": "ipv4", - "name": "acl3-in-2", - "source": "10.240.10.0/24", - "destination_port_max": 65535, - "destination_port_min": 1, - "protocol": "tcp", - "source_port_max": 443, - "source_port_min": 443 - } - ], - "subnets": [ - { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:09:50.000Z", - "crn": "crn:8", - "href": "href:9", - "id": "id:10", - "name": "capitol-siren-chirpy-doornail", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "action": "allow", - "before": { - "href": "href:131", - "id": "id:132", - "name": "allow-outbound" - }, - "created_at": "2024-09-09T09:09:50.000Z", - "destination": "0.0.0.0/0", - "direction": "inbound", - "href": "href:129", - "id": "id:130", - "ip_version": "ipv4", - "name": "allow-inbound", - "source": "0.0.0.0/0", - "protocol": "all" - }, - { - "action": "allow", - "created_at": "2024-09-09T09:09:50.000Z", - "destination": "0.0.0.0/0", - "direction": "outbound", - "href": "href:131", - "id": "id:132", - "ip_version": "ipv4", - "name": "allow-outbound", - "source": "0.0.0.0/0", - "protocol": "all" - } - ], - "subnets": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - } - ], - "security_groups": [ - { - "created_at": "2024-09-09T09:10:14.000Z", - "crn": "crn:133", - "href": "href:134", - "id": "id:135", - "name": "sg1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "inbound", - "href": "href:136", - "id": "id:137", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/0" - }, - "protocol": "all" - }, - { - "direction": "outbound", - "href": "href:138", - "id": "id:139", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/0" - }, - "protocol": "all" - } - ], - "targets": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": "2024-09-09T09:09:50.000Z", - "crn": "crn:13", - "href": "href:14", - "id": "id:15", - "name": "wombat-hesitate-scorn-subprime", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "outbound", - "href": "href:140", - "id": "id:141", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/0" - }, - "protocol": "all" - }, - { - "direction": "inbound", - "href": "href:142", - "id": "id:143", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "crn:13", - "href": "href:14", - "id": "id:15", - "name": "wombat-hesitate-scorn-subprime" - }, - "protocol": "all" - } - ], - "targets": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "inbound", - "href": "fake:href:1", - "id": "fake:id:1", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 0 - }, - { - "direction": "inbound", - "href": "fake:href:3", - "id": "fake:id:3", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 3 - }, - { - "direction": "inbound", - "href": "fake:href:4", - "id": "fake:id:4", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 4 - }, - { - "direction": "inbound", - "href": "fake:href:5", - "id": "fake:id:5", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "inbound", - "href": "fake:href:6", - "id": "fake:id:6", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 8 - }, - { - "direction": "inbound", - "href": "fake:href:7", - "id": "fake:id:7", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 11 - }, - { - "direction": "inbound", - "href": "fake:href:8", - "id": "fake:id:8", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 12 - }, - { - "direction": "inbound", - "href": "fake:href:9", - "id": "fake:id:9", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 13 - }, - { - "direction": "inbound", - "href": "fake:href:10", - "id": "fake:id:10", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 14 - }, - { - "direction": "inbound", - "href": "fake:href:11", - "id": "fake:id:11", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 15 - }, - { - "direction": "inbound", - "href": "fake:href:12", - "id": "fake:id:12", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - }, - "protocol": "icmp", - "type": 16 - } - ], - "targets": [ - { - "href": "href:43", - "id": "id:44", - "name": "ni2", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [ - { - "direction": "outbound", - "href": "fake:href:14", - "id": "fake:id:14", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 0 - }, - { - "direction": "outbound", - "href": "fake:href:15", - "id": "fake:id:15", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 3 - }, - { - "direction": "outbound", - "href": "fake:href:16", - "id": "fake:id:16", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 4 - }, - { - "direction": "outbound", - "href": "fake:href:17", - "id": "fake:id:17", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:18", - "id": "fake:id:18", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 8 - }, - { - "direction": "outbound", - "href": "fake:href:19", - "id": "fake:id:19", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 11 - }, - { - "direction": "outbound", - "href": "fake:href:20", - "id": "fake:id:20", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 12 - }, - { - "direction": "outbound", - "href": "fake:href:21", - "id": "fake:id:21", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 13 - }, - { - "direction": "outbound", - "href": "fake:href:22", - "id": "fake:id:22", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 14 - }, - { - "direction": "outbound", - "href": "fake:href:23", - "id": "fake:id:23", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 15 - }, - { - "direction": "outbound", - "href": "fake:href:24", - "id": "fake:id:24", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "cidr_block": "0.0.0.0/31" - }, - "protocol": "icmp", - "type": 16 - }, - { - "direction": "outbound", - "href": "fake:href:25", - "id": "fake:id:25", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 0 - }, - { - "direction": "outbound", - "href": "fake:href:26", - "id": "fake:id:26", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 3 - }, - { - "direction": "outbound", - "href": "fake:href:27", - "id": "fake:id:27", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 4 - }, - { - "direction": "outbound", - "href": "fake:href:28", - "id": "fake:id:28", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 5 - }, - { - "direction": "outbound", - "href": "fake:href:29", - "id": "fake:id:29", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 8 - }, - { - "direction": "outbound", - "href": "fake:href:30", - "id": "fake:id:30", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 11 - }, - { - "direction": "outbound", - "href": "fake:href:31", - "id": "fake:id:31", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 12 - }, - { - "direction": "outbound", - "href": "fake:href:32", - "id": "fake:id:32", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 13 - }, - { - "direction": "outbound", - "href": "fake:href:33", - "id": "fake:id:33", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 14 - }, - { - "direction": "outbound", - "href": "fake:href:34", - "id": "fake:id:34", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 15 - }, - { - "direction": "outbound", - "href": "fake:href:35", - "id": "fake:id:35", - "ip_version": "ipv4", - "local": { - "cidr_block": "0.0.0.0/0" - }, - "remote": { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - }, - "protocol": "icmp", - "type": 16 - } - ], - "targets": [ - { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:36", - "href": "fake:href:36", - "id": "fake:id:36", - "name": "test-vpc1--vsi3b", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [], - "targets": [ - { - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - }, - { - "created_at": null, - "crn": "fake:crn:37", - "href": "fake:href:37", - "id": "fake:id:37", - "name": "test-vpc1--vsi3a", - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "rules": [], - "targets": [ - { - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "resource_type": "network_interface" - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "tags": [] - } - ], - "endpoint_gateways": [], - "instances": [ - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:149" - }, - "href": "href:147", - "id": "id:148", - "name": "falsetto-snowstorm-bankbook-agreement", - "volume": { - "crn": "crn:150", - "href": "href:151", - "id": "id:152", - "name": "prawn-trusting-pasty-dental", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:11:07.000Z", - "crn": "crn:144", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:145", - "id": "id:146", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi2", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:43", - "id": "id:44", - "name": "ni2", - "primary_ip": { - "address": "10.240.20.4", - "href": "href:41", - "id": "id:42", - "name": "startle-percent-embellish-squeegee", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:149" - }, - "href": "href:147", - "id": "id:148", - "name": "falsetto-snowstorm-bankbook-agreement", - "volume": { - "crn": "crn:150", - "href": "href:151", - "id": "id:152", - "name": "prawn-trusting-pasty-dental", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:11:07.000Z", - "floating_ips": [], - "href": "href:43", - "id": "id:44", - "name": "ni2", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.20.4", - "href": "href:41", - "id": "id:42", - "name": "startle-percent-embellish-squeegee", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:13", - "href": "fake:href:13", - "id": "fake:id:13", - "name": "test-vpc1--vsi2" - } - ], - "status": "available", - "subnet": { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - }, - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:162" - }, - "href": "href:160", - "id": "id:161", - "name": "outskirts-oversized-roundish-ludicrous", - "volume": { - "crn": "crn:163", - "href": "href:164", - "id": "id:165", - "name": "family-tackling-foothold-train", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:10:52.000Z", - "crn": "crn:157", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:158", - "id": "id:159", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi1", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:63", - "id": "id:64", - "name": "ni1", - "primary_ip": { - "address": "10.240.10.4", - "href": "href:61", - "id": "id:62", - "name": "tableware-sprawl-shrivel-popper", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:162" - }, - "href": "href:160", - "id": "id:161", - "name": "outskirts-oversized-roundish-ludicrous", - "volume": { - "crn": "crn:163", - "href": "href:164", - "id": "id:165", - "name": "family-tackling-foothold-train", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:10:52.000Z", - "floating_ips": [ - { - "address": "52.116.129.168", - "crn": "crn:94", - "href": "href:95", - "id": "id:96", - "name": "vsi1-fip" - } - ], - "href": "href:63", - "id": "id:64", - "name": "ni1", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.10.4", - "href": "href:61", - "id": "id:62", - "name": "tableware-sprawl-shrivel-popper", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:2", - "href": "fake:href:2", - "id": "fake:id:2", - "name": "test-vpc1--vsi1" - } - ], - "status": "available", - "subnet": { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - }, - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:171" - }, - "href": "href:169", - "id": "id:170", - "name": "camera-yam-headfirst-scabiosa", - "volume": { - "crn": "crn:172", - "href": "href:173", - "id": "id:174", - "name": "sprinkler-avenue-playset-dislodge", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:10:35.000Z", - "crn": "crn:166", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:167", - "id": "id:168", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi3b", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "primary_ip": { - "address": "10.240.30.5", - "href": "href:85", - "id": "id:86", - "name": "reheat-joyride-little-overprice", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:171" - }, - "href": "href:169", - "id": "id:170", - "name": "camera-yam-headfirst-scabiosa", - "volume": { - "crn": "crn:172", - "href": "href:173", - "id": "id:174", - "name": "sprinkler-avenue-playset-dislodge", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:10:34.000Z", - "floating_ips": [], - "href": "href:87", - "id": "id:88", - "name": "ni3b", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.30.5", - "href": "href:85", - "id": "id:86", - "name": "reheat-joyride-little-overprice", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:36", - "href": "fake:href:36", - "id": "fake:id:36", - "name": "test-vpc1--vsi3b" - } - ], - "status": "available", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - }, - { - "availability_policy": { - "host_failure": "restart" - }, - "bandwidth": 4000, - "boot_volume_attachment": { - "device": { - "id": "id:180" - }, - "href": "href:178", - "id": "id:179", - "name": "cryptic-cork-saponify-lively", - "volume": { - "crn": "crn:181", - "href": "href:182", - "id": "id:183", - "name": "appraisal-mountains-itinerary-twine", - "resource_type": "volume" - } - }, - "confidential_compute_mode": "disabled", - "created_at": "2024-09-09T09:10:34.000Z", - "crn": "crn:175", - "disks": [], - "enable_secure_boot": false, - "health_reasons": [], - "health_state": "ok", - "href": "href:176", - "id": "id:177", - "image": { - "crn": "crn:153", - "href": "href:154", - "id": "id:155", - "name": "server-9080", - "resource_type": "image" - }, - "lifecycle_reasons": [], - "lifecycle_state": "stable", - "memory": 4, - "metadata_service": { - "enabled": false, - "protocol": "http", - "response_hop_limit": 1 - }, - "name": "vsi3a", - "network_attachments": [], - "numa_count": 1, - "primary_network_interface": { - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "primary_ip": { - "address": "10.240.30.4", - "href": "href:81", - "id": "id:82", - "name": "disallow-oxidant-etching-selection", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - }, - "profile": { - "href": "href:156", - "name": "cx2-2x4", - "resource_type": "instance_profile" - }, - "reservation_affinity": { - "policy": "disabled", - "pool": [] - }, - "resource_group": { - "href": "href:16", - "id": "id:17", - "name": "name:4" - }, - "resource_type": "instance", - "startable": true, - "status": "running", - "status_reasons": [], - "total_network_bandwidth": 3000, - "total_volume_bandwidth": 1000, - "vcpu": { - "architecture": "amd64", - "count": 2, - "manufacturer": "intel" - }, - "volume_attachments": [ - { - "device": { - "id": "id:180" - }, - "href": "href:178", - "id": "id:179", - "name": "cryptic-cork-saponify-lively", - "volume": { - "crn": "crn:181", - "href": "href:182", - "id": "id:183", - "name": "appraisal-mountains-itinerary-twine", - "resource_type": "volume" - } - } - ], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - }, - "zone": { - "href": "href:5", - "name": "us-south-1" - }, - "network_interfaces": [ - { - "allow_ip_spoofing": false, - "created_at": "2024-09-09T09:10:34.000Z", - "floating_ips": [], - "href": "href:83", - "id": "id:84", - "name": "ni3a", - "port_speed": 3000, - "primary_ip": { - "address": "10.240.30.4", - "href": "href:81", - "id": "id:82", - "name": "disallow-oxidant-etching-selection", - "resource_type": "subnet_reserved_ip" - }, - "resource_type": "network_interface", - "security_groups": [ - { - "crn": "fake:crn:37", - "href": "fake:href:37", - "id": "fake:id:37", - "name": "test-vpc1--vsi3a" - } - ], - "status": "available", - "subnet": { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - }, - "type": "primary" - } - ], - "tags": [] - } - ], - "virtual_nis": null, - "routing_tables": [ - { - "accept_routes_from": [ - { - "resource_type": "vpn_gateway" - }, - { - "resource_type": "vpn_server" - } - ], - "advertise_routes_to": [], - "created_at": "2024-09-09T09:09:51.000Z", - "href": "href:11", - "id": "id:12", - "is_default": true, - "lifecycle_state": "stable", - "name": "fiscally-fresh-uncanny-ceramics", - "resource_type": "routing_table", - "route_direct_link_ingress": false, - "route_internet_ingress": false, - "route_transit_gateway_ingress": false, - "route_vpc_zone_ingress": false, - "subnets": [ - { - "crn": "crn:24", - "href": "href:25", - "id": "id:26", - "name": "subnet2", - "resource_type": "subnet" - }, - { - "crn": "crn:47", - "href": "href:48", - "id": "id:49", - "name": "subnet1", - "resource_type": "subnet" - }, - { - "crn": "crn:67", - "href": "href:68", - "id": "id:69", - "name": "subnet3", - "resource_type": "subnet" - } - ], - "routes": [], - "vpc": { - "crn": "crn:1", - "href": "href:2", - "id": "id:3", - "name": "test-vpc1", - "resource_type": "vpc" - } - } - ], - "load_balancers": [], - "transit_connections": null, - "transit_gateways": null, - "iks_clusters": [] -} \ No newline at end of file diff --git a/test/data/optimize_sg_icmp_types/conn_spec.json b/test/data/optimize_sg_icmp_types/conn_spec.json deleted file mode 100644 index f9c8648c..00000000 --- a/test/data/optimize_sg_icmp_types/conn_spec.json +++ /dev/null @@ -1,359 +0,0 @@ -{ - "externals": { - "e1": "0.0.0.0/31" - }, - "required-connections": [ - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 0 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 3 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 4 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 8 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 11 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 12 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 13 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 14 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 15 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "e1", - "type": "external" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 16 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 0 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 3 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 4 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 5 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 8 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 11 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 12 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 13 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 14 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 15 - } - ] - }, - { - "src": { - "name": "vsi1", - "type": "instance" - }, - "dst": { - "name": "vsi2", - "type": "instance" - }, - "allowed-protocols": [ - { - "protocol": "ICMP", - "type": 16 - } - ] - } - ] -} diff --git a/test/data/optimize_sg_icmp_types/details.txt b/test/data/optimize_sg_icmp_types/details.txt deleted file mode 100644 index c13db0ec..00000000 --- a/test/data/optimize_sg_icmp_types/details.txt +++ /dev/null @@ -1,28 +0,0 @@ -vsi1 --> 0.0.0.0/31 (icmp type:0) -vsi1 --> 0.0.0.0/31 (icmp type:3) -vsi1 --> 0.0.0.0/31 (icmp type:4) -vsi1 --> 0.0.0.0/31 (icmp type:5) -vsi1 --> 0.0.0.0/31 (icmp type:8) -vsi1 --> 0.0.0.0/31 (icmp type:11) -vsi1 --> 0.0.0.0/31 (icmp type:12) -vsi1 --> 0.0.0.0/31 (icmp type:13) -vsi1 --> 0.0.0.0/31 (icmp type:14) -vsi1 --> 0.0.0.0/31 (icmp type:15) -vsi1 --> 0.0.0.0/31 (icmp type:16) - -vsi1 --> vsi2 (icmp type:0) -vsi1 --> vsi2 (icmp type:3) -vsi1 --> vsi2 (icmp type:4) -vsi1 --> vsi2 (icmp type:5) -vsi1 --> vsi2 (icmp type:8) -vsi1 --> vsi2 (icmp type:11) -vsi1 --> vsi2 (icmp type:12) -vsi1 --> vsi2 (icmp type:13) -vsi1 --> vsi2 (icmp type:14) -vsi1 --> vsi2 (icmp type:15) -vsi1 --> vsi2 (icmp type:16) - -==================================== - -vsi1 --> 0.0.0.0/31 (icmp) -vsi1 --> vsi2 (icmp) \ No newline at end of file diff --git a/test/expected/optimize_sg_icmp_codes/sg_expected.tf b/test/expected/optimize_sg_icmp_codes/sg_expected.tf deleted file mode 100644 index d1ca8c9d..00000000 --- a/test/expected/optimize_sg_icmp_codes/sg_expected.tf +++ /dev/null @@ -1,70 +0,0 @@ -resource "ibm_is_security_group" "sg1" { - name = "sg-sg1" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} - - -resource "ibm_is_security_group" "test-vpc1--vsi1" { - name = "sg-test-vpc1--vsi1" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { - group = ibm_is_security_group.test-vpc1--vsi1.id - direction = "outbound" - remote = ibm_is_security_group.test-vpc1--vsi2.id - icmp { - type = 5 - } -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { - group = ibm_is_security_group.test-vpc1--vsi1.id - direction = "outbound" - remote = "0.0.0.0/31" - icmp { - type = 5 - code = 0 - } -} - - -resource "ibm_is_security_group" "test-vpc1--vsi2" { - name = "sg-test-vpc1--vsi2" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { - group = ibm_is_security_group.test-vpc1--vsi2.id - direction = "inbound" - remote = ibm_is_security_group.test-vpc1--vsi1.id - icmp { - type = 5 - } -} - - -resource "ibm_is_security_group" "test-vpc1--vsi3a" { - name = "sg-test-vpc1--vsi3a" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} - - -resource "ibm_is_security_group" "test-vpc1--vsi3b" { - name = "sg-test-vpc1--vsi3b" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} - - -resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { - name = "sg-wombat-hesitate-scorn-subprime" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} -resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { - group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id - direction = "inbound" - remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id -} diff --git a/test/expected/optimize_sg_icmp_types/sg_expected.tf b/test/expected/optimize_sg_icmp_types/sg_expected.tf deleted file mode 100644 index 2795bc56..00000000 --- a/test/expected/optimize_sg_icmp_types/sg_expected.tf +++ /dev/null @@ -1,67 +0,0 @@ -resource "ibm_is_security_group" "sg1" { - name = "sg-sg1" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} - - -resource "ibm_is_security_group" "test-vpc1--vsi1" { - name = "sg-test-vpc1--vsi1" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { - group = ibm_is_security_group.test-vpc1--vsi1.id - direction = "outbound" - remote = ibm_is_security_group.test-vpc1--vsi2.id - icmp { - } -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { - group = ibm_is_security_group.test-vpc1--vsi1.id - direction = "outbound" - remote = "0.0.0.0/31" - icmp { - type = 0 - } -} - - -resource "ibm_is_security_group" "test-vpc1--vsi2" { - name = "sg-test-vpc1--vsi2" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { - group = ibm_is_security_group.test-vpc1--vsi2.id - direction = "inbound" - remote = ibm_is_security_group.test-vpc1--vsi1.id - icmp { - } -} - - -resource "ibm_is_security_group" "test-vpc1--vsi3a" { - name = "sg-test-vpc1--vsi3a" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} - - -resource "ibm_is_security_group" "test-vpc1--vsi3b" { - name = "sg-test-vpc1--vsi3b" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} - - -resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { - name = "sg-wombat-hesitate-scorn-subprime" - resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id -} -resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { - group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id - direction = "inbound" - remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id -} diff --git a/test/main_test_list.go b/test/main_test_list.go index a2f0982c..f9d63166 100644 --- a/test/main_test_list.go +++ b/test/main_test_list.go @@ -318,24 +318,6 @@ func synthSGTestsList() []testCase { // Note2: each data folder has a details.txt file with the test explanation func optimizeSGTestsLists() []testCase { return []testCase{ - { - testName: "optimize_sg_icmp_codes", - args: &command{ - cmd: optimize, - subcmd: sg, - config: "%s/optimize_sg_icmp_codes/config_object.json", - outputFile: "%s/optimize_sg_icmp_codes/sg_expected.tf", - }, - }, - { - testName: "optimize_sg_icmp_types", - args: &command{ - cmd: optimize, - subcmd: sg, - config: "%s/optimize_sg_icmp_types/config_object.json", - outputFile: "%s/optimize_sg_icmp_types/sg_expected.tf", - }, - }, { testName: "optimize_sg_protocols_to_all_tf", args: &command{ From fadb26bd5736c0a004269da54dfa3fda84d8e8b7 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 08:43:11 +0300 Subject: [PATCH 61/79] portset --- pkg/optimize/sg/ipCubesToRules.go | 10 ++-- pkg/optimize/sg/rulesToCubes.go | 96 ++++++++++++++++--------------- pkg/optimize/sg/sg.go | 2 +- pkg/optimize/sg/sgCubesToRules.go | 7 +-- 4 files changed, 58 insertions(+), 57 deletions(-) diff --git a/pkg/optimize/sg/ipCubesToRules.go b/pkg/optimize/sg/ipCubesToRules.go index e38acb9d..cf5c31b8 100644 --- a/pkg/optimize/sg/ipCubesToRules.go +++ b/pkg/optimize/sg/ipCubesToRules.go @@ -23,13 +23,13 @@ func allProtocolIPCubesIPToRules(cubes *netset.IPBlock, direction ir.Direction) return result } -func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], allProtocolCubes *netset.IPBlock, +func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.PortSet], allCubes *netset.IPBlock, direction ir.Direction, isTCP bool) []*ir.SGRule { activeRules := make(map[*netset.IPBlock]*interval.Interval) // start ip and ports result := make([]*ir.SGRule, 0) for i := range cubes { - if i > 0 && !continuation(cubes[i-1], cubes[i], allProtocolCubes) { + if i > 0 && !continuation(cubes[i-1], cubes[i], allCubes) { for ipb, ports := range activeRules { p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) @@ -75,7 +75,7 @@ func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *interval.CanonicalSe } // problem: where should I end the rule? -// func createTcpudpRules(rules []ds.Pair[*netset.IPBlock, *interval.Interval], span []ds.Pair[*netset.IPBlock, *interval.CanonicalSet], +// func createTcpudpRules(rules []ds.Pair[*netset.IPBlock, *interval.Interval], span []ds.Pair[*netset.IPBlock, *netset.PortSet], // direction ir.Direction, isTCP bool) (res []ir.SGRule) { // res = make([]ir.SGRule, 0) // for _, r := range rules { @@ -87,12 +87,12 @@ func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *interval.CanonicalSe // return res // } -func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allProtocolCubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { +func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { activeRules := make(map[*netset.IPBlock]*netp.ICMP) result := make([]*ir.SGRule, 0) for i := range cubes { - if i > 0 && !continuation(cubes[i-1], cubes[i], allProtocolCubes) { + if i > 0 && !continuation(cubes[i-1], cubes[i], allCubes) { for ipb, icmp := range activeRules { p, _ := netp.NewICMP(icmp.TypeCode) ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) diff --git a/pkg/optimize/sg/rulesToCubes.go b/pkg/optimize/sg/rulesToCubes.go index 84e28bd1..deb07179 100644 --- a/pkg/optimize/sg/rulesToCubes.go +++ b/pkg/optimize/sg/rulesToCubes.go @@ -16,7 +16,55 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/utils" ) -// calculate all cubes +// SG remote +func rulesToSGCubes(rules *rulesPerProtocol) *sgCubesPerProtocol { + tcpSpan := tcpudpRulesSGCubes(rules.tcp) + udpSpan := tcpudpRulesSGCubes(rules.udp) + icmpSpan := icmpRulesSGCubes(rules.icmp) + allSpan := allProtocolRulesToSGCubes(rules.all) + return &sgCubesPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} +} + +// all protocol rules to cubes +func allProtocolRulesToSGCubes(rules []*ir.SGRule) []ir.SGName { + result := make(map[ir.SGName]struct{}) + for i := range rules { + remote := rules[i].Remote.(ir.SGName) // already checked + result[remote] = struct{}{} + } + return utils.SortedMapKeys(result) +} + +// tcp/udp rules to cubes -- map where the key is the SG name and the value is the protocol ports +func tcpudpRulesSGCubes(rules []*ir.SGRule) map[ir.SGName]*netset.PortSet { + result := make(map[ir.SGName]*netset.PortSet) + for _, rule := range rules { + p := rule.Protocol.(netp.TCPUDP) // already checked + remote := rule.Remote.(ir.SGName) // already checked + if result[remote] == nil { + result[remote] = interval.NewCanonicalSet() + } + result[remote].AddInterval(p.DstPorts()) + } + return result +} + +// icmp rules to cubes -- map where the key is the SG name and the value is icmpset +func icmpRulesSGCubes(rules []*ir.SGRule) map[ir.SGName]*netset.ICMPSet { + result := make(map[ir.SGName]*netset.ICMPSet) + for _, rule := range rules { + p := rule.Protocol.(netp.ICMP) // already checked + remote := rule.Remote.(ir.SGName) // already checked + if result[remote] == nil { + result[remote] = netset.EmptyICMPSet() + } + icmpSet := optimize.IcmpRuleToIcmpSet(p) + result[remote] = result[remote].Union(icmpSet) + } + return result +} + +// IP remote func rulesToIPCubes(rules *rulesPerProtocol) *ipCubesPerProtocol { tcpCubes := tcpudpRulesToIPCubes(rules.tcp) udpCubes := tcpudpRulesToIPCubes(rules.udp) @@ -25,14 +73,6 @@ func rulesToIPCubes(rules *rulesPerProtocol) *ipCubesPerProtocol { return &ipCubesPerProtocol{tcp: tcpCubes, udp: udpCubes, icmp: icmpCubes, all: allCubes} } -func rulesToSGCubes(rules *rulesPerProtocol) *sgCubesPerProtocol { - tcpSpan := tcpudpRulesToSGToPortsSpan(rules.tcp) - udpSpan := tcpudpRulesToSGToPortsSpan(rules.udp) - icmpSpan := icmpRulesToSGToSpan(rules.icmp) - allSpan := allProtocolRulesToSGToSpan(rules.all) - return &sgCubesPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} -} - // all protocol rules to cubes func allProtocolRulesToIPCubes(rules []*ir.SGRule) *netset.IPBlock { res := netset.NewIPBlock() @@ -42,15 +82,6 @@ func allProtocolRulesToIPCubes(rules []*ir.SGRule) *netset.IPBlock { return res } -func allProtocolRulesToSGToSpan(rules []*ir.SGRule) []ir.SGName { - result := make(map[ir.SGName]struct{}) - for i := range rules { - remote := rules[i].Remote.(ir.SGName) - result[remote] = struct{}{} - } - return utils.SortedMapKeys(result) -} - // tcp/udp rules (separately) to cubes (IPBlock X portset). func tcpudpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.PortSet] { cubes := ds.NewProductLeft[*netset.IPBlock, *netset.PortSet]() @@ -63,20 +94,6 @@ func tcpudpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) } -// tcp/udp rules to cubes -- map where the key is the SG name and the value is the protocol ports -func tcpudpRulesToSGToPortsSpan(rules []*ir.SGRule) map[ir.SGName]*netset.PortSet { - result := make(map[ir.SGName]*netset.PortSet) - for _, rule := range rules { - p := rule.Protocol.(netp.TCPUDP) // already checked - remote := rule.Remote.(ir.SGName) // already checked - if result[remote] == nil { - result[remote] = interval.NewCanonicalSet() - } - result[remote].AddInterval(p.DstPorts()) - } - return result -} - // icmp rules to cubes (IPBlock X icmp set). func icmpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.ICMPSet] { cubes := ds.NewProductLeft[*netset.IPBlock, *netset.ICMPSet]() @@ -89,18 +106,3 @@ func icmpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.I } return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) } - -// icmp rules to cubes -- map where the key is the SG name and the value is icmpset -func icmpRulesToSGToSpan(rules []*ir.SGRule) map[ir.SGName]*netset.ICMPSet { - result := make(map[ir.SGName]*netset.ICMPSet) - for _, rule := range rules { - p := rule.Protocol.(netp.ICMP) // already checked - remote := rule.Remote.(ir.SGName) // already checked - if result[remote] == nil { - result[remote] = netset.EmptyICMPSet() - } - icmpSet := optimize.IcmpRuleToIcmpSet(p) - result[remote] = result[remote].Union(icmpSet) - } - return result -} diff --git a/pkg/optimize/sg/sg.go b/pkg/optimize/sg/sg.go index 7ddbafd3..2427c265 100644 --- a/pkg/optimize/sg/sg.go +++ b/pkg/optimize/sg/sg.go @@ -116,7 +116,7 @@ func (s *sgOptimizer) optimizeSG(vpcName string, sgName ir.SGName) { // reduceSGRules attempts to reduce the number of rules with different remote types separately func (s *sgOptimizer) reduceRules(rules []*ir.SGRule, direction ir.Direction) []*ir.SGRule { - // separate all rules to groups of (protocol X remote) + // separate all rules to groups of protocol X remote ([tcp, udp, icmp, protocolAll] X [ip, sg]) ruleGroups := divideSGRules(rules) // rules with SG as a remote diff --git a/pkg/optimize/sg/sgCubesToRules.go b/pkg/optimize/sg/sgCubesToRules.go index 0eb4bd12..4ed229c7 100644 --- a/pkg/optimize/sg/sgCubesToRules.go +++ b/pkg/optimize/sg/sgCubesToRules.go @@ -6,7 +6,6 @@ SPDX-License-Identifier: Apache-2.0 package sgoptimizer import ( - "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" @@ -14,8 +13,8 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" ) -// cubes (SGName X ports set) to SG rules -func tcpudpSGCubesToRules(span map[ir.SGName]*interval.CanonicalSet, direction ir.Direction, isTCP bool) []*ir.SGRule { +// cubes (SGName X portSet) to SG rules +func tcpudpSGCubesToRules(span map[ir.SGName]*netset.PortSet, direction ir.Direction, isTCP bool) []*ir.SGRule { result := make([]*ir.SGRule, 0) for sgName, portSet := range span { for _, dstPorts := range portSet.Intervals() { @@ -26,7 +25,7 @@ func tcpudpSGCubesToRules(span map[ir.SGName]*interval.CanonicalSet, direction i return result } -// cubes (SGName X icmp set) to SG rules +// cubes (SGName X icmpset) to SG rules func icmpSGCubesToRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction) []*ir.SGRule { result := make([]*ir.SGRule, 0) for sgName, icmpSet := range span { From 3cdadc60ab8aa759600e6117abdcaef897df09bb Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 13:46:10 +0300 Subject: [PATCH 62/79] convert ip cubes, generic ipCubeToRule --- pkg/optimize/common.go | 1 + pkg/optimize/sg/ipCubesToRules.go | 135 +++++++++++++---------------- pkg/optimize/sg/optimizeSG_test.go | 100 ++++++++++----------- pkg/optimize/sg/reduceCubes.go | 73 ++++++++++------ pkg/optimize/sg/rulesToCubes.go | 3 +- 5 files changed, 156 insertions(+), 156 deletions(-) diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index d4ba3e45..f28a4e62 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -32,6 +32,7 @@ func SortPartitionsByIPAddrs[T any](p []ds.Pair[*netset.IPBlock, T]) []ds.Pair[* return p } +// returns true if this 0 && !continuation(cubes[i-1], cubes[i], allCubes) { - for ipb, ports := range activeRules { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) - ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) - for _, cidr := range ipRange.SplitToCidrs() { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - delete(activeRules, ipb) - } + result = append(result, createActiveRules(activeRules, cubes[i-1].Left.LastIPAddressObject(), direction)...) + activeRules = make(map[*netset.IPBlock]netp.Protocol) } - // rules whose ports are not in the current cube will not remain active + // if the proctol is not contained in the current cube, we will generate SG rules + // calculate active ports = active rules covers these ports activePorts := interval.NewCanonicalSet() - for ipb, ports := range activeRules { - if !ports.ToSet().IsSubset(cubes[i].Right) { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) - ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) - for _, cidr := range ipRange.SplitToCidrs() { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + for ipb, protocol := range activeRules { + if tcpudp, ok := protocol.(netp.TCPUDP); ok { + if !tcpudp.DstPorts().ToSet().IsSubset(cubes[i].Right) { + result = append(result, createNewRules(protocol, ipb, cubes[i-1].Left.LastIPAddressObject(), direction)...) + } else { + activePorts.AddInterval(tcpudp.DstPorts()) } - } else { - activePorts.AddInterval(*ports) } } - // if the cube contains ports that are not contained in active rules, new rules will be created + // if the cube contains ports that are not contained in the active rules, new rules will be created for _, ports := range cubes[i].Right.Intervals() { if !ports.ToSet().IsSubset(activePorts) { - activeRules[cubes[i].Left.FirstIPAddressObject()] = &ports + p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) + activeRules[cubes[i].Left.FirstIPAddressObject()] = p } } } - - // create the rest of the rules - for ipb, ports := range activeRules { - p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(ports.Start()), int(ports.End())) - ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[len(cubes)-1].Left.LastIPAddressObject()) - for _, cidr := range ipRange.SplitToCidrs() { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } - - return result + // generate all the existing rules + return append(result, createActiveRules(activeRules, cubes[len(cubes)-1].Left.LastIPAddressObject(), direction)...) } -// problem: where should I end the rule? -// func createTcpudpRules(rules []ds.Pair[*netset.IPBlock, *interval.Interval], span []ds.Pair[*netset.IPBlock, *netset.PortSet], -// direction ir.Direction, isTCP bool) (res []ir.SGRule) { -// res = make([]ir.SGRule, 0) -// for _, r := range rules { -// p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(r.Right.Start()), int(r.Right.Start())) -// for _, cidr := range ToCidrs(IPBlockFromRange(r.Left, LastIPAddress(span[len(span)-1].Left))) { -// res = append(res, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) -// } -// } -// return res -// } - +// icmpIPCubesToRules converts cubes representing icmp protocol rules to SG rules func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { - activeRules := make(map[*netset.IPBlock]*netp.ICMP) + activeRules := make(map[*netset.IPBlock]netp.Protocol) // the key is the first IP result := make([]*ir.SGRule, 0) for i := range cubes { + // if it is not possible to continue the rule between the cubes, generate all the existing rules if i > 0 && !continuation(cubes[i-1], cubes[i], allCubes) { - for ipb, icmp := range activeRules { - p, _ := netp.NewICMP(icmp.TypeCode) - ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) - for _, cidr := range ipRange.SplitToCidrs() { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - delete(activeRules, ipb) - } + result = append(result, createActiveRules(activeRules, cubes[i-1].Left.LastIPAddressObject(), direction)...) + activeRules = make(map[*netset.IPBlock]netp.Protocol) } - // rules whose icmp value is not in the current cube will not remain active + // if the proctol is not contained in the current cube, we will generate SG rules + // calculate activeICMP = active rules covers these icmp values activeICMP := netset.EmptyICMPSet() - for ipb, icmp := range activeRules { - ruleIcmpSet := optimize.IcmpRuleToIcmpSet(*icmp) - if !ruleIcmpSet.IsSubset(cubes[i].Right) { // create rules - p, _ := netp.NewICMPWithoutRFCValidation(icmp.TypeCode) - ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[i-1].Left.LastIPAddressObject()) - for _, cidr := range ipRange.SplitToCidrs() { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) + for ipb, protocol := range activeRules { + if icmp, ok := protocol.(netp.ICMP); ok { + ruleIcmpSet := optimize.IcmpRuleToIcmpSet(icmp) + if !ruleIcmpSet.IsSubset(cubes[i].Right) { + result = append(result, createNewRules(protocol, ipb, cubes[i-1].Left.LastIPAddressObject(), direction)...) + } else { + activeICMP.Union(ruleIcmpSet) } - } else { - activeICMP.Union(ruleIcmpSet) } } - // new rules + // if the cube contains icmp values that are not contained in the active rules, new rules will be created for _, p := range optimize.IcmpsetPartitions(cubes[i].Right) { if !optimize.IcmpRuleToIcmpSet(p).IsSubset(activeICMP) { activeRules[cubes[i].Left.FirstIPAddressObject()] = &p @@ -126,18 +97,11 @@ func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCu } } - // create the rest of the rules - for ipb, icmp := range activeRules { - p, _ := netp.NewICMP(icmp.TypeCode) - ipRange, _ := netset.IPBlockFromIPRange(ipb, cubes[len(cubes)-1].Left.LastIPAddressObject()) - for _, cidr := range ipRange.SplitToCidrs() { - result = append(result, ir.NewSGRule(direction, cidr, p, netset.GetCidrAll(), "")) - } - } - - return result + // generate all the existing rules + return append(result, createActiveRules(activeRules, cubes[len(cubes)-1].Left.LastIPAddressObject(), direction)...) } +// continuation returns true if the rules can be continued between the two cubes func continuation[T ds.Set[T]](prevPair, currPair ds.Pair[*netset.IPBlock, T], allProtocolCubes *netset.IPBlock) bool { prevIPBlock := prevPair.Left currIPBlock := currPair.Left @@ -150,3 +114,22 @@ func continuation[T ds.Set[T]](prevPair, currPair ds.Pair[*netset.IPBlock, T], a hole, _ := netset.IPBlockFromIPRange(startH, endH) return hole.IsSubset(allProtocolCubes) } + +// creates sgRules from SG active rules +func createActiveRules(activeRules map[*netset.IPBlock]netp.Protocol, endIP *netset.IPBlock, direction ir.Direction) []*ir.SGRule { + res := make([]*ir.SGRule, 0) + for ipb, protocol := range activeRules { + res = append(res, createNewRules(protocol, ipb, endIP, direction)...) + } + return res +} + +// createNewRules breaks the startIP-endIP ip range into cidrs and creates SG rules +func createNewRules(protocol netp.Protocol, startIP, endIP *netset.IPBlock, direction ir.Direction) []*ir.SGRule { + res := make([]*ir.SGRule, 0) + ipRange, _ := netset.IPBlockFromIPRange(startIP, endIP) + for _, cidr := range ipRange.SplitToCidrs() { + res = append(res, ir.NewSGRule(direction, cidr, protocol, netset.GetCidrAll(), "")) + } + return res +} diff --git a/pkg/optimize/sg/optimizeSG_test.go b/pkg/optimize/sg/optimizeSG_test.go index 544fa53f..1bcd2c90 100644 --- a/pkg/optimize/sg/optimizeSG_test.go +++ b/pkg/optimize/sg/optimizeSG_test.go @@ -5,53 +5,53 @@ SPDX-License-Identifier: Apache-2.0 package sgoptimizer_test -import ( - "log" - "testing" - - "github.com/np-guard/models/pkg/ds" - "github.com/np-guard/models/pkg/netp" - "github.com/np-guard/models/pkg/netset" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" - "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" -) - -func TestOps(t *testing.T) { - sgRules := make([]*ir.SGRule, 0) - p1, _ := netp.NewTCPUDP(true, 1, 100, 1, 10) - p2, _ := netp.NewTCPUDP(true, 1, 100, 1, 20) - - ipb1, _ := netset.IPBlockFromCidrOrAddress("0.0.0.0") - ipb2, _ := netset.IPBlockFromCidrOrAddress("0.0.0.0/31") - - sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb1, p1, netset.GetCidrAll(), "")) - sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb2, p2, netset.GetCidrAll(), "")) - - res := tcpudpRulesToIPCubes(sgRules) - for i, pair := range res { - log.Println("pair ", i, ": ipblock: ", pair.Left.String(), ", ports: ", pair.Right.String()) - } - - sgRules = []*ir.SGRule{} - sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb2, p1, netset.GetCidrAll(), "")) - sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb1, p2, netset.GetCidrAll(), "")) - - res = tcpudpRulesToIPCubes(sgRules) - for i, pair := range res { - log.Println("pair ", i, ": ipblock: ", pair.Left.String(), ", ports: ", pair.Right.String()) - } - - t.Log("Hi") -} - -func tcpudpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.PortSet] { - cubes := ds.NewProductLeft[*netset.IPBlock, *netset.PortSet]() - for _, rule := range rules { - ipb := rule.Remote.(*netset.IPBlock) // already checked - portsSet := rule.Protocol.(netp.TCPUDP) // already checked - r := ds.CartesianPairLeft(ipb, portsSet.DstPorts().ToSet()) - cubes = cubes.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.PortSet]) - } - return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) -} +// import ( +// "log" +// "testing" + +// "github.com/np-guard/models/pkg/ds" +// "github.com/np-guard/models/pkg/netp" +// "github.com/np-guard/models/pkg/netset" + +// "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +// "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" +// ) + +// func TestOps(t *testing.T) { +// sgRules := make([]*ir.SGRule, 0) +// p1, _ := netp.NewTCPUDP(true, 1, 100, 1, 10) +// p2, _ := netp.NewTCPUDP(true, 1, 100, 1, 20) + +// ipb1, _ := netset.IPBlockFromCidrOrAddress("0.0.0.0") +// ipb2, _ := netset.IPBlockFromCidrOrAddress("0.0.0.0/31") + +// sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb1, p1, netset.GetCidrAll(), "")) +// sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb2, p2, netset.GetCidrAll(), "")) + +// res := tcpudpRulesToIPCubes(sgRules) +// for i, pair := range res { +// log.Println("pair ", i, ": ipblock: ", pair.Left.String(), ", ports: ", pair.Right.String()) +// } + +// sgRules = []*ir.SGRule{} +// sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb2, p1, netset.GetCidrAll(), "")) +// sgRules = append(sgRules, ir.NewSGRule(ir.Outbound, ipb1, p2, netset.GetCidrAll(), "")) + +// res = tcpudpRulesToIPCubes(sgRules) +// for i, pair := range res { +// log.Println("pair ", i, ": ipblock: ", pair.Left.String(), ", ports: ", pair.Right.String()) +// } + +// t.Log("Hi") +// } + +// func tcpudpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.PortSet] { +// cubes := ds.NewProductLeft[*netset.IPBlock, *netset.PortSet]() +// for _, rule := range rules { +// ipb := rule.Remote.(*netset.IPBlock) // already checked +// portsSet := rule.Protocol.(netp.TCPUDP) // already checked +// r := ds.CartesianPairLeft(ipb, portsSet.DstPorts().ToSet()) +// cubes = cubes.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.PortSet]) +// } +// return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) +// } diff --git a/pkg/optimize/sg/reduceCubes.go b/pkg/optimize/sg/reduceCubes.go index 3489ed49..b597b894 100644 --- a/pkg/optimize/sg/reduceCubes.go +++ b/pkg/optimize/sg/reduceCubes.go @@ -47,6 +47,8 @@ func compressThreeProtocolsToAllProtocol(spans *sgCubesPerProtocol) *sgCubesPerP // observation: It pays to switch to all protocol rule when we have rules that cover all other protocols // on exactly the same cidr (only one protocol can exceed). +// +//nolint:gocyclo // multiple if statments func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { tcpPtr := 0 udpPtr := 0 @@ -67,7 +69,7 @@ func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { continue } - cubes, changed = reduce(cubes, tcpPtr, udpPtr, icmpPtr) + cubes, changed = compressToAllCube(cubes, tcpPtr, udpPtr, icmpPtr) if changed { continue } @@ -76,43 +78,58 @@ func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { udpIP := cubes.udp[udpPtr].Left icmpIP := cubes.icmp[icmpPtr].Left - if udpIP.IsSubset(tcpIP) && icmpIP.IsSubset(tcpIP) { - if optimize.LessIPBlock(udpIP, icmpIP) { - udpPtr++ - } else { - icmpPtr++ - } - continue - } + switch { + // one protocol ipb contains two other ipbs. advance the smaller ipb + case udpIP.IsSubset(tcpIP) && icmpIP.IsSubset(tcpIP) && optimize.LessIPBlock(udpIP, icmpIP): + udpPtr++ + case udpIP.IsSubset(tcpIP) && icmpIP.IsSubset(tcpIP) && optimize.LessIPBlock(icmpIP, udpIP): + icmpPtr++ + case tcpIP.IsSubset(udpIP) && icmpIP.IsSubset(udpIP) && optimize.LessIPBlock(tcpIP, icmpIP): + tcpPtr++ + case tcpIP.IsSubset(udpIP) && icmpIP.IsSubset(udpIP) && optimize.LessIPBlock(icmpIP, tcpIP): + icmpPtr++ + case tcpIP.IsSubset(icmpIP) && udpIP.IsSubset(icmpIP) && optimize.LessIPBlock(tcpIP, udpIP): + tcpPtr++ + case tcpIP.IsSubset(icmpIP) && udpIP.IsSubset(icmpIP) && optimize.LessIPBlock(udpIP, tcpIP): + udpPtr++ + // advance the smaller ipb + case optimize.LessIPBlock(tcpIP, udpIP) && optimize.LessIPBlock(tcpIP, icmpIP): + tcpPtr++ + case optimize.LessIPBlock(udpIP, tcpIP) && optimize.LessIPBlock(udpIP, icmpIP): + udpPtr++ + case optimize.LessIPBlock(icmpIP, tcpIP) && optimize.LessIPBlock(icmpIP, udpIP): + icmpPtr++ + } } return cubes } -func reduce(cubes *ipCubesPerProtocol, tcpPtr, udpPtr, icmpPtr int) (*ipCubesPerProtocol, bool) { +// compress three protocol rules to all protocol rule (and maybe another protocol rule) +func compressToAllCube(cubes *ipCubesPerProtocol, tcpPtr, udpPtr, icmpPtr int) (*ipCubesPerProtocol, bool) { tcpIP := cubes.tcp[tcpPtr].Left udpIP := cubes.udp[udpPtr].Left icmpIP := cubes.icmp[icmpPtr].Left - if udpIP.IsSubset(tcpIP) && udpIP.Equal(icmpIP) { + switch { + case udpIP.Equal(tcpIP) && udpIP.Equal(icmpIP): + cubes.tcp = slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) + fallthrough + case udpIP.IsSubset(tcpIP) && udpIP.Equal(icmpIP): + cubes.udp = slices.Delete(cubes.udp, udpPtr, udpPtr+1) + cubes.icmp = slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) cubes.all = cubes.all.Union(udpIP) - slices.Delete(cubes.udp, udpPtr, udpPtr+1) - slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) - if tcpIP.Equal(udpIP) { - slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) - } - // continue + return cubes, true + case tcpIP.IsSubset(udpIP) && tcpIP.Equal(icmpIP): + cubes.tcp = slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) + cubes.icmp = slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) + cubes.all = cubes.all.Union(tcpIP) + return cubes, true + case tcpIP.IsSubset(icmpIP) && tcpIP.Equal(udpIP): + cubes.tcp = slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) + cubes.udp = slices.Delete(cubes.udp, udpPtr, udpPtr+1) + cubes.all = cubes.all.Union(tcpIP) + return cubes, true } - - if tcpIP.IsSubset(udpIP) && tcpIP.Equal(icmpIP) { - cubes.all = cubes.all.Union(udpIP) - slices.Delete(cubes.udp, udpPtr, udpPtr+1) - slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) - if tcpIP.Equal(udpIP) { - slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) - } - // continue - } - return cubes, false } diff --git a/pkg/optimize/sg/rulesToCubes.go b/pkg/optimize/sg/rulesToCubes.go index deb07179..589aad7e 100644 --- a/pkg/optimize/sg/rulesToCubes.go +++ b/pkg/optimize/sg/rulesToCubes.go @@ -100,8 +100,7 @@ func icmpRulesToIPCubes(rules []*ir.SGRule) []ds.Pair[*netset.IPBlock, *netset.I for _, rule := range rules { ipb := rule.Remote.(*netset.IPBlock) // already checked p := rule.Protocol.(netp.ICMP) // already checked - icmpSet := optimize.IcmpRuleToIcmpSet(p) - r := ds.CartesianPairLeft(ipb, icmpSet) + r := ds.CartesianPairLeft(ipb, optimize.IcmpRuleToIcmpSet(p)) cubes = cubes.Union(r).(*ds.ProductLeft[*netset.IPBlock, *netset.ICMPSet]) } return optimize.SortPartitionsByIPAddrs(cubes.Partitions()) From 69ca4125cb438aad649676a2a4b514fa54eca92b Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 13:49:34 +0300 Subject: [PATCH 63/79] delete test --- pkg/optimize/common.go | 2 +- pkg/optimize/sg/optimizeSG_test.go | 57 -- .../acl_externals_tf/nacl_expected.tf | 348 +++++------ test/expected/acl_nif_tf/nacl_expected.tf | 216 +++---- .../acl_protocols_tf/nacl_expected.tf | 280 ++++----- .../expected/acl_segments_tf/nacl_expected.tf | 216 +++---- .../expected/acl_testing5_tf/nacl_expected.tf | 584 +++++++++--------- .../nacl_single_expected.tf | 420 ++++++------- .../acl_tg_multiple_tf/nacl_expected.tf | 200 +++--- .../acl_tg_multiple_tf_separate/test-vpc0.tf | 120 ++-- .../acl_tg_multiple_tf_separate/test-vpc1.tf | 40 +- .../acl_tg_multiple_tf_separate/test-vpc2.tf | 20 +- .../acl_tg_multiple_tf_separate/test-vpc3.tf | 20 +- test/expected/sg_protocols_tf/sg_expected.tf | 136 ++-- test/expected/sg_testing3_tf/sg_expected.tf | 68 +- .../sg_tg_multiple_tf_separate/test-vpc0.tf | 56 +- .../sg_tg_multiple_tf_separate/test-vpc1.tf | 16 +- .../sg_tg_multiple_tf_separate/test-vpc2.tf | 20 +- .../sg_tg_multiple_tf_separate/test-vpc3.tf | 4 +- 19 files changed, 1383 insertions(+), 1440 deletions(-) delete mode 100644 pkg/optimize/sg/optimizeSG_test.go diff --git a/pkg/optimize/common.go b/pkg/optimize/common.go index f28a4e62..9d62a104 100644 --- a/pkg/optimize/common.go +++ b/pkg/optimize/common.go @@ -34,7 +34,7 @@ func SortPartitionsByIPAddrs[T any](p []ds.Pair[*netset.IPBlock, T]) []ds.Pair[* // returns true if this(subnet test-vpc1/subnet1); allowed-protocols[0] rules { - name = "rule18" - action = "allow" - direction = "inbound" - source = "8.8.8.8" + name = "rule18" + action = "allow" + direction = "inbound" + source = "8.8.8.8" destination = "10.240.10.0/24" } # External. response to required-connections[0]: (external dns)->(subnet test-vpc1/subnet1); allowed-protocols[0] rules { - name = "rule19" - action = "allow" - direction = "outbound" - source = "10.240.10.0/24" + name = "rule19" + action = "allow" + direction = "outbound" + source = "10.240.10.0/24" destination = "8.8.8.8" } } # test-vpc1/subnet2 [10.240.20.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet2" { - name = "acl-test-vpc1--subnet2" + name = "acl-test-vpc1--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule0" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule0" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule1" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule1" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule2" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule2" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule3" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule3" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule4" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule4" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule5" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule5" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule6" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule6" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule7" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule7" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule8" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule8" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule9" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule9" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule10" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule10" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule11" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule11" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule12" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule12" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule13" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule13" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule14" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule14" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule15" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule15" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule16" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule16" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule17" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule17" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (subnet test-vpc1/subnet2)->(external public internet); allowed-protocols[0] rules { - name = "rule18" - action = "allow" - direction = "outbound" - source = "10.240.20.0/24" + name = "rule18" + action = "allow" + direction = "outbound" + source = "10.240.20.0/24" destination = "0.0.0.0/0" } # External. response to required-connections[1]: (subnet test-vpc1/subnet2)->(external public internet); allowed-protocols[0] rules { - name = "rule19" - action = "allow" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule19" + action = "allow" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.20.0/24" } } # test-vpc1/subnet3 [10.240.30.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet3" { - name = "acl-test-vpc1--subnet3" + name = "acl-test-vpc1--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny all communication; subnet test-vpc1/subnet3[10.240.30.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.30.0/24" } # Deny all communication; subnet test-vpc1/subnet3[10.240.30.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.30.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.30.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_nif_tf/nacl_expected.tf b/test/expected/acl_nif_tf/nacl_expected.tf index 5d999aac..b3a073ba 100644 --- a/test/expected/acl_nif_tf/nacl_expected.tf +++ b/test/expected/acl_nif_tf/nacl_expected.tf @@ -1,14 +1,14 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.0.0/24" icmp { type = 0 @@ -16,10 +16,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.8.0/24" icmp { type = 8 @@ -29,25 +29,25 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.8.0/24" tcp { } } # Internal. response to required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.1.0/24" tcp { } @@ -56,61 +56,61 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet2[10.240.4.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.4.0/24" } # Deny all communication; subnet test-vpc0/subnet2[10.240.4.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.4.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet3[10.240.5.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.5.0/24" } # Deny all communication; subnet test-vpc0/subnet3[10.240.5.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.5.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.5.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.0.0/24" icmp { type = 0 @@ -118,10 +118,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.8.0/24" icmp { type = 8 @@ -129,20 +129,20 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.8.0/24" tcp { } } # Internal. response to required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.1.0/24" tcp { } @@ -151,115 +151,115 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet5[10.240.9.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.9.0/24" } # Deny all communication; subnet test-vpc0/subnet5[10.240.9.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.9.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.9.0/24" destination = "0.0.0.0/0" } } # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny all communication; subnet test-vpc1/subnet10[10.240.64.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.64.0/24" } # Deny all communication; subnet test-vpc1/subnet10[10.240.64.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.64.0/24" destination = "0.0.0.0/0" } } # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny all communication; subnet test-vpc1/subnet11[10.240.80.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.80.0/24" } # Deny all communication; subnet test-vpc1/subnet11[10.240.80.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.80.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.80.0/24" destination = "0.0.0.0/0" } } # test-vpc2/subnet20 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } # test-vpc3/subnet30 [10.240.192.0/24] resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_protocols_tf/nacl_expected.tf b/test/expected/acl_protocols_tf/nacl_expected.tf index 89da29a6..444efeb6 100644 --- a/test/expected/acl_protocols_tf/nacl_expected.tf +++ b/test/expected/acl_protocols_tf/nacl_expected.tf @@ -1,107 +1,107 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" tcp { } } # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" icmp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" icmp { } } # Internal. required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.9.0/24" } # Internal. response to required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.9.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.9.0/24" destination = "10.240.0.0/24" } } # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" tcp { } } # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" icmp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" icmp { } @@ -110,15 +110,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" tcp { port_min = 8080 @@ -127,10 +127,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { } # Internal. response to required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.5.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.5.0/24" destination = "10.240.4.0/24" tcp { source_port_min = 8080 @@ -139,10 +139,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { } # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" icmp { type = 3 @@ -153,15 +153,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" tcp { port_min = 8080 @@ -170,10 +170,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. response to required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.5.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.5.0/24" destination = "10.240.4.0/24" tcp { source_port_min = 8080 @@ -182,10 +182,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" icmp { type = 3 @@ -196,15 +196,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 15 @@ -212,10 +212,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.9.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.9.0/24" destination = "10.240.8.0/24" icmp { type = 16 @@ -223,10 +223,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" udp { } @@ -235,15 +235,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 15 @@ -251,10 +251,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.9.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.9.0/24" destination = "10.240.8.0/24" icmp { type = 16 @@ -262,43 +262,43 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { } # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" udp { } } # Internal. required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.9.0/24" } # Internal. response to required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.9.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.9.0/24" destination = "10.240.0.0/24" } } # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" udp { port_min = 53 @@ -309,15 +309,15 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" udp { port_min = 53 @@ -328,46 +328,46 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { # test-vpc2/subnet20 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } # test-vpc3/subnet30 [10.240.192.0/24] resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_segments_tf/nacl_expected.tf b/test/expected/acl_segments_tf/nacl_expected.tf index a781952b..7e615697 100644 --- a/test/expected/acl_segments_tf/nacl_expected.tf +++ b/test/expected/acl_segments_tf/nacl_expected.tf @@ -1,233 +1,233 @@ # testacl5-vpc/sub1-1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { - name = "acl-testacl5-vpc--sub1-1" + name = "acl-testacl5-vpc--sub1-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Deny all communication; subnet testacl5-vpc/sub1-1[10.240.1.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.1.0/24" } # Deny all communication; subnet testacl5-vpc/sub1-1[10.240.1.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.1.0/24" destination = "0.0.0.0/0" } } # testacl5-vpc/sub1-2 [10.240.2.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-2" { - name = "acl-testacl5-vpc--sub1-2" + name = "acl-testacl5-vpc--sub1-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.2.0/23" } # Internal. response to required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.2.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.2.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.2.0/24" } } # testacl5-vpc/sub1-3 [10.240.3.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-3" { - name = "acl-testacl5-vpc--sub1-3" + name = "acl-testacl5-vpc--sub1-3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.2.0/23" } # Internal. response to required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.3.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.3.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.3.0/24" } } # testacl5-vpc/sub2-1 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { - name = "acl-testacl5-vpc--sub2-1" + name = "acl-testacl5-vpc--sub2-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.64.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.2.0/23" } # Internal. required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } } # testacl5-vpc/sub2-2 [10.240.65.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-2" { - name = "acl-testacl5-vpc--sub2-2" + name = "acl-testacl5-vpc--sub2-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.65.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.2.0/23" } # Internal. required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } } # testacl5-vpc/sub3-1 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { - name = "acl-testacl5-vpc--sub3-1" + name = "acl-testacl5-vpc--sub3-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Deny all communication; subnet testacl5-vpc/sub3-1[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet testacl5-vpc/sub3-1[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_testing5_tf/nacl_expected.tf b/test/expected/acl_testing5_tf/nacl_expected.tf index 69925897..1664f0e1 100644 --- a/test/expected/acl_testing5_tf/nacl_expected.tf +++ b/test/expected/acl_testing5_tf/nacl_expected.tf @@ -1,30 +1,30 @@ # testacl5-vpc/sub1-1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { - name = "acl-testacl5-vpc--sub1-1" + name = "acl-testacl5-vpc--sub1-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -32,10 +32,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -43,194 +43,194 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule6" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule6" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule7" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule7" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule8" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule8" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule9" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule9" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule10" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule10" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule11" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule11" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule12" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule12" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule13" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule13" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule14" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule14" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule15" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule15" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule16" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule16" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule17" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule17" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule18" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule18" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule19" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule19" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule20" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule20" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule21" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule21" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule22" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule22" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule23" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule23" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule24" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule24" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule25" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule25" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule26" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule26" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "8.8.8.8" udp { port_min = 53 @@ -241,45 +241,45 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { # testacl5-vpc/sub1-2 [10.240.2.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-2" { - name = "acl-testacl5-vpc--sub1-2" + name = "acl-testacl5-vpc--sub1-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } @@ -288,45 +288,45 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-2" { # testacl5-vpc/sub1-3 [10.240.3.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-3" { - name = "acl-testacl5-vpc--sub1-3" + name = "acl-testacl5-vpc--sub1-3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } @@ -335,31 +335,31 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-3" { # testacl5-vpc/sub2-1 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { - name = "acl-testacl5-vpc--sub2-1" + name = "acl-testacl5-vpc--sub2-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -367,10 +367,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -378,26 +378,26 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule6" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule6" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -406,10 +406,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule7" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule7" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 @@ -418,154 +418,154 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule8" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule8" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule9" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule9" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule10" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule10" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule11" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule11" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule12" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule12" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule13" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule13" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule14" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule14" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule15" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule15" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule16" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule16" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule17" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule17" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule18" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule18" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule19" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule19" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule20" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule20" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule21" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule21" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule22" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule22" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule23" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule23" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule24" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule24" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule25" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule25" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule26" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule26" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "8.8.8.8" udp { port_min = 53 @@ -576,38 +576,38 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { # testacl5-vpc/sub2-2 [10.240.65.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-2" { - name = "acl-testacl5-vpc--sub2-2" + name = "acl-testacl5-vpc--sub2-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } } # testacl5-vpc/sub3-1 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { - name = "acl-testacl5-vpc--sub3-1" + name = "acl-testacl5-vpc--sub3-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -615,10 +615,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -626,10 +626,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -637,10 +637,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -648,10 +648,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -660,10 +660,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 diff --git a/test/expected/acl_testing5_tf_single/nacl_single_expected.tf b/test/expected/acl_testing5_tf_single/nacl_single_expected.tf index 5e3a1e07..0aa3da5c 100644 --- a/test/expected/acl_testing5_tf_single/nacl_single_expected.tf +++ b/test/expected/acl_testing5_tf_single/nacl_single_expected.tf @@ -1,45 +1,45 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { - name = "acl-testacl5-vpc--singleACL" + name = "acl-testacl5-vpc--singleACL" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -47,10 +47,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -58,10 +58,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule6" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule6" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -69,10 +69,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule7" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule7" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -80,10 +80,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule8" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule8" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -91,10 +91,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule9" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule9" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -102,10 +102,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule10" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule10" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -113,10 +113,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule11" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule11" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -124,162 +124,162 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule12" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule12" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule13" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule13" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule14" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule14" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule15" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule15" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule16" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule16" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule17" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule17" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule18" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule18" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule19" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule19" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule20" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule20" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule21" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule21" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule22" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule22" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule23" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule23" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule24" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule24" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule25" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule25" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule26" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule26" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule27" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule27" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule28" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule28" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -288,10 +288,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule29" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule29" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 @@ -300,10 +300,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule30" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule30" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -312,10 +312,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule31" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule31" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 @@ -324,154 +324,154 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule32" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule32" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule33" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule33" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule34" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule34" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule35" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule35" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule36" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule36" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule37" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule37" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule38" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule38" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule39" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule39" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule40" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule40" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule41" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule41" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule42" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule42" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule43" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule43" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule44" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule44" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule45" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule45" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule46" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule46" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule47" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule47" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule48" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule48" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule49" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule49" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule50" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule50" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "8.8.8.8" udp { port_min = 53 @@ -480,10 +480,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule51" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule51" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "8.8.8.8" udp { port_min = 53 diff --git a/test/expected/acl_tg_multiple_tf/nacl_expected.tf b/test/expected/acl_tg_multiple_tf/nacl_expected.tf index da72d490..f140447f 100644 --- a/test/expected/acl_tg_multiple_tf/nacl_expected.tf +++ b/test/expected/acl_tg_multiple_tf/nacl_expected.tf @@ -1,30 +1,30 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -35,54 +35,54 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.1.0/24" } # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.1.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -93,15 +93,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -110,10 +110,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -124,15 +124,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 @@ -142,15 +142,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 @@ -160,15 +160,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -176,10 +176,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -189,15 +189,15 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -205,10 +205,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -218,46 +218,46 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { # test-vpc2/subnet20 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } # test-vpc3/subnet30 [10.240.192.0/24] resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf index f4076710..7db93464 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf @@ -1,30 +1,30 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -35,54 +35,54 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.1.0/24" } # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.1.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -93,15 +93,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -110,10 +110,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -124,15 +124,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 @@ -142,15 +142,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf index 62ada153..78f27575 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf @@ -1,14 +1,14 @@ # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -16,10 +16,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -29,15 +29,15 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -45,10 +45,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf index 26cda248..72b647d1 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf @@ -1,21 +1,21 @@ resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf index bb8278a9..62ebac5b 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf @@ -1,21 +1,21 @@ resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/sg_protocols_tf/sg_expected.tf b/test/expected/sg_protocols_tf/sg_expected.tf index f7519b05..1367a53c 100644 --- a/test/expected/sg_protocols_tf/sg_expected.tf +++ b/test/expected/sg_protocols_tf/sg_expected.tf @@ -1,68 +1,68 @@ ### SG attached to test-vpc0/vsi0-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet0" { - name = "sg-test-vpc0--vsi0-subnet0" + name = "sg-test-vpc0--vsi0-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id udp { } } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id icmp { } } ### SG attached to test-vpc0/vsi0-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet1" { - name = "sg-test-vpc0--vsi0-subnet1" + name = "sg-test-vpc0--vsi0-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet1-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id udp { } } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet1-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id icmp { } } ### SG attached to test-vpc0/vsi0-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet2" { - name = "sg-test-vpc0--vsi0-subnet2" + name = "sg-test-vpc0--vsi0-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet2-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id tcp { } } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet2-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id icmp { type = 11 code = 1 @@ -71,23 +71,23 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet2-1" { ### SG attached to test-vpc0/vsi0-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet3" { - name = "sg-test-vpc0--vsi0-subnet3" + name = "sg-test-vpc0--vsi0-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet3-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id tcp { } } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet3-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id icmp { type = 11 code = 1 @@ -96,29 +96,29 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet3-1" { ### SG attached to test-vpc0/vsi0-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet4" { - name = "sg-test-vpc0--vsi0-subnet4" + name = "sg-test-vpc0--vsi0-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet5" { - name = "sg-test-vpc0--vsi0-subnet5" + name = "sg-test-vpc0--vsi0-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet0" { - name = "sg-test-vpc0--vsi1-subnet0" + name = "sg-test-vpc0--vsi1-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-0" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id tcp { port_min = 8080 port_max = 8080 @@ -126,9 +126,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-0" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-1" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id udp { port_min = 53 port_max = 53 @@ -136,9 +136,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-1" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[2] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-2" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id icmp { type = 8 } @@ -146,15 +146,15 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-2" { ### SG attached to test-vpc0/vsi1-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet1" { - name = "sg-test-vpc0--vsi1-subnet1" + name = "sg-test-vpc0--vsi1-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-0" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id tcp { port_min = 8080 port_max = 8080 @@ -162,9 +162,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-0" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-1" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id udp { port_min = 53 port_max = 53 @@ -172,9 +172,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-1" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[2] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-2" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id icmp { type = 8 } @@ -182,84 +182,84 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-2" { ### SG attached to test-vpc0/vsi1-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet2" { - name = "sg-test-vpc0--vsi1-subnet2" + name = "sg-test-vpc0--vsi1-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet3" { - name = "sg-test-vpc0--vsi1-subnet3" + name = "sg-test-vpc0--vsi1-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet4" { - name = "sg-test-vpc0--vsi1-subnet4" + name = "sg-test-vpc0--vsi1-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet5" { - name = "sg-test-vpc0--vsi1-subnet5" + name = "sg-test-vpc0--vsi1-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc1/vsi0-subnet10 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet10" { - name = "sg-test-vpc1--vsi0-subnet10" + name = "sg-test-vpc1--vsi0-subnet10" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } # External. required-connections[3]: (instance test-vpc1/vsi0-subnet10)->(external dns); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet10-0" { - group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id + group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id direction = "outbound" - remote = "8.8.8.8" + remote = "8.8.8.8" tcp { } } ### SG attached to test-vpc1/vsi0-subnet11 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet11" { - name = "sg-test-vpc1--vsi0-subnet11" + name = "sg-test-vpc1--vsi0-subnet11" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } ### SG attached to test-vpc2/vsi0-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi0-subnet20" { - name = "sg-test-vpc2--vsi0-subnet20" + name = "sg-test-vpc2--vsi0-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } ### SG attached to test-vpc2/vsi1-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi1-subnet20" { - name = "sg-test-vpc2--vsi1-subnet20" + name = "sg-test-vpc2--vsi1-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } # External. required-connections[4]: (instance test-vpc2/vsi1-subnet20)->(external public internet); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc2--vsi1-subnet20-0" { - group = ibm_is_security_group.test-vpc2--vsi1-subnet20.id + group = ibm_is_security_group.test-vpc2--vsi1-subnet20.id direction = "outbound" - remote = "0.0.0.0/0" + remote = "0.0.0.0/0" } ### SG attached to test-vpc2/vsi2-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi2-subnet20" { - name = "sg-test-vpc2--vsi2-subnet20" + name = "sg-test-vpc2--vsi2-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } ### SG attached to test-vpc3/vsi0-subnet30 resource "ibm_is_security_group" "test-vpc3--vsi0-subnet30" { - name = "sg-test-vpc3--vsi0-subnet30" + name = "sg-test-vpc3--vsi0-subnet30" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc3_id + vpc = local.sg_synth_test-vpc3_id } diff --git a/test/expected/sg_testing3_tf/sg_expected.tf b/test/expected/sg_testing3_tf/sg_expected.tf index 8bfb66a3..0da81523 100644 --- a/test/expected/sg_testing3_tf/sg_expected.tf +++ b/test/expected/sg_testing3_tf/sg_expected.tf @@ -1,48 +1,48 @@ ### SG attached to test-vpc/appdata-endpoint-gateway resource "ibm_is_security_group" "test-vpc--appdata-endpoint-gateway" { - name = "sg-test-vpc--appdata-endpoint-gateway" + name = "sg-test-vpc--appdata-endpoint-gateway" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } ### SG attached to test-vpc/be resource "ibm_is_security_group" "test-vpc--be" { - name = "sg-test-vpc--be" + name = "sg-test-vpc--be" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[2]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--be-0" { - group = ibm_is_security_group.test-vpc--be.id + group = ibm_is_security_group.test-vpc--be.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--fe.id + remote = ibm_is_security_group.test-vpc--fe.id tcp { } } # Internal. required-connections[3]: (instance test-vpc/be)->(instance test-vpc/opa); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--be-1" { - group = ibm_is_security_group.test-vpc--be.id + group = ibm_is_security_group.test-vpc--be.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--opa.id + remote = ibm_is_security_group.test-vpc--opa.id } # Internal. required-connections[4]: (instance test-vpc/be)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--be-2" { - group = ibm_is_security_group.test-vpc--be.id + group = ibm_is_security_group.test-vpc--be.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id } ### SG attached to test-vpc/fe resource "ibm_is_security_group" "test-vpc--fe" { - name = "sg-test-vpc--fe" + name = "sg-test-vpc--fe" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--fe-0" { - group = ibm_is_security_group.test-vpc--fe.id + group = ibm_is_security_group.test-vpc--fe.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--proxy.id + remote = ibm_is_security_group.test-vpc--proxy.id tcp { port_min = 9000 port_max = 9000 @@ -50,68 +50,68 @@ resource "ibm_is_security_group_rule" "test-vpc--fe-0" { } # Internal. required-connections[2]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--fe-1" { - group = ibm_is_security_group.test-vpc--fe.id + group = ibm_is_security_group.test-vpc--fe.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--be.id + remote = ibm_is_security_group.test-vpc--be.id tcp { } } ### SG attached to test-vpc/opa resource "ibm_is_security_group" "test-vpc--opa" { - name = "sg-test-vpc--opa" + name = "sg-test-vpc--opa" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[3]: (instance test-vpc/be)->(instance test-vpc/opa); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--opa-0" { - group = ibm_is_security_group.test-vpc--opa.id + group = ibm_is_security_group.test-vpc--opa.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--be.id + remote = ibm_is_security_group.test-vpc--be.id } # Internal. required-connections[5]: (instance test-vpc/opa)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--opa-1" { - group = ibm_is_security_group.test-vpc--opa.id + group = ibm_is_security_group.test-vpc--opa.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id } ### SG attached to test-vpc/policydb-endpoint-gateway resource "ibm_is_security_group" "test-vpc--policydb-endpoint-gateway" { - name = "sg-test-vpc--policydb-endpoint-gateway" + name = "sg-test-vpc--policydb-endpoint-gateway" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[4]: (instance test-vpc/be)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--policydb-endpoint-gateway-0" { - group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--be.id + remote = ibm_is_security_group.test-vpc--be.id } # Internal. required-connections[5]: (instance test-vpc/opa)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--policydb-endpoint-gateway-1" { - group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--opa.id + remote = ibm_is_security_group.test-vpc--opa.id } ### SG attached to test-vpc/proxy resource "ibm_is_security_group" "test-vpc--proxy" { - name = "sg-test-vpc--proxy" + name = "sg-test-vpc--proxy" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # External. required-connections[0]: (external public internet)->(instance test-vpc/proxy); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--proxy-0" { - group = ibm_is_security_group.test-vpc--proxy.id + group = ibm_is_security_group.test-vpc--proxy.id direction = "inbound" - remote = "0.0.0.0/0" + remote = "0.0.0.0/0" } # Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--proxy-1" { - group = ibm_is_security_group.test-vpc--proxy.id + group = ibm_is_security_group.test-vpc--proxy.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--fe.id + remote = ibm_is_security_group.test-vpc--fe.id tcp { port_min = 9000 port_max = 9000 diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf index 8f4979ba..07de4293 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf @@ -1,95 +1,95 @@ ### SG attached to test-vpc0/vsi0-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet0" { - name = "sg-test-vpc0--vsi0-subnet0" + name = "sg-test-vpc0--vsi0-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi1-subnet4); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet4.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet4.id } ### SG attached to test-vpc0/vsi0-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet1" { - name = "sg-test-vpc0--vsi0-subnet1" + name = "sg-test-vpc0--vsi0-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet2" { - name = "sg-test-vpc0--vsi0-subnet2" + name = "sg-test-vpc0--vsi0-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet3" { - name = "sg-test-vpc0--vsi0-subnet3" + name = "sg-test-vpc0--vsi0-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet4" { - name = "sg-test-vpc0--vsi0-subnet4" + name = "sg-test-vpc0--vsi0-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet5" { - name = "sg-test-vpc0--vsi0-subnet5" + name = "sg-test-vpc0--vsi0-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet0" { - name = "sg-test-vpc0--vsi1-subnet0" + name = "sg-test-vpc0--vsi1-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet1" { - name = "sg-test-vpc0--vsi1-subnet1" + name = "sg-test-vpc0--vsi1-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet2" { - name = "sg-test-vpc0--vsi1-subnet2" + name = "sg-test-vpc0--vsi1-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet3" { - name = "sg-test-vpc0--vsi1-subnet3" + name = "sg-test-vpc0--vsi1-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet4" { - name = "sg-test-vpc0--vsi1-subnet4" + name = "sg-test-vpc0--vsi1-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi1-subnet4); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet4-0" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet4.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet4.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id } ### SG attached to test-vpc0/vsi1-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet5" { - name = "sg-test-vpc0--vsi1-subnet5" + name = "sg-test-vpc0--vsi1-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf index 06e11954..a4810cf4 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf @@ -1,29 +1,29 @@ ### SG attached to test-vpc1/vsi0-subnet10 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet10" { - name = "sg-test-vpc1--vsi0-subnet10" + name = "sg-test-vpc1--vsi0-subnet10" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } # Internal. required-connections[2]: (instance test-vpc1/vsi0-subnet10)->(instance test-vpc1/vsi0-subnet11); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet10-0" { - group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id + group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id direction = "outbound" - remote = ibm_is_security_group.test-vpc1--vsi0-subnet11.id + remote = ibm_is_security_group.test-vpc1--vsi0-subnet11.id tcp { } } ### SG attached to test-vpc1/vsi0-subnet11 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet11" { - name = "sg-test-vpc1--vsi0-subnet11" + name = "sg-test-vpc1--vsi0-subnet11" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } # Internal. required-connections[2]: (instance test-vpc1/vsi0-subnet10)->(instance test-vpc1/vsi0-subnet11); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet11-0" { - group = ibm_is_security_group.test-vpc1--vsi0-subnet11.id + group = ibm_is_security_group.test-vpc1--vsi0-subnet11.id direction = "inbound" - remote = ibm_is_security_group.test-vpc1--vsi0-subnet10.id + remote = ibm_is_security_group.test-vpc1--vsi0-subnet10.id tcp { } } diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf index bf96f422..a4e97bbb 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf @@ -1,14 +1,14 @@ ### SG attached to test-vpc2/vsi0-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi0-subnet20" { - name = "sg-test-vpc2--vsi0-subnet20" + name = "sg-test-vpc2--vsi0-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } # Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc2--vsi0-subnet20-0" { - group = ibm_is_security_group.test-vpc2--vsi0-subnet20.id + group = ibm_is_security_group.test-vpc2--vsi0-subnet20.id direction = "outbound" - remote = ibm_is_security_group.test-vpc2--vsi2-subnet20.id + remote = ibm_is_security_group.test-vpc2--vsi2-subnet20.id tcp { port_min = 53 port_max = 53 @@ -17,22 +17,22 @@ resource "ibm_is_security_group_rule" "test-vpc2--vsi0-subnet20-0" { ### SG attached to test-vpc2/vsi1-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi1-subnet20" { - name = "sg-test-vpc2--vsi1-subnet20" + name = "sg-test-vpc2--vsi1-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } ### SG attached to test-vpc2/vsi2-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi2-subnet20" { - name = "sg-test-vpc2--vsi2-subnet20" + name = "sg-test-vpc2--vsi2-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } # Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc2--vsi2-subnet20-0" { - group = ibm_is_security_group.test-vpc2--vsi2-subnet20.id + group = ibm_is_security_group.test-vpc2--vsi2-subnet20.id direction = "inbound" - remote = ibm_is_security_group.test-vpc2--vsi0-subnet20.id + remote = ibm_is_security_group.test-vpc2--vsi0-subnet20.id tcp { port_min = 53 port_max = 53 diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf index ef77175b..b01452c6 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf @@ -1,6 +1,6 @@ ### SG attached to test-vpc3/vsi0-subnet30 resource "ibm_is_security_group" "test-vpc3--vsi0-subnet30" { - name = "sg-test-vpc3--vsi0-subnet30" + name = "sg-test-vpc3--vsi0-subnet30" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc3_id + vpc = local.sg_synth_test-vpc3_id } From c2512d9fa38cbde10a008b58455e448591accb56 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 13:50:43 +0300 Subject: [PATCH 64/79] make fmt --- .../acl_externals_tf/nacl_expected.tf | 348 +++++------ test/expected/acl_nif_tf/nacl_expected.tf | 216 +++---- .../acl_protocols_tf/nacl_expected.tf | 280 ++++----- .../expected/acl_segments_tf/nacl_expected.tf | 216 +++---- .../expected/acl_testing5_tf/nacl_expected.tf | 584 +++++++++--------- .../nacl_single_expected.tf | 420 ++++++------- .../acl_tg_multiple_tf/nacl_expected.tf | 200 +++--- .../acl_tg_multiple_tf_separate/test-vpc0.tf | 120 ++-- .../acl_tg_multiple_tf_separate/test-vpc1.tf | 40 +- .../acl_tg_multiple_tf_separate/test-vpc2.tf | 20 +- .../acl_tg_multiple_tf_separate/test-vpc3.tf | 20 +- test/expected/sg_protocols_tf/sg_expected.tf | 136 ++-- test/expected/sg_testing3_tf/sg_expected.tf | 68 +- .../sg_tg_multiple_tf_separate/test-vpc0.tf | 56 +- .../sg_tg_multiple_tf_separate/test-vpc1.tf | 16 +- .../sg_tg_multiple_tf_separate/test-vpc2.tf | 20 +- .../sg_tg_multiple_tf_separate/test-vpc3.tf | 4 +- 17 files changed, 1382 insertions(+), 1382 deletions(-) diff --git a/test/expected/acl_externals_tf/nacl_expected.tf b/test/expected/acl_externals_tf/nacl_expected.tf index 5a9777d1..f5b01067 100644 --- a/test/expected/acl_externals_tf/nacl_expected.tf +++ b/test/expected/acl_externals_tf/nacl_expected.tf @@ -1,356 +1,356 @@ # test-vpc1/subnet1 [10.240.10.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet1" { - name = "acl-test-vpc1--subnet1" + name = "acl-test-vpc1--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule0" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule0" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule1" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule1" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule2" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule2" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule3" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule3" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule4" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule4" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule5" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule5" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule6" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule6" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule7" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule7" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule8" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule8" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule9" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule9" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule10" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule10" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule11" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule11" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule12" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule12" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule13" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule13" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule14" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule14" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule15" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule15" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule16" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule16" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule17" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule17" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[0]: (external dns)->(subnet test-vpc1/subnet1); allowed-protocols[0] rules { - name = "rule18" - action = "allow" - direction = "inbound" - source = "8.8.8.8" + name = "rule18" + action = "allow" + direction = "inbound" + source = "8.8.8.8" destination = "10.240.10.0/24" } # External. response to required-connections[0]: (external dns)->(subnet test-vpc1/subnet1); allowed-protocols[0] rules { - name = "rule19" - action = "allow" - direction = "outbound" - source = "10.240.10.0/24" + name = "rule19" + action = "allow" + direction = "outbound" + source = "10.240.10.0/24" destination = "8.8.8.8" } } # test-vpc1/subnet2 [10.240.20.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet2" { - name = "acl-test-vpc1--subnet2" + name = "acl-test-vpc1--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule0" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule0" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule1" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule1" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule2" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule2" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule3" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule3" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule4" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule4" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule5" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule5" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule6" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule6" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule7" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule7" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule8" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule8" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule9" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule9" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule10" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule10" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule11" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule11" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule12" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule12" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule13" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule13" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule14" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule14" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule15" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule15" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule16" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule16" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule17" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule17" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (subnet test-vpc1/subnet2)->(external public internet); allowed-protocols[0] rules { - name = "rule18" - action = "allow" - direction = "outbound" - source = "10.240.20.0/24" + name = "rule18" + action = "allow" + direction = "outbound" + source = "10.240.20.0/24" destination = "0.0.0.0/0" } # External. response to required-connections[1]: (subnet test-vpc1/subnet2)->(external public internet); allowed-protocols[0] rules { - name = "rule19" - action = "allow" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule19" + action = "allow" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.20.0/24" } } # test-vpc1/subnet3 [10.240.30.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet3" { - name = "acl-test-vpc1--subnet3" + name = "acl-test-vpc1--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny all communication; subnet test-vpc1/subnet3[10.240.30.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.30.0/24" } # Deny all communication; subnet test-vpc1/subnet3[10.240.30.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.30.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.30.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_nif_tf/nacl_expected.tf b/test/expected/acl_nif_tf/nacl_expected.tf index b3a073ba..5d999aac 100644 --- a/test/expected/acl_nif_tf/nacl_expected.tf +++ b/test/expected/acl_nif_tf/nacl_expected.tf @@ -1,14 +1,14 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.0.0/24" icmp { type = 0 @@ -16,10 +16,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.8.0/24" icmp { type = 8 @@ -29,25 +29,25 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.8.0/24" tcp { } } # Internal. response to required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.1.0/24" tcp { } @@ -56,61 +56,61 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet2[10.240.4.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.4.0/24" } # Deny all communication; subnet test-vpc0/subnet2[10.240.4.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.4.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet3[10.240.5.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.5.0/24" } # Deny all communication; subnet test-vpc0/subnet3[10.240.5.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.5.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.5.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.0.0/24" icmp { type = 0 @@ -118,10 +118,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet4)->(instance test-vpc0/vsi0-subnet0); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.8.0/24" icmp { type = 8 @@ -129,20 +129,20 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.8.0/24" tcp { } } # Internal. response to required-connections[1]: (nif test-vpc0/vsi0-subnet1/scale-clambake-endearing-abridged)->(subnet test-vpc0/subnet4); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.1.0/24" tcp { } @@ -151,115 +151,115 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet5[10.240.9.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.9.0/24" } # Deny all communication; subnet test-vpc0/subnet5[10.240.9.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.9.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.9.0/24" destination = "0.0.0.0/0" } } # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny all communication; subnet test-vpc1/subnet10[10.240.64.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.64.0/24" } # Deny all communication; subnet test-vpc1/subnet10[10.240.64.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.64.0/24" destination = "0.0.0.0/0" } } # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Deny all communication; subnet test-vpc1/subnet11[10.240.80.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.80.0/24" } # Deny all communication; subnet test-vpc1/subnet11[10.240.80.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.80.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.80.0/24" destination = "0.0.0.0/0" } } # test-vpc2/subnet20 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } # test-vpc3/subnet30 [10.240.192.0/24] resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_protocols_tf/nacl_expected.tf b/test/expected/acl_protocols_tf/nacl_expected.tf index 444efeb6..89da29a6 100644 --- a/test/expected/acl_protocols_tf/nacl_expected.tf +++ b/test/expected/acl_protocols_tf/nacl_expected.tf @@ -1,107 +1,107 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" tcp { } } # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" icmp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" icmp { } } # Internal. required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.9.0/24" } # Internal. response to required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.9.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.9.0/24" destination = "10.240.0.0/24" } } # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" tcp { } } # Internal. required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.1.0/24" icmp { } } # Internal. response to required-connections[0]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet1); allowed-protocols[1] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.0.0/24" icmp { } @@ -110,15 +110,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" tcp { port_min = 8080 @@ -127,10 +127,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { } # Internal. response to required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.5.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.5.0/24" destination = "10.240.4.0/24" tcp { source_port_min = 8080 @@ -139,10 +139,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { } # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" icmp { type = 3 @@ -153,15 +153,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" tcp { port_min = 8080 @@ -170,10 +170,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. response to required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.5.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.5.0/24" destination = "10.240.4.0/24" tcp { source_port_min = 8080 @@ -182,10 +182,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. required-connections[1]: (subnet test-vpc0/subnet2)->(subnet test-vpc0/subnet3); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" icmp { type = 3 @@ -196,15 +196,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 15 @@ -212,10 +212,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.9.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.9.0/24" destination = "10.240.8.0/24" icmp { type = 16 @@ -223,10 +223,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { } # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" udp { } @@ -235,15 +235,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 15 @@ -251,10 +251,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { } # Internal. response to required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.9.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.9.0/24" destination = "10.240.8.0/24" icmp { type = 16 @@ -262,43 +262,43 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { } # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[1] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" udp { } } # Internal. required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.9.0/24" } # Internal. response to required-connections[4]: (subnet test-vpc0/subnet0)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.9.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.9.0/24" destination = "10.240.0.0/24" } } # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" udp { port_min = 53 @@ -309,15 +309,15 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" udp { port_min = 53 @@ -328,46 +328,46 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { # test-vpc2/subnet20 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } # test-vpc3/subnet30 [10.240.192.0/24] resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_segments_tf/nacl_expected.tf b/test/expected/acl_segments_tf/nacl_expected.tf index 7e615697..a781952b 100644 --- a/test/expected/acl_segments_tf/nacl_expected.tf +++ b/test/expected/acl_segments_tf/nacl_expected.tf @@ -1,233 +1,233 @@ # testacl5-vpc/sub1-1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { - name = "acl-testacl5-vpc--sub1-1" + name = "acl-testacl5-vpc--sub1-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Deny all communication; subnet testacl5-vpc/sub1-1[10.240.1.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.1.0/24" } # Deny all communication; subnet testacl5-vpc/sub1-1[10.240.1.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.1.0/24" destination = "0.0.0.0/0" } } # testacl5-vpc/sub1-2 [10.240.2.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-2" { - name = "acl-testacl5-vpc--sub1-2" + name = "acl-testacl5-vpc--sub1-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.2.0/23" } # Internal. response to required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.2.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.2.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.2.0/24" } } # testacl5-vpc/sub1-3 [10.240.3.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-3" { - name = "acl-testacl5-vpc--sub1-3" + name = "acl-testacl5-vpc--sub1-3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.2.0/23" } # Internal. response to required-connections[0]: (segment cidrSegment)->(segment cidrSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.3.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.3.0/24" } # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.3.0/24" } } # testacl5-vpc/sub2-1 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { - name = "acl-testacl5-vpc--sub2-1" + name = "acl-testacl5-vpc--sub2-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.64.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.2.0/23" } # Internal. required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } } # testacl5-vpc/sub2-2 [10.240.65.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-2" { - name = "acl-testacl5-vpc--sub2-2" + name = "acl-testacl5-vpc--sub2-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.2.0/23" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.2.0/23" destination = "10.240.65.0/24" } # Internal. response to required-connections[1]: (segment cidrSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.2.0/23" } # Internal. required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[2]: (segment subnetSegment)->(segment subnetSegment); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } } # testacl5-vpc/sub3-1 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { - name = "acl-testacl5-vpc--sub3-1" + name = "acl-testacl5-vpc--sub3-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Deny all communication; subnet testacl5-vpc/sub3-1[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet testacl5-vpc/sub3-1[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_testing5_tf/nacl_expected.tf b/test/expected/acl_testing5_tf/nacl_expected.tf index 1664f0e1..69925897 100644 --- a/test/expected/acl_testing5_tf/nacl_expected.tf +++ b/test/expected/acl_testing5_tf/nacl_expected.tf @@ -1,30 +1,30 @@ # testacl5-vpc/sub1-1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { - name = "acl-testacl5-vpc--sub1-1" + name = "acl-testacl5-vpc--sub1-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -32,10 +32,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -43,194 +43,194 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule6" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule6" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule7" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule7" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule8" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule8" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule9" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule9" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule10" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule10" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule11" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule11" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule12" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule12" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule13" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule13" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule14" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule14" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule15" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule15" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule16" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule16" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule17" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule17" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule18" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule18" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule19" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule19" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule20" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule20" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule21" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule21" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule22" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule22" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule23" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule23" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule24" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule24" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule25" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule25" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule26" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule26" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "8.8.8.8" udp { port_min = 53 @@ -241,45 +241,45 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-1" { # testacl5-vpc/sub1-2 [10.240.2.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-2" { - name = "acl-testacl5-vpc--sub1-2" + name = "acl-testacl5-vpc--sub1-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } @@ -288,45 +288,45 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-2" { # testacl5-vpc/sub1-3 [10.240.3.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-3" { - name = "acl-testacl5-vpc--sub1-3" + name = "acl-testacl5-vpc--sub1-3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } @@ -335,31 +335,31 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub1-3" { # testacl5-vpc/sub2-1 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { - name = "acl-testacl5-vpc--sub2-1" + name = "acl-testacl5-vpc--sub2-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -367,10 +367,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule3" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -378,26 +378,26 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule6" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule6" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -406,10 +406,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule7" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule7" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 @@ -418,154 +418,154 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule8" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule8" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule9" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule9" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule10" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule10" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule11" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule11" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule12" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule12" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule13" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule13" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule14" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule14" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule15" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule15" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule16" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule16" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule17" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule17" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule18" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule18" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule19" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule19" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule20" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule20" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule21" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule21" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule22" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule22" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule23" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule23" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule24" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule24" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule25" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule25" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule26" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule26" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "8.8.8.8" udp { port_min = 53 @@ -576,38 +576,38 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-1" { # testacl5-vpc/sub2-2 [10.240.65.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub2-2" { - name = "acl-testacl5-vpc--sub2-2" + name = "acl-testacl5-vpc--sub2-2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } } # testacl5-vpc/sub3-1 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { - name = "acl-testacl5-vpc--sub3-1" + name = "acl-testacl5-vpc--sub3-1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -615,10 +615,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -626,10 +626,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -637,10 +637,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -648,10 +648,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -660,10 +660,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--sub3-1" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 diff --git a/test/expected/acl_testing5_tf_single/nacl_single_expected.tf b/test/expected/acl_testing5_tf_single/nacl_single_expected.tf index 0aa3da5c..5e3a1e07 100644 --- a/test/expected/acl_testing5_tf_single/nacl_single_expected.tf +++ b/test/expected/acl_testing5_tf_single/nacl_single_expected.tf @@ -1,45 +1,45 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { - name = "acl-testacl5-vpc--singleACL" + name = "acl-testacl5-vpc--singleACL" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_testacl5-vpc_id + vpc = local.acl_synth_testacl5-vpc_id # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule2" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.64.0/24" } # Internal. response to required-connections[0]: (segment need-dns)->(segment need-dns); allowed-protocols[0] rules { - name = "rule3" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule3" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.1.0/24" } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule4" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule4" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -47,10 +47,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule5" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule5" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -58,10 +58,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule6" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule6" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -69,10 +69,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule7" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule7" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.1.0/24" icmp { type = 8 @@ -80,10 +80,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule8" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule8" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -91,10 +91,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule9" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule9" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -102,10 +102,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule10" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule10" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" icmp { type = 0 @@ -113,10 +113,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[2]: (segment need-dns)->(subnet testacl5-vpc/sub3-1); allowed-protocols[0] rules { - name = "rule11" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule11" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -124,162 +124,162 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule12" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule12" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule13" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule13" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule14" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule14" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. response to required-connections[3]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-2); allowed-protocols[0] rules { - name = "rule15" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule15" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule16" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule16" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule17" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule17" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule18" - action = "allow" - direction = "inbound" - source = "10.240.1.0/24" + name = "rule18" + action = "allow" + direction = "inbound" + source = "10.240.1.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[4]: (subnet testacl5-vpc/sub1-1)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule19" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule19" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.1.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule20" - action = "allow" - direction = "outbound" - source = "10.240.2.0/24" + name = "rule20" + action = "allow" + direction = "outbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule21" - action = "allow" - direction = "inbound" - source = "10.240.3.0/24" + name = "rule21" + action = "allow" + direction = "inbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule22" - action = "allow" - direction = "inbound" - source = "10.240.2.0/24" + name = "rule22" + action = "allow" + direction = "inbound" + source = "10.240.2.0/24" destination = "10.240.3.0/24" tcp { } } # Internal. response to required-connections[5]: (subnet testacl5-vpc/sub1-2)->(subnet testacl5-vpc/sub1-3); allowed-protocols[0] rules { - name = "rule23" - action = "allow" - direction = "outbound" - source = "10.240.3.0/24" + name = "rule23" + action = "allow" + direction = "outbound" + source = "10.240.3.0/24" destination = "10.240.2.0/24" tcp { } } # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule24" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule24" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule25" - action = "allow" - direction = "inbound" - source = "10.240.65.0/24" + name = "rule25" + action = "allow" + direction = "inbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } # Internal. required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule26" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule26" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.65.0/24" } # Internal. response to required-connections[6]: (subnet testacl5-vpc/sub2-1)->(subnet testacl5-vpc/sub2-2); allowed-protocols[0] rules { - name = "rule27" - action = "allow" - direction = "outbound" - source = "10.240.65.0/24" + name = "rule27" + action = "allow" + direction = "outbound" + source = "10.240.65.0/24" destination = "10.240.64.0/24" } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule28" - action = "allow" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule28" + action = "allow" + direction = "outbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -288,10 +288,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule29" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule29" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 @@ -300,10 +300,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule30" - action = "allow" - direction = "inbound" - source = "10.240.128.0/24" + name = "rule30" + action = "allow" + direction = "inbound" + source = "10.240.128.0/24" destination = "10.240.64.0/24" tcp { port_min = 443 @@ -312,10 +312,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Internal. response to required-connections[7]: (subnet testacl5-vpc/sub3-1)->(subnet testacl5-vpc/sub2-1); allowed-protocols[0] rules { - name = "rule31" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule31" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.128.0/24" tcp { source_port_min = 443 @@ -324,154 +324,154 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule32" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule32" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,0 rules { - name = "rule33" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule33" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule34" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule34" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 0,1 rules { - name = "rule35" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule35" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule36" - action = "deny" - direction = "outbound" - source = "10.0.0.0/8" + name = "rule36" + action = "deny" + direction = "outbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 0,2 rules { - name = "rule37" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule37" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule38" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule38" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 1,0 rules { - name = "rule39" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule39" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule40" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule40" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,1 rules { - name = "rule41" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule41" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule42" - action = "deny" - direction = "outbound" - source = "172.16.0.0/12" + name = "rule42" + action = "deny" + direction = "outbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 1,2 rules { - name = "rule43" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule43" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule44" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule44" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "10.0.0.0/8" } # Deny other internal communication; see rfc1918#3; item 2,0 rules { - name = "rule45" - action = "deny" - direction = "inbound" - source = "10.0.0.0/8" + name = "rule45" + action = "deny" + direction = "inbound" + source = "10.0.0.0/8" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule46" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule46" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "172.16.0.0/12" } # Deny other internal communication; see rfc1918#3; item 2,1 rules { - name = "rule47" - action = "deny" - direction = "inbound" - source = "172.16.0.0/12" + name = "rule47" + action = "deny" + direction = "inbound" + source = "172.16.0.0/12" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule48" - action = "deny" - direction = "outbound" - source = "192.168.0.0/16" + name = "rule48" + action = "deny" + direction = "outbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # Deny other internal communication; see rfc1918#3; item 2,2 rules { - name = "rule49" - action = "deny" - direction = "inbound" - source = "192.168.0.0/16" + name = "rule49" + action = "deny" + direction = "inbound" + source = "192.168.0.0/16" destination = "192.168.0.0/16" } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule50" - action = "allow" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule50" + action = "allow" + direction = "outbound" + source = "10.240.1.0/24" destination = "8.8.8.8" udp { port_min = 53 @@ -480,10 +480,10 @@ resource "ibm_is_network_acl" "acl-testacl5-vpc--singleACL" { } # External. required-connections[1]: (segment need-dns)->(external dns); allowed-protocols[0] rules { - name = "rule51" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule51" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "8.8.8.8" udp { port_min = 53 diff --git a/test/expected/acl_tg_multiple_tf/nacl_expected.tf b/test/expected/acl_tg_multiple_tf/nacl_expected.tf index f140447f..da72d490 100644 --- a/test/expected/acl_tg_multiple_tf/nacl_expected.tf +++ b/test/expected/acl_tg_multiple_tf/nacl_expected.tf @@ -1,30 +1,30 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -35,54 +35,54 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.1.0/24" } # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.1.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -93,15 +93,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -110,10 +110,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -124,15 +124,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 @@ -142,15 +142,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 @@ -160,15 +160,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -176,10 +176,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -189,15 +189,15 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -205,10 +205,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -218,46 +218,46 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { # test-vpc2/subnet20 [10.240.128.0/24] resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } # test-vpc3/subnet30 [10.240.192.0/24] resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf index 7db93464..f4076710 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc0.tf @@ -1,30 +1,30 @@ # test-vpc0/subnet0 [10.240.0.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { - name = "acl-test-vpc0--subnet0" + name = "acl-test-vpc0--subnet0" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.0.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -35,54 +35,54 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet0" { # test-vpc0/subnet1 [10.240.1.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet1" { - name = "acl-test-vpc0--subnet1" + name = "acl-test-vpc0--subnet1" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.1.0/24" } # Deny all communication; subnet test-vpc0/subnet1[10.240.1.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.1.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.1.0/24" destination = "0.0.0.0/0" } } # test-vpc0/subnet2 [10.240.4.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { - name = "acl-test-vpc0--subnet2" + name = "acl-test-vpc0--subnet2" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.4.0/24" } # Internal. response to required-connections[0]: (segment segment1)->(segment segment1); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.0.0/24" } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule2" - action = "allow" - direction = "outbound" - source = "10.240.4.0/24" + name = "rule2" + action = "allow" + direction = "outbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -93,15 +93,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet2" { # test-vpc0/subnet3 [10.240.5.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { - name = "acl-test-vpc0--subnet3" + name = "acl-test-vpc0--subnet3" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.0.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.0.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -110,10 +110,10 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { } # Internal. required-connections[1]: (segment segment1)->(subnet test-vpc0/subnet3); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.4.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.4.0/24" destination = "10.240.5.0/24" udp { port_min = 53 @@ -124,15 +124,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet3" { # test-vpc0/subnet4 [10.240.8.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { - name = "acl-test-vpc0--subnet4" + name = "acl-test-vpc0--subnet4" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 @@ -142,15 +142,15 @@ resource "ibm_is_network_acl" "acl-test-vpc0--subnet4" { # test-vpc0/subnet5 [10.240.9.0/24] resource "ibm_is_network_acl" "acl-test-vpc0--subnet5" { - name = "acl-test-vpc0--subnet5" + name = "acl-test-vpc0--subnet5" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc0_id + vpc = local.acl_synth_test-vpc0_id # Internal. required-connections[2]: (subnet test-vpc0/subnet4)->(subnet test-vpc0/subnet5); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.8.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.8.0/24" destination = "10.240.9.0/24" icmp { type = 4 diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf index 78f27575..62ada153 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc1.tf @@ -1,14 +1,14 @@ # test-vpc1/subnet10 [10.240.64.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { - name = "acl-test-vpc1--subnet10" + name = "acl-test-vpc1--subnet10" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "outbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "outbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -16,10 +16,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "inbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "inbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 @@ -29,15 +29,15 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet10" { # test-vpc1/subnet11 [10.240.80.0/24] resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { - name = "acl-test-vpc1--subnet11" + name = "acl-test-vpc1--subnet11" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc1_id + vpc = local.acl_synth_test-vpc1_id # Internal. required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule0" - action = "allow" - direction = "inbound" - source = "10.240.64.0/24" + name = "rule0" + action = "allow" + direction = "inbound" + source = "10.240.64.0/24" destination = "10.240.80.0/24" icmp { type = 0 @@ -45,10 +45,10 @@ resource "ibm_is_network_acl" "acl-test-vpc1--subnet11" { } # Internal. response to required-connections[3]: (subnet test-vpc1/subnet10)->(subnet test-vpc1/subnet11); allowed-protocols[0] rules { - name = "rule1" - action = "allow" - direction = "outbound" - source = "10.240.80.0/24" + name = "rule1" + action = "allow" + direction = "outbound" + source = "10.240.80.0/24" destination = "10.240.64.0/24" icmp { type = 8 diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf index 72b647d1..26cda248 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc2.tf @@ -1,21 +1,21 @@ resource "ibm_is_network_acl" "acl-test-vpc2--subnet20" { - name = "acl-test-vpc2--subnet20" + name = "acl-test-vpc2--subnet20" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc2_id + vpc = local.acl_synth_test-vpc2_id # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.128.0/24" } # Deny all communication; subnet test-vpc2/subnet20[10.240.128.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.128.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.128.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf b/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf index 62ebac5b..bb8278a9 100644 --- a/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf +++ b/test/expected/acl_tg_multiple_tf_separate/test-vpc3.tf @@ -1,21 +1,21 @@ resource "ibm_is_network_acl" "acl-test-vpc3--subnet30" { - name = "acl-test-vpc3--subnet30" + name = "acl-test-vpc3--subnet30" resource_group = local.acl_synth_resource_group_id - vpc = local.acl_synth_test-vpc3_id + vpc = local.acl_synth_test-vpc3_id # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule0" - action = "deny" - direction = "inbound" - source = "0.0.0.0/0" + name = "rule0" + action = "deny" + direction = "inbound" + source = "0.0.0.0/0" destination = "10.240.192.0/24" } # Deny all communication; subnet test-vpc3/subnet30[10.240.192.0/24] does not have required connections rules { - name = "rule1" - action = "deny" - direction = "outbound" - source = "10.240.192.0/24" + name = "rule1" + action = "deny" + direction = "outbound" + source = "10.240.192.0/24" destination = "0.0.0.0/0" } } diff --git a/test/expected/sg_protocols_tf/sg_expected.tf b/test/expected/sg_protocols_tf/sg_expected.tf index 1367a53c..f7519b05 100644 --- a/test/expected/sg_protocols_tf/sg_expected.tf +++ b/test/expected/sg_protocols_tf/sg_expected.tf @@ -1,68 +1,68 @@ ### SG attached to test-vpc0/vsi0-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet0" { - name = "sg-test-vpc0--vsi0-subnet0" + name = "sg-test-vpc0--vsi0-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id udp { } } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet1.id icmp { } } ### SG attached to test-vpc0/vsi0-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet1" { - name = "sg-test-vpc0--vsi0-subnet1" + name = "sg-test-vpc0--vsi0-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet1-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id udp { } } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi0-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet1-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id icmp { } } ### SG attached to test-vpc0/vsi0-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet2" { - name = "sg-test-vpc0--vsi0-subnet2" + name = "sg-test-vpc0--vsi0-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet2-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id tcp { } } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet2-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet2.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet3.id icmp { type = 11 code = 1 @@ -71,23 +71,23 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet2-1" { ### SG attached to test-vpc0/vsi0-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet3" { - name = "sg-test-vpc0--vsi0-subnet3" + name = "sg-test-vpc0--vsi0-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet3-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id tcp { } } # Internal. required-connections[2]: (nif test-vpc0/vsi0-subnet2/graveyard-handmade-ransack-acquaint)->(nif test-vpc0/vsi0-subnet3/icky-balsamic-outgoing-leached); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet3-1" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet3.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet2.id icmp { type = 11 code = 1 @@ -96,29 +96,29 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet3-1" { ### SG attached to test-vpc0/vsi0-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet4" { - name = "sg-test-vpc0--vsi0-subnet4" + name = "sg-test-vpc0--vsi0-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet5" { - name = "sg-test-vpc0--vsi0-subnet5" + name = "sg-test-vpc0--vsi0-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet0" { - name = "sg-test-vpc0--vsi1-subnet0" + name = "sg-test-vpc0--vsi1-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-0" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id tcp { port_min = 8080 port_max = 8080 @@ -126,9 +126,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-0" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-1" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id udp { port_min = 53 port_max = 53 @@ -136,9 +136,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-1" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[2] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-2" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet1.id icmp { type = 8 } @@ -146,15 +146,15 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-2" { ### SG attached to test-vpc0/vsi1-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet1" { - name = "sg-test-vpc0--vsi1-subnet1" + name = "sg-test-vpc0--vsi1-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-0" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id tcp { port_min = 8080 port_max = 8080 @@ -162,9 +162,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-0" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[1] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-1" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id udp { port_min = 53 port_max = 53 @@ -172,9 +172,9 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-1" { } # Internal. required-connections[1]: (instance test-vpc0/vsi1-subnet0)->(instance test-vpc0/vsi1-subnet1); allowed-protocols[2] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-2" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet1.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet0.id icmp { type = 8 } @@ -182,84 +182,84 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-2" { ### SG attached to test-vpc0/vsi1-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet2" { - name = "sg-test-vpc0--vsi1-subnet2" + name = "sg-test-vpc0--vsi1-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet3" { - name = "sg-test-vpc0--vsi1-subnet3" + name = "sg-test-vpc0--vsi1-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet4" { - name = "sg-test-vpc0--vsi1-subnet4" + name = "sg-test-vpc0--vsi1-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet5" { - name = "sg-test-vpc0--vsi1-subnet5" + name = "sg-test-vpc0--vsi1-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc1/vsi0-subnet10 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet10" { - name = "sg-test-vpc1--vsi0-subnet10" + name = "sg-test-vpc1--vsi0-subnet10" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } # External. required-connections[3]: (instance test-vpc1/vsi0-subnet10)->(external dns); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet10-0" { - group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id + group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id direction = "outbound" - remote = "8.8.8.8" + remote = "8.8.8.8" tcp { } } ### SG attached to test-vpc1/vsi0-subnet11 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet11" { - name = "sg-test-vpc1--vsi0-subnet11" + name = "sg-test-vpc1--vsi0-subnet11" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } ### SG attached to test-vpc2/vsi0-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi0-subnet20" { - name = "sg-test-vpc2--vsi0-subnet20" + name = "sg-test-vpc2--vsi0-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } ### SG attached to test-vpc2/vsi1-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi1-subnet20" { - name = "sg-test-vpc2--vsi1-subnet20" + name = "sg-test-vpc2--vsi1-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } # External. required-connections[4]: (instance test-vpc2/vsi1-subnet20)->(external public internet); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc2--vsi1-subnet20-0" { - group = ibm_is_security_group.test-vpc2--vsi1-subnet20.id + group = ibm_is_security_group.test-vpc2--vsi1-subnet20.id direction = "outbound" - remote = "0.0.0.0/0" + remote = "0.0.0.0/0" } ### SG attached to test-vpc2/vsi2-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi2-subnet20" { - name = "sg-test-vpc2--vsi2-subnet20" + name = "sg-test-vpc2--vsi2-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } ### SG attached to test-vpc3/vsi0-subnet30 resource "ibm_is_security_group" "test-vpc3--vsi0-subnet30" { - name = "sg-test-vpc3--vsi0-subnet30" + name = "sg-test-vpc3--vsi0-subnet30" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc3_id + vpc = local.sg_synth_test-vpc3_id } diff --git a/test/expected/sg_testing3_tf/sg_expected.tf b/test/expected/sg_testing3_tf/sg_expected.tf index 0da81523..8bfb66a3 100644 --- a/test/expected/sg_testing3_tf/sg_expected.tf +++ b/test/expected/sg_testing3_tf/sg_expected.tf @@ -1,48 +1,48 @@ ### SG attached to test-vpc/appdata-endpoint-gateway resource "ibm_is_security_group" "test-vpc--appdata-endpoint-gateway" { - name = "sg-test-vpc--appdata-endpoint-gateway" + name = "sg-test-vpc--appdata-endpoint-gateway" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } ### SG attached to test-vpc/be resource "ibm_is_security_group" "test-vpc--be" { - name = "sg-test-vpc--be" + name = "sg-test-vpc--be" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[2]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--be-0" { - group = ibm_is_security_group.test-vpc--be.id + group = ibm_is_security_group.test-vpc--be.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--fe.id + remote = ibm_is_security_group.test-vpc--fe.id tcp { } } # Internal. required-connections[3]: (instance test-vpc/be)->(instance test-vpc/opa); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--be-1" { - group = ibm_is_security_group.test-vpc--be.id + group = ibm_is_security_group.test-vpc--be.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--opa.id + remote = ibm_is_security_group.test-vpc--opa.id } # Internal. required-connections[4]: (instance test-vpc/be)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--be-2" { - group = ibm_is_security_group.test-vpc--be.id + group = ibm_is_security_group.test-vpc--be.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id } ### SG attached to test-vpc/fe resource "ibm_is_security_group" "test-vpc--fe" { - name = "sg-test-vpc--fe" + name = "sg-test-vpc--fe" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--fe-0" { - group = ibm_is_security_group.test-vpc--fe.id + group = ibm_is_security_group.test-vpc--fe.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--proxy.id + remote = ibm_is_security_group.test-vpc--proxy.id tcp { port_min = 9000 port_max = 9000 @@ -50,68 +50,68 @@ resource "ibm_is_security_group_rule" "test-vpc--fe-0" { } # Internal. required-connections[2]: (instance test-vpc/fe)->(instance test-vpc/be); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--fe-1" { - group = ibm_is_security_group.test-vpc--fe.id + group = ibm_is_security_group.test-vpc--fe.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--be.id + remote = ibm_is_security_group.test-vpc--be.id tcp { } } ### SG attached to test-vpc/opa resource "ibm_is_security_group" "test-vpc--opa" { - name = "sg-test-vpc--opa" + name = "sg-test-vpc--opa" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[3]: (instance test-vpc/be)->(instance test-vpc/opa); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--opa-0" { - group = ibm_is_security_group.test-vpc--opa.id + group = ibm_is_security_group.test-vpc--opa.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--be.id + remote = ibm_is_security_group.test-vpc--be.id } # Internal. required-connections[5]: (instance test-vpc/opa)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--opa-1" { - group = ibm_is_security_group.test-vpc--opa.id + group = ibm_is_security_group.test-vpc--opa.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id } ### SG attached to test-vpc/policydb-endpoint-gateway resource "ibm_is_security_group" "test-vpc--policydb-endpoint-gateway" { - name = "sg-test-vpc--policydb-endpoint-gateway" + name = "sg-test-vpc--policydb-endpoint-gateway" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # Internal. required-connections[4]: (instance test-vpc/be)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--policydb-endpoint-gateway-0" { - group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--be.id + remote = ibm_is_security_group.test-vpc--be.id } # Internal. required-connections[5]: (instance test-vpc/opa)->(vpe test-vpc/policydb-endpoint-gateway); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--policydb-endpoint-gateway-1" { - group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id + group = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id direction = "inbound" - remote = ibm_is_security_group.test-vpc--opa.id + remote = ibm_is_security_group.test-vpc--opa.id } ### SG attached to test-vpc/proxy resource "ibm_is_security_group" "test-vpc--proxy" { - name = "sg-test-vpc--proxy" + name = "sg-test-vpc--proxy" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc_id + vpc = local.sg_synth_test-vpc_id } # External. required-connections[0]: (external public internet)->(instance test-vpc/proxy); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--proxy-0" { - group = ibm_is_security_group.test-vpc--proxy.id + group = ibm_is_security_group.test-vpc--proxy.id direction = "inbound" - remote = "0.0.0.0/0" + remote = "0.0.0.0/0" } # Internal. required-connections[1]: (instance test-vpc/proxy)->(instance test-vpc/fe); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc--proxy-1" { - group = ibm_is_security_group.test-vpc--proxy.id + group = ibm_is_security_group.test-vpc--proxy.id direction = "outbound" - remote = ibm_is_security_group.test-vpc--fe.id + remote = ibm_is_security_group.test-vpc--fe.id tcp { port_min = 9000 port_max = 9000 diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf index 07de4293..8f4979ba 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf @@ -1,95 +1,95 @@ ### SG attached to test-vpc0/vsi0-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet0" { - name = "sg-test-vpc0--vsi0-subnet0" + name = "sg-test-vpc0--vsi0-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi1-subnet4); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-0" { - group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + group = ibm_is_security_group.test-vpc0--vsi0-subnet0.id direction = "outbound" - remote = ibm_is_security_group.test-vpc0--vsi1-subnet4.id + remote = ibm_is_security_group.test-vpc0--vsi1-subnet4.id } ### SG attached to test-vpc0/vsi0-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet1" { - name = "sg-test-vpc0--vsi0-subnet1" + name = "sg-test-vpc0--vsi0-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet2" { - name = "sg-test-vpc0--vsi0-subnet2" + name = "sg-test-vpc0--vsi0-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet3" { - name = "sg-test-vpc0--vsi0-subnet3" + name = "sg-test-vpc0--vsi0-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet4" { - name = "sg-test-vpc0--vsi0-subnet4" + name = "sg-test-vpc0--vsi0-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi0-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet5" { - name = "sg-test-vpc0--vsi0-subnet5" + name = "sg-test-vpc0--vsi0-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet0" { - name = "sg-test-vpc0--vsi1-subnet0" + name = "sg-test-vpc0--vsi1-subnet0" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet1" { - name = "sg-test-vpc0--vsi1-subnet1" + name = "sg-test-vpc0--vsi1-subnet1" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet2" { - name = "sg-test-vpc0--vsi1-subnet2" + name = "sg-test-vpc0--vsi1-subnet2" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet3" { - name = "sg-test-vpc0--vsi1-subnet3" + name = "sg-test-vpc0--vsi1-subnet3" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } ### SG attached to test-vpc0/vsi1-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet4" { - name = "sg-test-vpc0--vsi1-subnet4" + name = "sg-test-vpc0--vsi1-subnet4" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } # Internal. required-connections[0]: (instance test-vpc0/vsi0-subnet0)->(instance test-vpc0/vsi1-subnet4); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet4-0" { - group = ibm_is_security_group.test-vpc0--vsi1-subnet4.id + group = ibm_is_security_group.test-vpc0--vsi1-subnet4.id direction = "inbound" - remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id + remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id } ### SG attached to test-vpc0/vsi1-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet5" { - name = "sg-test-vpc0--vsi1-subnet5" + name = "sg-test-vpc0--vsi1-subnet5" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc0_id + vpc = local.sg_synth_test-vpc0_id } diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf index a4810cf4..06e11954 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf @@ -1,29 +1,29 @@ ### SG attached to test-vpc1/vsi0-subnet10 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet10" { - name = "sg-test-vpc1--vsi0-subnet10" + name = "sg-test-vpc1--vsi0-subnet10" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } # Internal. required-connections[2]: (instance test-vpc1/vsi0-subnet10)->(instance test-vpc1/vsi0-subnet11); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet10-0" { - group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id + group = ibm_is_security_group.test-vpc1--vsi0-subnet10.id direction = "outbound" - remote = ibm_is_security_group.test-vpc1--vsi0-subnet11.id + remote = ibm_is_security_group.test-vpc1--vsi0-subnet11.id tcp { } } ### SG attached to test-vpc1/vsi0-subnet11 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet11" { - name = "sg-test-vpc1--vsi0-subnet11" + name = "sg-test-vpc1--vsi0-subnet11" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc1_id + vpc = local.sg_synth_test-vpc1_id } # Internal. required-connections[2]: (instance test-vpc1/vsi0-subnet10)->(instance test-vpc1/vsi0-subnet11); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet11-0" { - group = ibm_is_security_group.test-vpc1--vsi0-subnet11.id + group = ibm_is_security_group.test-vpc1--vsi0-subnet11.id direction = "inbound" - remote = ibm_is_security_group.test-vpc1--vsi0-subnet10.id + remote = ibm_is_security_group.test-vpc1--vsi0-subnet10.id tcp { } } diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf index a4e97bbb..bf96f422 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf @@ -1,14 +1,14 @@ ### SG attached to test-vpc2/vsi0-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi0-subnet20" { - name = "sg-test-vpc2--vsi0-subnet20" + name = "sg-test-vpc2--vsi0-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } # Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc2--vsi0-subnet20-0" { - group = ibm_is_security_group.test-vpc2--vsi0-subnet20.id + group = ibm_is_security_group.test-vpc2--vsi0-subnet20.id direction = "outbound" - remote = ibm_is_security_group.test-vpc2--vsi2-subnet20.id + remote = ibm_is_security_group.test-vpc2--vsi2-subnet20.id tcp { port_min = 53 port_max = 53 @@ -17,22 +17,22 @@ resource "ibm_is_security_group_rule" "test-vpc2--vsi0-subnet20-0" { ### SG attached to test-vpc2/vsi1-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi1-subnet20" { - name = "sg-test-vpc2--vsi1-subnet20" + name = "sg-test-vpc2--vsi1-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } ### SG attached to test-vpc2/vsi2-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi2-subnet20" { - name = "sg-test-vpc2--vsi2-subnet20" + name = "sg-test-vpc2--vsi2-subnet20" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc2_id + vpc = local.sg_synth_test-vpc2_id } # Internal. required-connections[1]: (instance test-vpc2/vsi0-subnet20)->(instance test-vpc2/vsi2-subnet20); allowed-protocols[0] resource "ibm_is_security_group_rule" "test-vpc2--vsi2-subnet20-0" { - group = ibm_is_security_group.test-vpc2--vsi2-subnet20.id + group = ibm_is_security_group.test-vpc2--vsi2-subnet20.id direction = "inbound" - remote = ibm_is_security_group.test-vpc2--vsi0-subnet20.id + remote = ibm_is_security_group.test-vpc2--vsi0-subnet20.id tcp { port_min = 53 port_max = 53 diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf index b01452c6..ef77175b 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf @@ -1,6 +1,6 @@ ### SG attached to test-vpc3/vsi0-subnet30 resource "ibm_is_security_group" "test-vpc3--vsi0-subnet30" { - name = "sg-test-vpc3--vsi0-subnet30" + name = "sg-test-vpc3--vsi0-subnet30" resource_group = local.sg_synth_resource_group_id - vpc = local.sg_synth_test-vpc3_id + vpc = local.sg_synth_test-vpc3_id } From 28c3a3b8aaafd4a11f5f7bafce4419e4ec8b6079 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 13:56:54 +0300 Subject: [PATCH 65/79] remove utils func --- pkg/utils/utils.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index e3923aa5..ede1bb67 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -9,8 +9,6 @@ import ( "cmp" "maps" "slices" - - "github.com/np-guard/models/pkg/ds" ) func Ptr[T any](t T) *T { @@ -49,11 +47,3 @@ func Int64PointerToIntPointer(v *int64) *int { } return Ptr(int(*v)) } - -// m1 does not have any key of m2 -func MergeSetMaps[T comparable, K ds.Set[K]](m1, m2 map[T]K) map[T]K { - for key, val := range m2 { - m1[key] = val.Copy() - } - return m1 -} From 9cd866330945f7c8107561652de9907a1339b097 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 13:57:46 +0300 Subject: [PATCH 66/79] models v0.5.1 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 78ec72e8..25753169 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 require ( github.com/IBM/vpc-go-sdk v0.60.0 github.com/np-guard/cloud-resource-collector v0.15.0 - github.com/np-guard/models v0.5.1-0.20241008132809-1e27bae86fe4 + github.com/np-guard/models v0.5.1 github.com/spf13/cobra v1.8.1 ) diff --git a/go.sum b/go.sum index a83a5162..afa0f647 100644 --- a/go.sum +++ b/go.sum @@ -134,8 +134,8 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/np-guard/cloud-resource-collector v0.15.0 h1:jkmxql6D1uBr/qmSOsBzUgeDxlUXSCe7dBKfqfK+QZ4= github.com/np-guard/cloud-resource-collector v0.15.0/go.mod h1:klCHnNnuuVcCtGQHA7R1a8fqnvfMCk/5Jdld6V7sN2A= -github.com/np-guard/models v0.5.1-0.20241008132809-1e27bae86fe4 h1:wsf8U4t74ouuhLqdvxrf247pcjCPlrDhEggpUeskiHo= -github.com/np-guard/models v0.5.1-0.20241008132809-1e27bae86fe4/go.mod h1:29M8utxinyUpYaDuIuOyCcMBf7EsMWZcIrRWCjFm0Bw= +github.com/np-guard/models v0.5.1 h1:qxewCB3cBLkBdcpMk05gKJkV1D7qkbteQdIXbN1juW0= +github.com/np-guard/models v0.5.1/go.mod h1:29M8utxinyUpYaDuIuOyCcMBf7EsMWZcIrRWCjFm0Bw= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= From da1c7d2b9ca92f040108090d86516e09bbb0c928 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 14:14:59 +0300 Subject: [PATCH 67/79] fixed --- pkg/optimize/sg/ipCubesToRules.go | 8 ++ pkg/optimize/sg/rulesToCubes.go | 2 +- .../sg_expected.csv | 7 +- .../sg_expected.md | 7 +- .../sg_expected.tf | 33 ++--- .../optimize_sg_redundant/sg_expected.tf | 20 +++ test/expected/optimize_sg_t/sg_expected.tf | 6 +- .../expected/optimize_sg_t_all/sg_expected.tf | 7 +- test/main_test.go | 136 +++++++++--------- test/update_test.go | 40 +++--- 10 files changed, 149 insertions(+), 117 deletions(-) diff --git a/pkg/optimize/sg/ipCubesToRules.go b/pkg/optimize/sg/ipCubesToRules.go index d61f4f81..a02da0f0 100644 --- a/pkg/optimize/sg/ipCubesToRules.go +++ b/pkg/optimize/sg/ipCubesToRules.go @@ -28,6 +28,10 @@ func allProtocolIPCubesIPToRules(cubes *netset.IPBlock, direction ir.Direction) // tcpudpIPCubesToRules converts cubes representing tcp or udp protocol rules to SG rules func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.PortSet], allCubes *netset.IPBlock, direction ir.Direction, isTCP bool) []*ir.SGRule { + if len(cubes) == 0 { + return []*ir.SGRule{} + } + activeRules := make(map[*netset.IPBlock]netp.Protocol) // the key is the first IP result := make([]*ir.SGRule, 0) @@ -65,6 +69,10 @@ func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.PortSet], all // icmpIPCubesToRules converts cubes representing icmp protocol rules to SG rules func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { + if len(cubes) == 0 { + return []*ir.SGRule{} + } + activeRules := make(map[*netset.IPBlock]netp.Protocol) // the key is the first IP result := make([]*ir.SGRule, 0) diff --git a/pkg/optimize/sg/rulesToCubes.go b/pkg/optimize/sg/rulesToCubes.go index 589aad7e..c8d14fcb 100644 --- a/pkg/optimize/sg/rulesToCubes.go +++ b/pkg/optimize/sg/rulesToCubes.go @@ -77,7 +77,7 @@ func rulesToIPCubes(rules *rulesPerProtocol) *ipCubesPerProtocol { func allProtocolRulesToIPCubes(rules []*ir.SGRule) *netset.IPBlock { res := netset.NewIPBlock() for i := range rules { - res.Union(rules[i].Remote.(*netset.IPBlock)) + res = res.Union(rules[i].Remote.(*netset.IPBlock)) } return res } diff --git a/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv b/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv index 773f874b..ffecbe70 100644 --- a/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv +++ b/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv @@ -1,7 +1,8 @@ SG,Direction,Remote type,Remote,Protocol,Protocol params,Description +sg1,Inbound,CIDR block,Any IP,ALL,, +sg1,Outbound,CIDR block,Any IP,ALL,, test-vpc1--vsi1,Outbound,Security group,test-vpc1--vsi2,ALL,, -test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,TCP,ports 1-1, -test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,UDP,ports 1-1, -test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,ICMP,"Type: Any, Code: Any", +test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,ALL,, test-vpc1--vsi2,Inbound,Security group,test-vpc1--vsi1,ALL,, wombat-hesitate-scorn-subprime,Inbound,Security group,wombat-hesitate-scorn-subprime,ALL,, +wombat-hesitate-scorn-subprime,Outbound,CIDR block,Any IP,ALL,, diff --git a/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md b/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md index 4fdc42e0..502f442e 100644 --- a/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md +++ b/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md @@ -1,8 +1,9 @@ | SG | Direction | Remote type | Remote | Protocol | Protocol params | Description | | :--- | :--- | :--- | :--- | :--- | :--- | :--- | + | sg1 | Inbound | CIDR block | Any IP | ALL | | | + | sg1 | Outbound | CIDR block | Any IP | ALL | | | | test-vpc1--vsi1 | Outbound | Security group | test-vpc1--vsi2 | ALL | | | - | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | TCP | ports 1-1 | | - | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | UDP | ports 1-1 | | - | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | ICMP | Type: Any, Code: Any | | + | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | ALL | | | | test-vpc1--vsi2 | Inbound | Security group | test-vpc1--vsi1 | ALL | | | | wombat-hesitate-scorn-subprime | Inbound | Security group | wombat-hesitate-scorn-subprime | ALL | | | + | wombat-hesitate-scorn-subprime | Outbound | CIDR block | Any IP | ALL | | | diff --git a/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf index d8324ff5..7f196edc 100644 --- a/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf +++ b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf @@ -3,6 +3,16 @@ resource "ibm_is_security_group" "sg1" { resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } +resource "ibm_is_security_group_rule" "sg1-0" { + group = ibm_is_security_group.sg1.id + direction = "inbound" + remote = "0.0.0.0/0" +} +resource "ibm_is_security_group_rule" "sg1-1" { + group = ibm_is_security_group.sg1.id + direction = "outbound" + remote = "0.0.0.0/0" +} resource "ibm_is_security_group" "test-vpc1--vsi1" { @@ -19,24 +29,6 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { group = ibm_is_security_group.test-vpc1--vsi1.id direction = "outbound" remote = "0.0.0.0/31" - tcp { - port_max = 1 - } -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi1-2" { - group = ibm_is_security_group.test-vpc1--vsi1.id - direction = "outbound" - remote = "0.0.0.0/31" - udp { - port_max = 1 - } -} -resource "ibm_is_security_group_rule" "test-vpc1--vsi1-3" { - group = ibm_is_security_group.test-vpc1--vsi1.id - direction = "outbound" - remote = "0.0.0.0/31" - icmp { - } } @@ -76,3 +68,8 @@ resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { direction = "inbound" remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id } +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-1" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "outbound" + remote = "0.0.0.0/0" +} diff --git a/test/expected/optimize_sg_redundant/sg_expected.tf b/test/expected/optimize_sg_redundant/sg_expected.tf index 15bd1e64..88239143 100644 --- a/test/expected/optimize_sg_redundant/sg_expected.tf +++ b/test/expected/optimize_sg_redundant/sg_expected.tf @@ -3,6 +3,16 @@ resource "ibm_is_security_group" "sg1" { resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } +resource "ibm_is_security_group_rule" "sg1-0" { + group = ibm_is_security_group.sg1.id + direction = "inbound" + remote = "0.0.0.0/0" +} +resource "ibm_is_security_group_rule" "sg1-1" { + group = ibm_is_security_group.sg1.id + direction = "outbound" + remote = "0.0.0.0/0" +} resource "ibm_is_security_group" "test-vpc1--vsi1" { @@ -15,6 +25,11 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { direction = "outbound" remote = ibm_is_security_group.test-vpc1--vsi2.id } +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/30" +} resource "ibm_is_security_group" "test-vpc1--vsi2" { @@ -53,3 +68,8 @@ resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-0" { direction = "inbound" remote = ibm_is_security_group.wombat-hesitate-scorn-subprime.id } +resource "ibm_is_security_group_rule" "wombat-hesitate-scorn-subprime-1" { + group = ibm_is_security_group.wombat-hesitate-scorn-subprime.id + direction = "outbound" + remote = "0.0.0.0/0" +} diff --git a/test/expected/optimize_sg_t/sg_expected.tf b/test/expected/optimize_sg_t/sg_expected.tf index 32fd2e3b..448d25d8 100644 --- a/test/expected/optimize_sg_t/sg_expected.tf +++ b/test/expected/optimize_sg_t/sg_expected.tf @@ -23,9 +23,9 @@ resource "ibm_is_security_group" "test-vpc1--vsi1" { resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { group = ibm_is_security_group.test-vpc1--vsi1.id direction = "outbound" - remote = "0.0.0.0/30" + remote = "0.0.0.0/29" tcp { - port_max = 1 + port_max = 10 } } resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { @@ -33,7 +33,7 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { direction = "outbound" remote = "0.0.0.2/31" tcp { - port_max = 1 + port_max = 20 } } diff --git a/test/expected/optimize_sg_t_all/sg_expected.tf b/test/expected/optimize_sg_t_all/sg_expected.tf index f932cb58..0f4d41e0 100644 --- a/test/expected/optimize_sg_t_all/sg_expected.tf +++ b/test/expected/optimize_sg_t_all/sg_expected.tf @@ -25,9 +25,14 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { direction = "outbound" remote = "0.0.0.0/29" tcp { - port_max = 1 + port_max = 10 } } +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.2/31" +} resource "ibm_is_security_group" "test-vpc1--vsi2" { diff --git a/test/main_test.go b/test/main_test.go index 998995de..aabe832d 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -5,84 +5,84 @@ SPDX-License-Identifier: Apache-2.0 package test -// import ( -// "os" -// "path/filepath" -// "regexp" -// "strings" -// "testing" +import ( + "os" + "path/filepath" + "regexp" + "strings" + "testing" -// "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" -// ) + "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" +) -// func TestMain(t *testing.T) { -// for _, tt := range allMainTests() { -// t.Run(tt.testName, func(t *testing.T) { -// // create a sub folder -// if err := os.MkdirAll(filepath.Join(resultsFolder, tt.testName), defaultDirectoryPermission); err != nil { -// t.Fatalf("Bad test %s; error creating folder for results: %v", tt.testName, err) -// } +func TestMain(t *testing.T) { + for _, tt := range allMainTests() { + t.Run(tt.testName, func(t *testing.T) { + // create a sub folder + if err := os.MkdirAll(filepath.Join(resultsFolder, tt.testName), defaultDirectoryPermission); err != nil { + t.Fatalf("Bad test %s; error creating folder for results: %v", tt.testName, err) + } -// // run command -// if err := subcmds.Main(tt.args.Args(dataFolder, resultsFolder)); err != nil { -// t.Fatalf("Bad test %s; unexpected err: %v", tt.testName, err) -// } + // run command + if err := subcmds.Main(tt.args.Args(dataFolder, resultsFolder)); err != nil { + t.Fatalf("Bad test %s; unexpected err: %v", tt.testName, err) + } -// // compare results -// compareTestResults(t, tt.testName) -// }) -// } -// removeGeneratedFiles() -// } + // compare results + compareTestResults(t, tt.testName) + }) + } + removeGeneratedFiles() +} -// func compareTestResults(t *testing.T, testName string) { -// expectedSubDirPath := filepath.Join(expectedFolder, testName) -// expectedDirFiles := readDir(t, expectedSubDirPath) -// expectedFileNames := strings.Join(expectedDirFiles, ", ") +func compareTestResults(t *testing.T, testName string) { + expectedSubDirPath := filepath.Join(expectedFolder, testName) + expectedDirFiles := readDir(t, expectedSubDirPath) + expectedFileNames := strings.Join(expectedDirFiles, ", ") -// resultsSubDirPath := filepath.Join(resultsFolder, testName) -// resultsDirFiles := readDir(t, resultsSubDirPath) -// resultsFileNames := strings.Join(resultsDirFiles, ", ") + resultsSubDirPath := filepath.Join(resultsFolder, testName) + resultsDirFiles := readDir(t, resultsSubDirPath) + resultsFileNames := strings.Join(resultsDirFiles, ", ") -// if len(expectedDirFiles) != len(resultsDirFiles) { -// t.Fatalf("Bad test: %s; incorrect number of files created.\nexpected: %s\ngot: %s", testName, expectedFileNames, resultsFileNames) -// } + if len(expectedDirFiles) != len(resultsDirFiles) { + t.Fatalf("Bad test: %s; incorrect number of files created.\nexpected: %s\ngot: %s", testName, expectedFileNames, resultsFileNames) + } -// for _, file := range expectedDirFiles { -// if readFile(t, filepath.Join(expectedSubDirPath, file), testName) != readFile(t, filepath.Join(resultsSubDirPath, file), testName) { -// t.Fatalf("Bad test %s; The %s file is different than expected", testName, file) -// } -// } -// } + for _, file := range expectedDirFiles { + if readFile(t, filepath.Join(expectedSubDirPath, file), testName) != readFile(t, filepath.Join(resultsSubDirPath, file), testName) { + t.Fatalf("Bad test %s; The %s file is different than expected", testName, file) + } + } +} -// func readDir(t *testing.T, dirName string) []string { -// entries, err := os.ReadDir(dirName) -// if err != nil { -// t.Fatalf("Bad test %s; error reading folder: %s", dirName, err) -// } +func readDir(t *testing.T, dirName string) []string { + entries, err := os.ReadDir(dirName) + if err != nil { + t.Fatalf("Bad test %s; error reading folder: %s", dirName, err) + } -// result := make([]string, len(entries)) -// for i := range entries { -// result[i] = entries[i].Name() -// } -// return result -// } + result := make([]string, len(entries)) + for i := range entries { + result[i] = entries[i].Name() + } + return result +} -// func readFile(t *testing.T, file, testName string) string { -// buf, err := os.ReadFile(file) -// if err != nil { -// t.Fatalf("Bad test: %s; error reading file %s: %v", testName, file, err) -// } -// return shrinkWhitespace(string(buf)) -// } +func readFile(t *testing.T, file, testName string) string { + buf, err := os.ReadFile(file) + if err != nil { + t.Fatalf("Bad test: %s; error reading file %s: %v", testName, file, err) + } + return shrinkWhitespace(string(buf)) +} -// func shrinkWhitespace(s string) string { -// return regexp.MustCompile(`[ \t]+`).ReplaceAllString(s, " ") -// } +func shrinkWhitespace(s string) string { + return regexp.MustCompile(`[ \t]+`).ReplaceAllString(s, " ") +} -// func removeGeneratedFiles() { -// err := os.RemoveAll(resultsFolder) -// if err != nil { -// panic(err) -// } -// } +func removeGeneratedFiles() { + err := os.RemoveAll(resultsFolder) + if err != nil { + panic(err) + } +} diff --git a/test/update_test.go b/test/update_test.go index 7687fabe..209921cf 100644 --- a/test/update_test.go +++ b/test/update_test.go @@ -5,26 +5,26 @@ SPDX-License-Identifier: Apache-2.0 package test -import ( - "os" - "path/filepath" - "testing" +// import ( +// "os" +// "path/filepath" +// "testing" - "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" -) +// "github.com/np-guard/vpc-network-config-synthesis/cmd/subcmds" +// ) -func TestUpdate(t *testing.T) { - for _, tt := range allMainTests() { - t.Run(tt.testName, func(t *testing.T) { - // create a sub folder - if err := os.MkdirAll(filepath.Join(expectedFolder, tt.testName), defaultDirectoryPermission); err != nil { - t.Errorf("Bad test %s: %s", tt.testName, err) - } +// func TestUpdate(t *testing.T) { +// for _, tt := range allMainTests() { +// t.Run(tt.testName, func(t *testing.T) { +// // create a sub folder +// if err := os.MkdirAll(filepath.Join(expectedFolder, tt.testName), defaultDirectoryPermission); err != nil { +// t.Errorf("Bad test %s: %s", tt.testName, err) +// } - err := subcmds.Main(tt.args.Args(dataFolder, expectedFolder)) - if err != nil { - t.Errorf("Bad test %s: %s", tt.testName, err) - } - }) - } -} +// err := subcmds.Main(tt.args.Args(dataFolder, expectedFolder)) +// if err != nil { +// t.Errorf("Bad test %s: %s", tt.testName, err) +// } +// }) +// } +// } From 4f549452df2760eab05023848e219e38fa1a51e8 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Wed, 9 Oct 2024 14:47:09 +0300 Subject: [PATCH 68/79] another test, fixed icmp bug --- pkg/optimize/sg/ipCubesToRules.go | 2 +- test/data/optimize_sg_protocols_to_all/config_object.json | 8 +++++++- test/data/optimize_sg_protocols_to_all/conn_spec.json | 5 +++-- test/data/optimize_sg_protocols_to_all/details.txt | 3 ++- .../optimize_sg_protocols_to_all_csv/sg_expected.csv | 1 + .../optimize_sg_protocols_to_all_md/sg_expected.md | 1 + .../optimize_sg_protocols_to_all_tf/sg_expected.tf | 7 +++++++ 7 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pkg/optimize/sg/ipCubesToRules.go b/pkg/optimize/sg/ipCubesToRules.go index a02da0f0..f7b41bcf 100644 --- a/pkg/optimize/sg/ipCubesToRules.go +++ b/pkg/optimize/sg/ipCubesToRules.go @@ -100,7 +100,7 @@ func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCu // if the cube contains icmp values that are not contained in the active rules, new rules will be created for _, p := range optimize.IcmpsetPartitions(cubes[i].Right) { if !optimize.IcmpRuleToIcmpSet(p).IsSubset(activeICMP) { - activeRules[cubes[i].Left.FirstIPAddressObject()] = &p + activeRules[cubes[i].Left.FirstIPAddressObject()] = p } } } diff --git a/test/data/optimize_sg_protocols_to_all/config_object.json b/test/data/optimize_sg_protocols_to_all/config_object.json index 23a99429..e4d7662a 100644 --- a/test/data/optimize_sg_protocols_to_all/config_object.json +++ b/test/data/optimize_sg_protocols_to_all/config_object.json @@ -42,6 +42,7 @@ "name": "capitol-siren-chirpy-doornail" }, "default_routing_table": { + "crn": null, "href": "href:11", "id": "id:12", "name": "fiscally-fresh-uncanny-ceramics", @@ -156,6 +157,7 @@ }, "resource_type": "subnet", "routing_table": { + "crn": null, "href": "href:11", "id": "id:12", "name": "fiscally-fresh-uncanny-ceramics", @@ -279,6 +281,7 @@ }, "resource_type": "subnet", "routing_table": { + "crn": null, "href": "href:11", "id": "id:12", "name": "fiscally-fresh-uncanny-ceramics", @@ -395,6 +398,7 @@ }, "resource_type": "subnet", "routing_table": { + "crn": null, "href": "href:11", "id": "id:12", "name": "fiscally-fresh-uncanny-ceramics", @@ -1279,7 +1283,7 @@ "cidr_block": "0.0.0.0/0" }, "remote": { - "cidr_block": "0.0.0.0/31" + "cidr_block": "0.0.0.0/30" }, "protocol": "icmp" }, @@ -2164,11 +2168,13 @@ ], "advertise_routes_to": [], "created_at": "2024-09-09T09:09:51.000Z", + "crn": null, "href": "href:11", "id": "id:12", "is_default": true, "lifecycle_state": "stable", "name": "fiscally-fresh-uncanny-ceramics", + "resource_group": null, "resource_type": "routing_table", "route_direct_link_ingress": false, "route_internet_ingress": false, diff --git a/test/data/optimize_sg_protocols_to_all/conn_spec.json b/test/data/optimize_sg_protocols_to_all/conn_spec.json index 32a127fb..4b184550 100644 --- a/test/data/optimize_sg_protocols_to_all/conn_spec.json +++ b/test/data/optimize_sg_protocols_to_all/conn_spec.json @@ -1,6 +1,7 @@ { "externals": { - "e1": "0.0.0.0/31" + "e1": "0.0.0.0/31", + "e2": "0.0.0.0/30" }, "required-connections": [ { @@ -9,7 +10,7 @@ "type": "instance" }, "dst": { - "name": "e1", + "name": "e2", "type": "external" }, "allowed-protocols": [ diff --git a/test/data/optimize_sg_protocols_to_all/details.txt b/test/data/optimize_sg_protocols_to_all/details.txt index ca29dc0f..09b14960 100644 --- a/test/data/optimize_sg_protocols_to_all/details.txt +++ b/test/data/optimize_sg_protocols_to_all/details.txt @@ -1,4 +1,4 @@ -vsi1 --> 0.0.0.0/31 (icmp) +vsi1 --> 0.0.0.0/30 (icmp) vsi1 --> 0.0.0.0/31 (tcp) vsi1 --> 0.0.0.0/31 (udp ports 1-100) vsi1 --> 0.0.0.0/31 (udp ports 50-150) @@ -13,4 +13,5 @@ vsi1 --> vsi2 (udp ports 151-65535) ==================================== vsi1 --> 0.0.0.0/31 (all protocol) +vsi1 --> 0.0.0.0/30 (icmp) vsi1 --> vsi2 (all protocol) \ No newline at end of file diff --git a/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv b/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv index ffecbe70..2e4c7efb 100644 --- a/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv +++ b/test/expected/optimize_sg_protocols_to_all_csv/sg_expected.csv @@ -2,6 +2,7 @@ SG,Direction,Remote type,Remote,Protocol,Protocol params,Description sg1,Inbound,CIDR block,Any IP,ALL,, sg1,Outbound,CIDR block,Any IP,ALL,, test-vpc1--vsi1,Outbound,Security group,test-vpc1--vsi2,ALL,, +test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/30,ICMP,"Type: Any, Code: Any", test-vpc1--vsi1,Outbound,CIDR block,0.0.0.0/31,ALL,, test-vpc1--vsi2,Inbound,Security group,test-vpc1--vsi1,ALL,, wombat-hesitate-scorn-subprime,Inbound,Security group,wombat-hesitate-scorn-subprime,ALL,, diff --git a/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md b/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md index 502f442e..52e2f303 100644 --- a/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md +++ b/test/expected/optimize_sg_protocols_to_all_md/sg_expected.md @@ -3,6 +3,7 @@ | sg1 | Inbound | CIDR block | Any IP | ALL | | | | sg1 | Outbound | CIDR block | Any IP | ALL | | | | test-vpc1--vsi1 | Outbound | Security group | test-vpc1--vsi2 | ALL | | | + | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/30 | ICMP | Type: Any, Code: Any | | | test-vpc1--vsi1 | Outbound | CIDR block | 0.0.0.0/31 | ALL | | | | test-vpc1--vsi2 | Inbound | Security group | test-vpc1--vsi1 | ALL | | | | wombat-hesitate-scorn-subprime | Inbound | Security group | wombat-hesitate-scorn-subprime | ALL | | | diff --git a/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf index 7f196edc..10f44116 100644 --- a/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf +++ b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf @@ -26,6 +26,13 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-0" { remote = ibm_is_security_group.test-vpc1--vsi2.id } resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { + group = ibm_is_security_group.test-vpc1--vsi1.id + direction = "outbound" + remote = "0.0.0.0/30" + icmp { + } +} +resource "ibm_is_security_group_rule" "test-vpc1--vsi1-2" { group = ibm_is_security_group.test-vpc1--vsi1.id direction = "outbound" remote = "0.0.0.0/31" From fe6f4e3cad9ecc08cae173880ea6ecded0c6bba9 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 20 Oct 2024 10:09:16 +0300 Subject: [PATCH 69/79] small fixes --- pkg/optimize/sg/reduceCubes.go | 31 +++++++++++++------------------ pkg/optimize/sg/rulesToCubes.go | 20 ++++++++++---------- pkg/optimize/sg/sg.go | 4 ++-- 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/pkg/optimize/sg/reduceCubes.go b/pkg/optimize/sg/reduceCubes.go index b597b894..44d9a9d7 100644 --- a/pkg/optimize/sg/reduceCubes.go +++ b/pkg/optimize/sg/reduceCubes.go @@ -13,23 +13,22 @@ import ( "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" ) -func reduceSGCubes(spans *sgCubesPerProtocol) *sgCubesPerProtocol { - spans = deleteOtherProtocolIfAllProtocolExists(spans) - return compressThreeProtocolsToAllProtocol(spans) +func reduceSGCubes(spans *sgCubesPerProtocol) { + deleteOtherProtocolIfAllProtocolExists(spans) + compressThreeProtocolsToAllProtocol(spans) } // delete other protocols rules if all protocol rule exists -func deleteOtherProtocolIfAllProtocolExists(spans *sgCubesPerProtocol) *sgCubesPerProtocol { +func deleteOtherProtocolIfAllProtocolExists(spans *sgCubesPerProtocol) { for _, sgName := range spans.all { delete(spans.tcp, sgName) delete(spans.udp, sgName) delete(spans.icmp, sgName) } - return spans } // merge tcp, udp and icmp rules into all protocol rule -func compressThreeProtocolsToAllProtocol(spans *sgCubesPerProtocol) *sgCubesPerProtocol { +func compressThreeProtocolsToAllProtocol(spans *sgCubesPerProtocol) { for sgName, tcpPorts := range spans.tcp { if udpPorts, ok := spans.udp[sgName]; ok { if ic, ok := spans.icmp[sgName]; ok { @@ -42,19 +41,17 @@ func compressThreeProtocolsToAllProtocol(spans *sgCubesPerProtocol) *sgCubesPerP } } } - return spans } // observation: It pays to switch to all protocol rule when we have rules that cover all other protocols // on exactly the same cidr (only one protocol can exceed). // //nolint:gocyclo // multiple if statments -func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { +func reduceIPCubes(cubes *ipCubesPerProtocol) { tcpPtr := 0 udpPtr := 0 icmpPtr := 0 - var changed bool for tcpPtr < len(cubes.tcp) && udpPtr < len(cubes.udp) && icmpPtr < len(cubes.icmp) { if !cubes.tcp[tcpPtr].Right.Equal(netset.AllPorts()) { tcpPtr++ @@ -69,8 +66,7 @@ func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { continue } - cubes, changed = compressToAllCube(cubes, tcpPtr, udpPtr, icmpPtr) - if changed { + if compressedToAllCube(cubes, tcpPtr, udpPtr, icmpPtr) { continue } @@ -79,7 +75,7 @@ func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { icmpIP := cubes.icmp[icmpPtr].Left switch { - // one protocol ipb contains two other ipbs. advance the smaller ipb + // one protocol ipb contains two other ipbs ==> advance the smaller ipb case udpIP.IsSubset(tcpIP) && icmpIP.IsSubset(tcpIP) && optimize.LessIPBlock(udpIP, icmpIP): udpPtr++ case udpIP.IsSubset(tcpIP) && icmpIP.IsSubset(tcpIP) && optimize.LessIPBlock(icmpIP, udpIP): @@ -102,11 +98,10 @@ func reduceIPCubes(cubes *ipCubesPerProtocol) *ipCubesPerProtocol { icmpPtr++ } } - return cubes } // compress three protocol rules to all protocol rule (and maybe another protocol rule) -func compressToAllCube(cubes *ipCubesPerProtocol, tcpPtr, udpPtr, icmpPtr int) (*ipCubesPerProtocol, bool) { +func compressedToAllCube(cubes *ipCubesPerProtocol, tcpPtr, udpPtr, icmpPtr int) bool { tcpIP := cubes.tcp[tcpPtr].Left udpIP := cubes.udp[udpPtr].Left icmpIP := cubes.icmp[icmpPtr].Left @@ -119,17 +114,17 @@ func compressToAllCube(cubes *ipCubesPerProtocol, tcpPtr, udpPtr, icmpPtr int) ( cubes.udp = slices.Delete(cubes.udp, udpPtr, udpPtr+1) cubes.icmp = slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) cubes.all = cubes.all.Union(udpIP) - return cubes, true + return true case tcpIP.IsSubset(udpIP) && tcpIP.Equal(icmpIP): cubes.tcp = slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) cubes.icmp = slices.Delete(cubes.icmp, icmpPtr, icmpPtr+1) cubes.all = cubes.all.Union(tcpIP) - return cubes, true + return true case tcpIP.IsSubset(icmpIP) && tcpIP.Equal(udpIP): cubes.tcp = slices.Delete(cubes.tcp, tcpPtr, tcpPtr+1) cubes.udp = slices.Delete(cubes.udp, udpPtr, udpPtr+1) cubes.all = cubes.all.Union(tcpIP) - return cubes, true + return true } - return cubes, false + return false } diff --git a/pkg/optimize/sg/rulesToCubes.go b/pkg/optimize/sg/rulesToCubes.go index c8d14fcb..f3802ef1 100644 --- a/pkg/optimize/sg/rulesToCubes.go +++ b/pkg/optimize/sg/rulesToCubes.go @@ -18,11 +18,11 @@ import ( // SG remote func rulesToSGCubes(rules *rulesPerProtocol) *sgCubesPerProtocol { - tcpSpan := tcpudpRulesSGCubes(rules.tcp) - udpSpan := tcpudpRulesSGCubes(rules.udp) - icmpSpan := icmpRulesSGCubes(rules.icmp) - allSpan := allProtocolRulesToSGCubes(rules.all) - return &sgCubesPerProtocol{tcp: tcpSpan, udp: udpSpan, icmp: icmpSpan, all: allSpan} + return &sgCubesPerProtocol{tcp: tcpudpRulesSGCubes(rules.tcp), + udp: tcpudpRulesSGCubes(rules.udp), + icmp: icmpRulesSGCubes(rules.icmp), + all: allProtocolRulesToSGCubes(rules.all), + } } // all protocol rules to cubes @@ -66,11 +66,11 @@ func icmpRulesSGCubes(rules []*ir.SGRule) map[ir.SGName]*netset.ICMPSet { // IP remote func rulesToIPCubes(rules *rulesPerProtocol) *ipCubesPerProtocol { - tcpCubes := tcpudpRulesToIPCubes(rules.tcp) - udpCubes := tcpudpRulesToIPCubes(rules.udp) - icmpCubes := icmpRulesToIPCubes(rules.icmp) - allCubes := allProtocolRulesToIPCubes(rules.all) - return &ipCubesPerProtocol{tcp: tcpCubes, udp: udpCubes, icmp: icmpCubes, all: allCubes} + return &ipCubesPerProtocol{tcp: tcpudpRulesToIPCubes(rules.tcp), + udp: tcpudpRulesToIPCubes(rules.udp), + icmp: icmpRulesToIPCubes(rules.icmp), + all: allProtocolRulesToIPCubes(rules.all), + } } // all protocol rules to cubes diff --git a/pkg/optimize/sg/sg.go b/pkg/optimize/sg/sg.go index 2427c265..0da688a2 100644 --- a/pkg/optimize/sg/sg.go +++ b/pkg/optimize/sg/sg.go @@ -137,7 +137,7 @@ func (s *sgOptimizer) reduceRules(rules []*ir.SGRule, direction ir.Direction) [] } func reduceRulesSGRemote(cubes *sgCubesPerProtocol, direction ir.Direction) []*ir.SGRule { - cubes = reduceSGCubes(cubes) + reduceSGCubes(cubes) // cubes to SG rules tcpRules := tcpudpSGCubesToRules(cubes.tcp, direction, true) @@ -150,7 +150,7 @@ func reduceRulesSGRemote(cubes *sgCubesPerProtocol, direction ir.Direction) []*i } func reduceRulesIPRemote(cubes *ipCubesPerProtocol, direction ir.Direction) []*ir.SGRule { - cubes = reduceIPCubes(cubes) + reduceIPCubes(cubes) // cubes to SG rules tcpRules := tcpudpIPCubesToRules(cubes.tcp, cubes.all, direction, true) From 2f08925b395c785b2088f25ffcc86b8249436ee0 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 20 Oct 2024 13:06:34 +0300 Subject: [PATCH 70/79] fixed --- cmd/subcmds/output.go | 7 +- pkg/io/{csvio => }/common.go | 48 ++++----- pkg/io/{csvio/acl.go => commonACL.go} | 70 +++++-------- pkg/io/{csvio/sg.go => commonSG.go} | 57 ++++------ pkg/io/csvWriter.go | 38 +++++++ pkg/io/mdWriter.go | 71 +++++++++++++ pkg/io/mdio/acl.go | 138 ------------------------ pkg/io/mdio/common.go | 82 --------------- pkg/io/mdio/sg.go | 144 -------------------------- 9 files changed, 182 insertions(+), 473 deletions(-) rename pkg/io/{csvio => }/common.go (77%) rename pkg/io/{csvio/acl.go => commonACL.go} (68%) rename pkg/io/{csvio/sg.go => commonSG.go} (80%) create mode 100644 pkg/io/csvWriter.go create mode 100644 pkg/io/mdWriter.go delete mode 100644 pkg/io/mdio/acl.go delete mode 100644 pkg/io/mdio/common.go delete mode 100644 pkg/io/mdio/sg.go diff --git a/cmd/subcmds/output.go b/cmd/subcmds/output.go index b3f71013..66bf752a 100644 --- a/cmd/subcmds/output.go +++ b/cmd/subcmds/output.go @@ -12,9 +12,8 @@ import ( "os" "path/filepath" + "github.com/np-guard/vpc-network-config-synthesis/pkg/io" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/confio" - "github.com/np-guard/vpc-network-config-synthesis/pkg/io/csvio" - "github.com/np-guard/vpc-network-config-synthesis/pkg/io/mdio" "github.com/np-guard/vpc-network-config-synthesis/pkg/io/tfio" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -77,9 +76,9 @@ func pickWriter(args *inArgs, data *bytes.Buffer, isSynth bool) (ir.Writer, erro case tfOutputFormat: return tfio.NewWriter(w), nil case csvOutputFormat: - return csvio.NewWriter(w), nil + return io.NewCSVWriter(w), nil case mdOutputFormat: - return mdio.NewWriter(w), nil + return io.NewMDWriter(w), nil case jsonOutputFormat: if isSynth { return confio.NewWriter(w, args.configFile) diff --git a/pkg/io/csvio/common.go b/pkg/io/common.go similarity index 77% rename from pkg/io/csvio/common.go rename to pkg/io/common.go index 41cd664d..4e4f9e33 100644 --- a/pkg/io/csvio/common.go +++ b/pkg/io/common.go @@ -3,33 +3,22 @@ Copyright 2023- IBM Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -// Package csvio implements output of ACLs and security groups in CSV format -package csvio +package io import ( - "encoding/csv" "fmt" - "io" "strconv" "strings" + "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// Writer implements ir.Writer -type Writer struct { - w *csv.Writer -} - -func NewWriter(w io.Writer) *Writer { - return &Writer{w: csv.NewWriter(w)} -} - const ( anyProtocol = "ALL" - nonIcmp = "-" // IBM cloud uses "—" + nonIcmp = "-" anyIcmpValue = "Any" ) @@ -40,6 +29,25 @@ func direction(d ir.Direction) string { return "Outbound" } +func printProtocolName(protocol netp.Protocol) string { + switch p := protocol.(type) { + case netp.ICMP: + return "ICMP" + case netp.TCPUDP: + return strings.ToUpper(string(p.ProtocolString())) + case netp.AnyProtocol: + return anyProtocol + } + return "" +} + +func printPorts(p interval.Interval) string { + if p.Equal(netp.AllPorts()) { + return "any port" + } + return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) +} + func printICMPTypeCode(protocol netp.Protocol) string { p, ok := protocol.(netp.ICMP) if !ok { @@ -55,15 +63,3 @@ func printICMPTypeCode(protocol netp.Protocol) string { } return fmt.Sprintf("Type: %v, Code: %v", icmpType, icmpCode) } - -func printProtocolName(protocol netp.Protocol) string { - switch p := protocol.(type) { - case netp.ICMP: - return "ICMP" - case netp.TCPUDP: - return strings.ToUpper(string(p.ProtocolString())) - case netp.AnyProtocol: - return anyProtocol - } - return "" -} diff --git a/pkg/io/csvio/acl.go b/pkg/io/commonACL.go similarity index 68% rename from pkg/io/csvio/acl.go rename to pkg/io/commonACL.go index 643dfe38..99a1f0be 100644 --- a/pkg/io/csvio/acl.go +++ b/pkg/io/commonACL.go @@ -3,36 +3,44 @@ Copyright 2023- IBM Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package csvio +package io import ( "errors" "fmt" "strconv" - "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -// Write prints an entire collection of acls as a single CSV table. -func (w *Writer) WriteACL(collection *ir.ACLCollection, vpc string) error { - if err := w.w.WriteAll(aclHeader()); err != nil { - return err - } +func WriteACL(collection *ir.ACLCollection, vpc string) ([][]string, error) { + res := make([][]string, 0) for _, subnet := range collection.SortedACLSubnets(vpc) { vpcName := ir.VpcFromScopedResource(subnet) aclTable, err := makeACLTable(collection.ACLs[vpcName][subnet], subnet) if err != nil { - return err - } - if err := w.w.WriteAll(aclTable); err != nil { - return err + return nil, err } + res = append(res, aclTable...) } - return nil + return res, nil +} + +func ACLHeader() [][]string { + return [][]string{{ + "Acl", + "Subnet", + "Direction", + "Rule priority", + "Allow or deny", + "Protocol", + "Source", + "Destination", + "Value", + "Description", + }} } func makeACLTable(t *ir.ACL, subnet string) ([][]string, error) { @@ -48,13 +56,6 @@ func makeACLTable(t *ir.ACL, subnet string) ([][]string, error) { return rows, nil } -func aclPort(p interval.Interval) string { - if p.Equal(netp.AllPorts()) { - return "any port" //nolint:goconst // independent decision for SG and ACL - } - return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) -} - func action(a ir.Action) string { if a == ir.Deny { return "Deny" @@ -62,24 +63,9 @@ func action(a ir.Action) string { return "Allow" } -func aclHeader() [][]string { - return [][]string{{ - "Acl", - "Subnet", - "Direction", - "Rule priority", - "Allow or deny", - "Protocol", - "Source", - "Destination", - "Value", - "Description", - }} -} - func makeACLRow(priority int, rule *ir.ACLRule, aclName, subnet string) ([]string, error) { - srcProtocol, err1 := printIP(rule.Source, rule.Protocol, true) - dstProtocol, err2 := printIP(rule.Destination, rule.Protocol, false) + src, err1 := printIP(rule.Source, rule.Protocol, true) + dst, err2 := printIP(rule.Destination, rule.Protocol, false) if errors.Join(err1, err2) != nil { return nil, errors.Join(err1, err2) } @@ -91,8 +77,8 @@ func makeACLRow(priority int, rule *ir.ACLRule, aclName, subnet string) ([]strin strconv.Itoa(priority), action(rule.Action), printProtocolName(rule.Protocol), - srcProtocol, - dstProtocol, + src, + dst, printICMPTypeCode(rule.Protocol), rule.Explanation, }, nil @@ -107,13 +93,11 @@ func printIP(ip *netset.IPBlock, protocol netp.Protocol, isSource bool) (string, case netp.ICMP: return ipString, nil case netp.TCPUDP: - var r interval.Interval + r := p.DstPorts() if isSource { r = p.SrcPorts() - } else { - r = p.DstPorts() } - return fmt.Sprintf("%v, %v", ipString, aclPort(r)), nil + return fmt.Sprintf("%v, %v", ipString, printPorts(r)), nil case netp.AnyProtocol: return ipString, nil } diff --git a/pkg/io/csvio/sg.go b/pkg/io/commonSG.go similarity index 80% rename from pkg/io/csvio/sg.go rename to pkg/io/commonSG.go index 35c74f8b..d7ab5793 100644 --- a/pkg/io/csvio/sg.go +++ b/pkg/io/commonSG.go @@ -3,23 +3,19 @@ Copyright 2023- IBM Inc. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 */ -package csvio +package io import ( "errors" "fmt" - "github.com/np-guard/models/pkg/interval" "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) -func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { - if err := w.w.WriteAll(sgHeader()); err != nil { - return err - } +func WriteSG(collection *ir.SGCollection, vpc string) ([][]string, error) { + res := make([][]string, 0) for _, vpcName := range collection.VpcNames() { if vpc != vpcName && vpc != "" { continue @@ -27,17 +23,15 @@ func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { for _, sgName := range collection.SortedSGNames(vpcName) { sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) if err != nil { - return err - } - if err := w.w.WriteAll(sgTable); err != nil { - return err + return nil, err } + res = append(res, sgTable...) } } - return nil + return res, nil } -func sgHeader() [][]string { +func SGHeader() [][]string { return [][]string{{ "SG", "Direction", @@ -49,6 +43,19 @@ func sgHeader() [][]string { }} } +func makeSGTable(t *ir.SG, sgName ir.SGName) ([][]string, error) { + rules := t.AllRules() + rows := make([][]string, len(rules)) + for i, rule := range rules { + sgRow, err := makeSGRow(rule, sgName) + if err != nil { + return nil, err + } + rows[i] = sgRow + } + return rows, nil +} + func makeSGRow(rule *ir.SGRule, sgName ir.SGName) ([]string, error) { remoteType, err1 := sgRemoteType(rule.Remote) remote, err2 := sgRemote(rule.Remote) @@ -68,28 +75,6 @@ func makeSGRow(rule *ir.SGRule, sgName ir.SGName) ([]string, error) { }, nil } -func makeSGTable(t *ir.SG, sgName ir.SGName) ([][]string, error) { - rules := t.AllRules() - rows := make([][]string, len(rules)) - for i, rule := range rules { - sgRow, err := makeSGRow(rule, sgName) - if err != nil { - return nil, err - } - rows[i] = sgRow - } - return rows, nil -} - -func sgPort(p interval.Interval) string { - switch { - case p.Start() == netp.MinPort && p.End() == netp.MaxPort: - return "any port" - default: - return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) - } -} - func sgRemoteType(t ir.RemoteType) (string, error) { switch p := t.(type) { case *netset.IPBlock: @@ -122,7 +107,7 @@ func printProtocolParams(protocol netp.Protocol) (string, error) { case netp.ICMP: return printICMPTypeCode(protocol), nil case netp.TCPUDP: - return sgPort(p.DstPorts()), nil + return printPorts(p.DstPorts()), nil case netp.AnyProtocol: return "", nil } diff --git a/pkg/io/csvWriter.go b/pkg/io/csvWriter.go new file mode 100644 index 00000000..4c97b060 --- /dev/null +++ b/pkg/io/csvWriter.go @@ -0,0 +1,38 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package io + +import ( + "encoding/csv" + "io" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +// CSVWriter implements ir.Writer +type CSVWriter struct { + w *csv.Writer +} + +func NewCSVWriter(w io.Writer) *CSVWriter { + return &CSVWriter{w: csv.NewWriter(w)} +} + +func (w *CSVWriter) WriteSG(collection *ir.SGCollection, vpc string) error { + sgTable, err := WriteSG(collection, vpc) + if err != nil { + return err + } + return w.w.WriteAll(append(SGHeader(), sgTable...)) +} + +func (w *CSVWriter) WriteACL(collection *ir.ACLCollection, vpc string) error { + aclTable, err := WriteACL(collection, vpc) + if err != nil { + return err + } + return w.w.WriteAll(append(ACLHeader(), aclTable...)) +} diff --git a/pkg/io/mdWriter.go b/pkg/io/mdWriter.go new file mode 100644 index 00000000..5da1d3ed --- /dev/null +++ b/pkg/io/mdWriter.go @@ -0,0 +1,71 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package io + +import ( + "bufio" + "io" + "strings" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +const ( + sgColsNum = 7 + aclColsNum = 10 + + leftAlign = " :--- " + separator = " | " +) + +// MDWriter implements ir.Writer +type MDWriter struct { + w *bufio.Writer +} + +func NewMDWriter(w io.Writer) *MDWriter { + return &MDWriter{w: bufio.NewWriter(w)} +} + +func (w *MDWriter) WriteSG(collection *ir.SGCollection, vpc string) error { + sgTable, err := WriteSG(collection, vpc) + if err != nil { + return err + } + return w.writeAll(append(append(SGHeader(), addAlighns(sgColsNum)...), sgTable...)) +} + +func (w *MDWriter) WriteACL(collection *ir.ACLCollection, vpc string) error { + aclTable, err := WriteACL(collection, vpc) + if err != nil { + return err + } + return w.writeAll(append(append(ACLHeader(), addAlighns(aclColsNum)...), aclTable...)) +} + +func (w *MDWriter) writeAll(rows [][]string) error { + for _, row := range rows { + if _, err := w.w.WriteString(separator); err != nil { + return err + } + if _, err := w.w.WriteString(strings.Join(row, separator)); err != nil { + return err + } + if _, err := w.w.WriteString(separator + "\n"); err != nil { + return err + } + } + w.w.Flush() + return nil +} + +func addAlighns(n int) [][]string { + res := make([]string, n) + for i := range n { + res[i] = leftAlign + } + return [][]string{res} +} diff --git a/pkg/io/mdio/acl.go b/pkg/io/mdio/acl.go deleted file mode 100644 index 17f2b2ee..00000000 --- a/pkg/io/mdio/acl.go +++ /dev/null @@ -1,138 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package mdio - -import ( - "errors" - "fmt" - "strconv" - - "github.com/np-guard/models/pkg/interval" - "github.com/np-guard/models/pkg/netp" - "github.com/np-guard/models/pkg/netset" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -) - -// Write prints an entire collection of acls as a single MD table. -func (w *Writer) WriteACL(collection *ir.ACLCollection, vpc string) error { - if err := w.writeAll(aclHeader()); err != nil { - return err - } - for _, subnet := range collection.SortedACLSubnets(vpc) { - vpcName := ir.VpcFromScopedResource(subnet) - aclTable, err := makeACLTable(collection.ACLs[vpcName][subnet], subnet) - if err != nil { - return err - } - if err := w.writeAll(aclTable); err != nil { - return err - } - } - return nil -} - -func makeACLTable(t *ir.ACL, subnet string) ([][]string, error) { - rules := t.Rules() - rows := make([][]string, len(rules)) - for i, rule := range rules { - aclRow, err := makeACLRow(i+1, rule, t.Name(), subnet) - if err != nil { - return nil, err - } - rows[i] = aclRow - } - return rows, nil -} - -func aclPort(p interval.Interval) string { - if p.Equal(netp.AllPorts()) { - return "any port" //nolint:goconst // independent decision for SG and ACL - } - return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) -} - -func action(a ir.Action) string { - if a == ir.Deny { - return "Deny" - } - return "Allow" -} - -func aclHeader() [][]string { - return [][]string{{ - "", - "Acl", - "Subnet", - "Direction", - "Rule priority", - "Allow or deny", - "Protocol", - "Source", - "Destination", - "Value", - "Description", - "", - }, { - "", - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - "", - }} -} - -func makeACLRow(priority int, rule *ir.ACLRule, aclName, subnet string) ([]string, error) { - srcProtocol, err1 := printIP(rule.Source, rule.Protocol, true) - dstProtocol, err2 := printIP(rule.Destination, rule.Protocol, false) - if err := errors.Join(err1, err2); err != nil { - return nil, err - } - - return []string{ - "", - aclName, - subnet, - direction(rule.Direction), - strconv.Itoa(priority), - action(rule.Action), - printProtocolName(rule.Protocol), - srcProtocol, - dstProtocol, - printICMPTypeCode(rule.Protocol), - rule.Explanation, - "", - }, nil -} - -func printIP(ip *netset.IPBlock, protocol netp.Protocol, isSource bool) (string, error) { - ipString := ip.String() - if ip.Equal(netset.GetCidrAll()) { - ipString = "Any IP" //nolint:goconst // independent decision for SG and ACL - } - switch p := protocol.(type) { - case netp.ICMP: - return ipString, nil - case netp.TCPUDP: - var r interval.Interval - if isSource { - r = p.SrcPorts() - } else { - r = p.DstPorts() - } - return fmt.Sprintf("%v, %v", ipString, aclPort(r)), nil - case netp.AnyProtocol: - return ipString, nil - } - return "", fmt.Errorf("impossible protocol %T", protocol) -} diff --git a/pkg/io/mdio/common.go b/pkg/io/mdio/common.go deleted file mode 100644 index abfb24a8..00000000 --- a/pkg/io/mdio/common.go +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -// Package mdio implements output of ACLs and security groups in CSV format -package mdio - -import ( - "bufio" - "fmt" - "io" - "strconv" - "strings" - - "github.com/np-guard/models/pkg/netp" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -) - -const leftAlign = " :--- " - -// Writer implements ir.Writer -type Writer struct { - w *bufio.Writer -} - -func NewWriter(w io.Writer) *Writer { - return &Writer{w: bufio.NewWriter(w)} -} - -func (w *Writer) writeAll(rows [][]string) error { - for _, row := range rows { - _, err := w.w.WriteString(strings.Join(row, " | ") + "\n") - if err != nil { - return err - } - } - w.w.Flush() - return nil -} - -const ( - anyProtocol = "ALL" - nonIcmp = "-" - anyIcmpValue = "Any" -) - -func direction(d ir.Direction) string { - if d == ir.Inbound { - return "Inbound" - } - return "Outbound" -} - -func printICMPTypeCode(protocol netp.Protocol) string { - p, ok := protocol.(netp.ICMP) - if !ok { - return nonIcmp - } - icmpType := anyIcmpValue - icmpCode := anyIcmpValue - if typeCode := p.ICMPTypeCode(); typeCode != nil { - icmpType = strconv.Itoa(typeCode.Type) - if typeCode.Code != nil { - icmpCode = strconv.Itoa(*typeCode.Code) - } - } - return fmt.Sprintf("Type: %v, Code: %v", icmpType, icmpCode) -} - -func printProtocolName(protocol netp.Protocol) string { - switch p := protocol.(type) { - case netp.ICMP: - return "ICMP" - case netp.TCPUDP: - return strings.ToUpper(string(p.ProtocolString())) - case netp.AnyProtocol: - return anyProtocol - } - return "" -} diff --git a/pkg/io/mdio/sg.go b/pkg/io/mdio/sg.go deleted file mode 100644 index 0fcbf734..00000000 --- a/pkg/io/mdio/sg.go +++ /dev/null @@ -1,144 +0,0 @@ -/* -Copyright 2023- IBM Inc. All Rights Reserved. -SPDX-License-Identifier: Apache-2.0 -*/ - -package mdio - -import ( - "errors" - "fmt" - - "github.com/np-guard/models/pkg/interval" - "github.com/np-guard/models/pkg/netp" - "github.com/np-guard/models/pkg/netset" - - "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" -) - -func (w *Writer) WriteSG(collection *ir.SGCollection, vpc string) error { - if err := w.writeAll(sgHeader()); err != nil { - return err - } - for _, vpcName := range collection.VpcNames() { - if vpc != vpcName && vpc != "" { - continue - } - for _, sgName := range collection.SortedSGNames(vpcName) { - sgTable, err := makeSGTable(collection.SGs[vpcName][sgName], sgName) - if err != nil { - return err - } - if err := w.writeAll(sgTable); err != nil { - return err - } - } - } - return nil -} - -func sgHeader() [][]string { - return [][]string{{ - "", - "SG", - "Direction", - "Remote type", - "Remote", - "Protocol", - "Protocol params", - "Description", - "", - }, { - "", - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - leftAlign, - "", - }} -} - -func makeSGRow(rule *ir.SGRule, sgName ir.SGName) ([]string, error) { - remoteType, err1 := sgRemoteType(rule.Remote) - remote, err2 := sgRemote(rule.Remote) - protocolParams, err3 := printProtocolParams(rule.Protocol) - if err := errors.Join(err1, err2, err3); err != nil { - return nil, err - } - - return []string{ - "", - string(sgName), - direction(rule.Direction), - remoteType, - remote, - printProtocolName(rule.Protocol), - protocolParams, - rule.Explanation, - "", - }, nil -} - -func makeSGTable(t *ir.SG, sgName ir.SGName) ([][]string, error) { - rules := t.AllRules() - rows := make([][]string, len(rules)) - for i, rule := range rules { - sgRow, err := makeSGRow(rule, sgName) - if err != nil { - return nil, err - } - rows[i] = sgRow - } - return rows, nil -} - -func sgPort(p interval.Interval) string { - switch { - case p.Start() == netp.MinPort && p.End() == netp.MaxPort: - return "any port" - default: - return fmt.Sprintf("ports %v-%v", p.Start(), p.End()) - } -} - -func sgRemoteType(t ir.RemoteType) (string, error) { - switch r := t.(type) { - case *netset.IPBlock: - if ipString := r.ToIPAddressString(); ipString != "" { // single IP address - return "IP address", nil - } - return "CIDR block", nil - case ir.SGName: - return "Security group", nil - } - return "", fmt.Errorf("impossible remote type %T", t) -} - -func sgRemote(r ir.RemoteType) (string, error) { - switch tr := r.(type) { - case *netset.IPBlock: - s := tr.String() - if s == netset.CidrAll { - return "Any IP", nil - } - return s, nil - case ir.SGName: - return tr.String(), nil - } - return "", fmt.Errorf("impossible remote %v (%T)", r, r) -} - -func printProtocolParams(protocol netp.Protocol) (string, error) { - switch p := protocol.(type) { - case netp.ICMP: - return printICMPTypeCode(protocol), nil - case netp.TCPUDP: - return sgPort(p.DstPorts()), nil - case netp.AnyProtocol: - return "", nil - } - return "", fmt.Errorf("impossible protocol %v (type %T)", protocol, protocol) -} From fb59982440573bcca8bdb22e008dc0322698b5da Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 20 Oct 2024 15:39:28 +0300 Subject: [PATCH 71/79] added isSynth argument --- cmd/subcmds/output.go | 2 +- pkg/io/confio/acl.go | 2 +- pkg/io/confio/sg.go | 2 +- pkg/io/csvWriter.go | 4 ++-- pkg/io/mdWriter.go | 4 ++-- pkg/io/tfio/acl.go | 2 +- pkg/io/tfio/sg.go | 2 +- pkg/ir/acl.go | 6 +++--- pkg/ir/common.go | 2 +- pkg/ir/sg.go | 6 +++--- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/cmd/subcmds/output.go b/cmd/subcmds/output.go index 66bf752a..97acf01a 100644 --- a/cmd/subcmds/output.go +++ b/cmd/subcmds/output.go @@ -64,7 +64,7 @@ func writeCollection(args *inArgs, collection ir.Collection, vpc string, isSynth if err != nil { return nil, err } - if err := collection.Write(writer, vpc); err != nil { + if err := collection.Write(writer, vpc, isSynth); err != nil { return nil, err } return &data, nil diff --git a/pkg/io/confio/acl.go b/pkg/io/confio/acl.go index ae5e7a7b..03059301 100644 --- a/pkg/io/confio/acl.go +++ b/pkg/io/confio/acl.go @@ -209,7 +209,7 @@ func subnetRef(subnet *configModel.Subnet) *vpcv1.SubnetReference { } } -func (w *Writer) WriteACL(collection *ir.ACLCollection, _ string) error { +func (w *Writer) WriteACL(collection *ir.ACLCollection, _ string, _ bool) error { if err := updateACLList(w.model, collection); err != nil { return err } diff --git a/pkg/io/confio/sg.go b/pkg/io/confio/sg.go index e4b74be7..90f1fd4f 100644 --- a/pkg/io/confio/sg.go +++ b/pkg/io/confio/sg.go @@ -258,7 +258,7 @@ func updateSG(model *configModel.ResourcesContainerModel, collection *ir.SGColle return errors.Join(err1, err2) } -func (w *Writer) WriteSG(collection *ir.SGCollection, _ string) error { +func (w *Writer) WriteSG(collection *ir.SGCollection, _ string, isSynth bool) error { if err := updateSG(w.model, collection); err != nil { return err } diff --git a/pkg/io/csvWriter.go b/pkg/io/csvWriter.go index 4c97b060..e583ca45 100644 --- a/pkg/io/csvWriter.go +++ b/pkg/io/csvWriter.go @@ -21,7 +21,7 @@ func NewCSVWriter(w io.Writer) *CSVWriter { return &CSVWriter{w: csv.NewWriter(w)} } -func (w *CSVWriter) WriteSG(collection *ir.SGCollection, vpc string) error { +func (w *CSVWriter) WriteSG(collection *ir.SGCollection, vpc string, _ bool) error { sgTable, err := WriteSG(collection, vpc) if err != nil { return err @@ -29,7 +29,7 @@ func (w *CSVWriter) WriteSG(collection *ir.SGCollection, vpc string) error { return w.w.WriteAll(append(SGHeader(), sgTable...)) } -func (w *CSVWriter) WriteACL(collection *ir.ACLCollection, vpc string) error { +func (w *CSVWriter) WriteACL(collection *ir.ACLCollection, vpc string, _ bool) error { aclTable, err := WriteACL(collection, vpc) if err != nil { return err diff --git a/pkg/io/mdWriter.go b/pkg/io/mdWriter.go index 5da1d3ed..94b18553 100644 --- a/pkg/io/mdWriter.go +++ b/pkg/io/mdWriter.go @@ -30,7 +30,7 @@ func NewMDWriter(w io.Writer) *MDWriter { return &MDWriter{w: bufio.NewWriter(w)} } -func (w *MDWriter) WriteSG(collection *ir.SGCollection, vpc string) error { +func (w *MDWriter) WriteSG(collection *ir.SGCollection, vpc string, _ bool) error { sgTable, err := WriteSG(collection, vpc) if err != nil { return err @@ -38,7 +38,7 @@ func (w *MDWriter) WriteSG(collection *ir.SGCollection, vpc string) error { return w.writeAll(append(append(SGHeader(), addAlighns(sgColsNum)...), sgTable...)) } -func (w *MDWriter) WriteACL(collection *ir.ACLCollection, vpc string) error { +func (w *MDWriter) WriteACL(collection *ir.ACLCollection, vpc string, _ bool) error { aclTable, err := WriteACL(collection, vpc) if err != nil { return err diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index d71b8d56..15b31afe 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -18,7 +18,7 @@ import ( ) // WriteACL prints an entire collection of acls as a sequence of terraform resources. -func (w *Writer) WriteACL(c *ir.ACLCollection, vpc string) error { +func (w *Writer) WriteACL(c *ir.ACLCollection, vpc string, _ bool) error { collection, err := aclCollection(c, vpc) if err != nil { return err diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index dafcaa6d..4d30de34 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -18,7 +18,7 @@ import ( ) // WriteSG prints an entire collection of Security Groups as a sequence of terraform resources. -func (w *Writer) WriteSG(c *ir.SGCollection, vpc string) error { +func (w *Writer) WriteSG(c *ir.SGCollection, vpc string, isSynth bool) error { collection, err := sgCollection(c, vpc) if err != nil { return err diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index e13b91bb..938a74e8 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -38,7 +38,7 @@ type ( } ACLWriter interface { - WriteACL(aclColl *ACLCollection, vpc string) error + WriteACL(aclColl *ACLCollection, vpc string, isSynth bool) error } ) @@ -128,8 +128,8 @@ func (c *ACLCollection) VpcNames() []string { return utils.SortedMapKeys(c.ACLs) } -func (c *ACLCollection) Write(w Writer, vpc string) error { - return w.WriteACL(c, vpc) +func (c *ACLCollection) Write(w Writer, vpc string, isSynth bool) error { + return w.WriteACL(c, vpc, isSynth) } func (c *ACLCollection) SortedACLSubnets(vpc string) []string { diff --git a/pkg/ir/common.go b/pkg/ir/common.go index a89aeae8..49d87bbc 100644 --- a/pkg/ir/common.go +++ b/pkg/ir/common.go @@ -9,7 +9,7 @@ type ( Direction string Collection interface { - Write(writer Writer, vpc string) error + Write(writer Writer, vpc string, isSynth bool) error VpcNames() []string } diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 286d683d..eb1737ec 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -54,7 +54,7 @@ type ( } SGWriter interface { - WriteSG(sgColl *SGCollection, vpc string) error + WriteSG(sgColl *SGCollection, vpc string, isSynth bool) error } ) @@ -122,8 +122,8 @@ func (c *SGCollection) VpcNames() []string { return utils.SortedMapKeys(c.SGs) } -func (c *SGCollection) Write(w Writer, vpc string) error { - return w.WriteSG(c, vpc) +func (c *SGCollection) Write(w Writer, vpc string, isSynth bool) error { + return w.WriteSG(c, vpc, isSynth) } func (c *SGCollection) SortedSGNames(vpc ID) []SGName { From 27bbf91796d2248a9ab5e64c90d8a035d835b594 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 20 Oct 2024 16:07:55 +0300 Subject: [PATCH 72/79] read sg targets, rename attached to targets --- pkg/io/confio/parse_sgs.go | 16 +++++++++++++++- pkg/ir/sg.go | 4 ++-- pkg/synth/sg.go | 4 ++-- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index e1528913..4ae37ecd 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -39,7 +39,10 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { if result.SGs[vpcName] == nil { result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) } - result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, OutboundRules: outbound} + result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, + OutboundRules: outbound, + Targets: transalteTargets(sg.Targets), + } } return result, nil } @@ -170,6 +173,17 @@ func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, er return nil, fmt.Errorf("error parsing Local field") } +// translate SG targets +func transalteTargets(targets []vpcv1.SecurityGroupTargetReferenceIntf) []string { + res := make([]string, 0) + for i := range targets { + if t, ok := targets[i].(*vpcv1.SecurityGroupTargetReference); ok && t.Name != nil { + res = append(res, *t.Name) + } + } + return res +} + // temporary - first version of optimization requires local = 0.0.0.0/32 func verifyLocalValue(ipAddrs *netset.IPBlock) (*netset.IPBlock, error) { if !ipAddrs.Equal(netset.GetCidrAll()) { diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index eb1737ec..4ee2dd10 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -46,7 +46,7 @@ type ( SGName SGName InboundRules []*SGRule OutboundRules []*SGRule - Attached []ID + Targets []ID } SGCollection struct { @@ -85,7 +85,7 @@ func NewSGRule(direction Direction, remote RemoteType, p netp.Protocol, local *n } func NewSG(sgName SGName) *SG { - return &SG{SGName: sgName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Attached: []ID{}} + return &SG{SGName: sgName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Targets: []ID{}} } func NewSGCollection() *SGCollection { diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index c90b1783..4ffd887b 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -84,7 +84,7 @@ func (s *SGSynthesizer) allowConnectionEndpoint(localEndpoint, remoteEndpoint *n } localSGName := ir.SGName(localEndpoint.Name) localSG := s.result.LookupOrCreate(localSGName) - localSG.Attached = []ir.ID{ir.ID(localSGName)} + localSG.Targets = []ir.ID{ir.ID(localSGName)} rule := &ir.SGRule{ Remote: sgRemote(&s.spec.Defs, remoteEndpoint), Direction: direction, @@ -99,7 +99,7 @@ func (s *SGSynthesizer) generateSGsForBlockedResources() { blockedResources := s.spec.ComputeBlockedResources() for _, resource := range blockedResources { sg := s.result.LookupOrCreate(ir.SGName(resource)) // an empty SG allows no connections - sg.Attached = []ir.ID{resource} + sg.Targets = []ir.ID{resource} } } From 40e87d32a2aab56dcbe52560bd6281bec9674567 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Sun, 20 Oct 2024 16:33:41 +0300 Subject: [PATCH 73/79] tf comment, read targets --- pkg/io/commonACL.go | 1 + pkg/io/commonSG.go | 1 + pkg/io/confio/parse_sgs.go | 16 ++++++--- pkg/io/tfio/sg.go | 26 +++++++------- .../sg_expected.tf | 11 +++--- .../optimize_sg_redundant/sg_expected.tf | 11 +++--- test/expected/optimize_sg_t/sg_expected.tf | 11 +++--- .../expected/optimize_sg_t_all/sg_expected.tf | 11 +++--- test/expected/sg_protocols_tf/sg_expected.tf | 36 +++++++++---------- test/expected/sg_testing3_tf/sg_expected.tf | 12 +++---- .../sg_tg_multiple_tf_separate/test-vpc0.tf | 24 ++++++------- .../sg_tg_multiple_tf_separate/test-vpc1.tf | 4 +-- .../sg_tg_multiple_tf_separate/test-vpc2.tf | 6 ++-- .../sg_tg_multiple_tf_separate/test-vpc3.tf | 2 +- 14 files changed, 92 insertions(+), 80 deletions(-) diff --git a/pkg/io/commonACL.go b/pkg/io/commonACL.go index 99a1f0be..3dfe2537 100644 --- a/pkg/io/commonACL.go +++ b/pkg/io/commonACL.go @@ -12,6 +12,7 @@ import ( "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) diff --git a/pkg/io/commonSG.go b/pkg/io/commonSG.go index d7ab5793..021f5a57 100644 --- a/pkg/io/commonSG.go +++ b/pkg/io/commonSG.go @@ -11,6 +11,7 @@ import ( "github.com/np-guard/models/pkg/netp" "github.com/np-guard/models/pkg/netset" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index 4ae37ecd..5b0cdc95 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -39,9 +39,10 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { if result.SGs[vpcName] == nil { result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) } - result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{InboundRules: inbound, + result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{SGName: ir.SGName(*sg.Name), + InboundRules: inbound, OutboundRules: outbound, - Targets: transalteTargets(sg.Targets), + Targets: transalteTargets(&sg.SecurityGroup), } } return result, nil @@ -174,11 +175,16 @@ func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, er } // translate SG targets -func transalteTargets(targets []vpcv1.SecurityGroupTargetReferenceIntf) []string { +func transalteTargets(sg *vpcv1.SecurityGroup) []string { + if len(sg.Targets) == 0 { + log.Printf("Warning: Security Groups %s does not have attached resources", *sg.Name) + } res := make([]string, 0) - for i := range targets { - if t, ok := targets[i].(*vpcv1.SecurityGroupTargetReference); ok && t.Name != nil { + for i := range sg.Targets { + if t, ok := sg.Targets[i].(*vpcv1.SecurityGroupTargetReference); ok && t.Name != nil { res = append(res, *t.Name) + } else { + log.Printf("Warning: error translating target %d in %s Security Group", i, *sg.Name) } } return res diff --git a/pkg/io/tfio/sg.go b/pkg/io/tfio/sg.go index 4d30de34..05d330a1 100644 --- a/pkg/io/tfio/sg.go +++ b/pkg/io/tfio/sg.go @@ -18,7 +18,7 @@ import ( ) // WriteSG prints an entire collection of Security Groups as a sequence of terraform resources. -func (w *Writer) WriteSG(c *ir.SGCollection, vpc string, isSynth bool) error { +func (w *Writer) WriteSG(c *ir.SGCollection, vpc string, _ bool) error { collection, err := sgCollection(c, vpc) if err != nil { return err @@ -79,7 +79,7 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { return tf.Block{ Name: "resource", - Labels: []string{quote("ibm_is_security_group_rule"), ir.ChangeScoping(quote(ruleName))}, + Labels: []string{quote("ibm_is_security_group_rule"), quote(ruleName)}, Comment: comment, Arguments: []tf.Argument{ {Name: "group", Value: group}, @@ -90,21 +90,21 @@ func sgRule(rule *ir.SGRule, sgName ir.SGName, i int) (tf.Block, error) { }, nil } -func sg(sgName, vpcName string) (tf.Block, error) { - tfSGName := ir.ChangeScoping(sgName) - comment := fmt.Sprintf("\n### SG attached to %s", sgName) - if sgName == tfSGName { // optimization mode - comment = "\n" +func sg(sG *ir.SG, vpcName string) (tf.Block, error) { + sgName := ir.ChangeScoping(sG.SGName.String()) + comment := fmt.Sprintf("\n### SG %s is attached to %s", sgName, strings.Join(sG.Targets, ", ")) + if len(sG.Targets) == 0 { + comment = fmt.Sprintf("\n### SG %s is not attached to anything", sgName) } - if err := verifyName(tfSGName); err != nil { + if err := verifyName(sgName); err != nil { return tf.Block{}, err } return tf.Block{ Name: "resource", //nolint:revive // obvious false positive - Labels: []string{quote("ibm_is_security_group"), quote(tfSGName)}, + Labels: []string{quote("ibm_is_security_group"), quote(sgName)}, Comment: comment, Arguments: []tf.Argument{ - {Name: "name", Value: quote("sg-" + tfSGName)}, + {Name: "name", Value: quote("sg-" + sgName)}, {Name: "resource_group", Value: "local.sg_synth_resource_group_id"}, {Name: "vpc", Value: fmt.Sprintf("local.sg_synth_%s_id", vpcName)}, }, @@ -119,13 +119,13 @@ func sgCollection(collection *ir.SGCollection, vpc string) (*tf.ConfigFile, erro continue } for _, sgName := range collection.SortedSGNames(vpcName) { - rules := collection.SGs[vpcName][sgName].AllRules() - sg, err := sg(sgName.String(), vpcName) + sG := collection.SGs[vpcName][sgName] + sg, err := sg(sG, vpcName) if err != nil { return nil, err } resources = append(resources, sg) - for i, rule := range rules { + for i, rule := range sG.AllRules() { rule, err := sgRule(rule, sgName, i) if err != nil { return nil, err diff --git a/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf index 10f44116..3b2fc12f 100644 --- a/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf +++ b/test/expected/optimize_sg_protocols_to_all_tf/sg_expected.tf @@ -1,3 +1,4 @@ +### SG sg1 is not attached to anything resource "ibm_is_security_group" "sg1" { name = "sg-sg1" resource_group = local.sg_synth_resource_group_id @@ -14,7 +15,7 @@ resource "ibm_is_security_group_rule" "sg1-1" { remote = "0.0.0.0/0" } - +### SG test-vpc1--vsi1 is attached to ni1 resource "ibm_is_security_group" "test-vpc1--vsi1" { name = "sg-test-vpc1--vsi1" resource_group = local.sg_synth_resource_group_id @@ -38,7 +39,7 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-2" { remote = "0.0.0.0/31" } - +### SG test-vpc1--vsi2 is attached to ni2 resource "ibm_is_security_group" "test-vpc1--vsi2" { name = "sg-test-vpc1--vsi2" resource_group = local.sg_synth_resource_group_id @@ -50,21 +51,21 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { remote = ibm_is_security_group.test-vpc1--vsi1.id } - +### SG test-vpc1--vsi3a is attached to ni3a resource "ibm_is_security_group" "test-vpc1--vsi3a" { name = "sg-test-vpc1--vsi3a" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG test-vpc1--vsi3b is attached to ni3b resource "ibm_is_security_group" "test-vpc1--vsi3b" { name = "sg-test-vpc1--vsi3b" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG wombat-hesitate-scorn-subprime is not attached to anything resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { name = "sg-wombat-hesitate-scorn-subprime" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/optimize_sg_redundant/sg_expected.tf b/test/expected/optimize_sg_redundant/sg_expected.tf index 88239143..5ee3d54f 100644 --- a/test/expected/optimize_sg_redundant/sg_expected.tf +++ b/test/expected/optimize_sg_redundant/sg_expected.tf @@ -1,3 +1,4 @@ +### SG sg1 is not attached to anything resource "ibm_is_security_group" "sg1" { name = "sg-sg1" resource_group = local.sg_synth_resource_group_id @@ -14,7 +15,7 @@ resource "ibm_is_security_group_rule" "sg1-1" { remote = "0.0.0.0/0" } - +### SG test-vpc1--vsi1 is attached to ni1 resource "ibm_is_security_group" "test-vpc1--vsi1" { name = "sg-test-vpc1--vsi1" resource_group = local.sg_synth_resource_group_id @@ -31,7 +32,7 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { remote = "0.0.0.0/30" } - +### SG test-vpc1--vsi2 is attached to ni2 resource "ibm_is_security_group" "test-vpc1--vsi2" { name = "sg-test-vpc1--vsi2" resource_group = local.sg_synth_resource_group_id @@ -43,21 +44,21 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi2-0" { remote = ibm_is_security_group.test-vpc1--vsi1.id } - +### SG test-vpc1--vsi3a is attached to ni3a resource "ibm_is_security_group" "test-vpc1--vsi3a" { name = "sg-test-vpc1--vsi3a" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG test-vpc1--vsi3b is attached to ni3b resource "ibm_is_security_group" "test-vpc1--vsi3b" { name = "sg-test-vpc1--vsi3b" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG wombat-hesitate-scorn-subprime is not attached to anything resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { name = "sg-wombat-hesitate-scorn-subprime" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/optimize_sg_t/sg_expected.tf b/test/expected/optimize_sg_t/sg_expected.tf index 448d25d8..995e1b94 100644 --- a/test/expected/optimize_sg_t/sg_expected.tf +++ b/test/expected/optimize_sg_t/sg_expected.tf @@ -1,3 +1,4 @@ +### SG sg1 is not attached to anything resource "ibm_is_security_group" "sg1" { name = "sg-sg1" resource_group = local.sg_synth_resource_group_id @@ -14,7 +15,7 @@ resource "ibm_is_security_group_rule" "sg1-1" { remote = "0.0.0.0/0" } - +### SG test-vpc1--vsi1 is attached to ni1 resource "ibm_is_security_group" "test-vpc1--vsi1" { name = "sg-test-vpc1--vsi1" resource_group = local.sg_synth_resource_group_id @@ -37,28 +38,28 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { } } - +### SG test-vpc1--vsi2 is attached to ni2 resource "ibm_is_security_group" "test-vpc1--vsi2" { name = "sg-test-vpc1--vsi2" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG test-vpc1--vsi3a is attached to ni3a resource "ibm_is_security_group" "test-vpc1--vsi3a" { name = "sg-test-vpc1--vsi3a" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG test-vpc1--vsi3b is attached to ni3b resource "ibm_is_security_group" "test-vpc1--vsi3b" { name = "sg-test-vpc1--vsi3b" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG wombat-hesitate-scorn-subprime is not attached to anything resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { name = "sg-wombat-hesitate-scorn-subprime" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/optimize_sg_t_all/sg_expected.tf b/test/expected/optimize_sg_t_all/sg_expected.tf index 0f4d41e0..fd5b626f 100644 --- a/test/expected/optimize_sg_t_all/sg_expected.tf +++ b/test/expected/optimize_sg_t_all/sg_expected.tf @@ -1,3 +1,4 @@ +### SG sg1 is not attached to anything resource "ibm_is_security_group" "sg1" { name = "sg-sg1" resource_group = local.sg_synth_resource_group_id @@ -14,7 +15,7 @@ resource "ibm_is_security_group_rule" "sg1-1" { remote = "0.0.0.0/0" } - +### SG test-vpc1--vsi1 is attached to ni1 resource "ibm_is_security_group" "test-vpc1--vsi1" { name = "sg-test-vpc1--vsi1" resource_group = local.sg_synth_resource_group_id @@ -34,28 +35,28 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi1-1" { remote = "0.0.0.2/31" } - +### SG test-vpc1--vsi2 is attached to ni2 resource "ibm_is_security_group" "test-vpc1--vsi2" { name = "sg-test-vpc1--vsi2" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG test-vpc1--vsi3a is attached to ni3a resource "ibm_is_security_group" "test-vpc1--vsi3a" { name = "sg-test-vpc1--vsi3a" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG test-vpc1--vsi3b is attached to ni3b resource "ibm_is_security_group" "test-vpc1--vsi3b" { name = "sg-test-vpc1--vsi3b" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } - +### SG wombat-hesitate-scorn-subprime is not attached to anything resource "ibm_is_security_group" "wombat-hesitate-scorn-subprime" { name = "sg-wombat-hesitate-scorn-subprime" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/sg_protocols_tf/sg_expected.tf b/test/expected/sg_protocols_tf/sg_expected.tf index f7519b05..a85f889c 100644 --- a/test/expected/sg_protocols_tf/sg_expected.tf +++ b/test/expected/sg_protocols_tf/sg_expected.tf @@ -1,4 +1,4 @@ -### SG attached to test-vpc0/vsi0-subnet0 +### SG test-vpc0--vsi0-subnet0 is attached to test-vpc0/vsi0-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet0" { name = "sg-test-vpc0--vsi0-subnet0" resource_group = local.sg_synth_resource_group_id @@ -21,7 +21,7 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-1" { } } -### SG attached to test-vpc0/vsi0-subnet1 +### SG test-vpc0--vsi0-subnet1 is attached to test-vpc0/vsi0-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet1" { name = "sg-test-vpc0--vsi0-subnet1" resource_group = local.sg_synth_resource_group_id @@ -44,7 +44,7 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet1-1" { } } -### SG attached to test-vpc0/vsi0-subnet2 +### SG test-vpc0--vsi0-subnet2 is attached to test-vpc0/vsi0-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet2" { name = "sg-test-vpc0--vsi0-subnet2" resource_group = local.sg_synth_resource_group_id @@ -69,7 +69,7 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet2-1" { } } -### SG attached to test-vpc0/vsi0-subnet3 +### SG test-vpc0--vsi0-subnet3 is attached to test-vpc0/vsi0-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet3" { name = "sg-test-vpc0--vsi0-subnet3" resource_group = local.sg_synth_resource_group_id @@ -94,21 +94,21 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet3-1" { } } -### SG attached to test-vpc0/vsi0-subnet4 +### SG test-vpc0--vsi0-subnet4 is attached to test-vpc0/vsi0-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet4" { name = "sg-test-vpc0--vsi0-subnet4" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi0-subnet5 +### SG test-vpc0--vsi0-subnet5 is attached to test-vpc0/vsi0-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet5" { name = "sg-test-vpc0--vsi0-subnet5" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet0 +### SG test-vpc0--vsi1-subnet0 is attached to test-vpc0/vsi1-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet0" { name = "sg-test-vpc0--vsi1-subnet0" resource_group = local.sg_synth_resource_group_id @@ -144,7 +144,7 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet0-2" { } } -### SG attached to test-vpc0/vsi1-subnet1 +### SG test-vpc0--vsi1-subnet1 is attached to test-vpc0/vsi1-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet1" { name = "sg-test-vpc0--vsi1-subnet1" resource_group = local.sg_synth_resource_group_id @@ -180,35 +180,35 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet1-2" { } } -### SG attached to test-vpc0/vsi1-subnet2 +### SG test-vpc0--vsi1-subnet2 is attached to test-vpc0/vsi1-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet2" { name = "sg-test-vpc0--vsi1-subnet2" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet3 +### SG test-vpc0--vsi1-subnet3 is attached to test-vpc0/vsi1-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet3" { name = "sg-test-vpc0--vsi1-subnet3" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet4 +### SG test-vpc0--vsi1-subnet4 is attached to test-vpc0/vsi1-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet4" { name = "sg-test-vpc0--vsi1-subnet4" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet5 +### SG test-vpc0--vsi1-subnet5 is attached to test-vpc0/vsi1-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet5" { name = "sg-test-vpc0--vsi1-subnet5" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc1/vsi0-subnet10 +### SG test-vpc1--vsi0-subnet10 is attached to test-vpc1/vsi0-subnet10 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet10" { name = "sg-test-vpc1--vsi0-subnet10" resource_group = local.sg_synth_resource_group_id @@ -223,21 +223,21 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet10-0" { } } -### SG attached to test-vpc1/vsi0-subnet11 +### SG test-vpc1--vsi0-subnet11 is attached to test-vpc1/vsi0-subnet11 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet11" { name = "sg-test-vpc1--vsi0-subnet11" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc1_id } -### SG attached to test-vpc2/vsi0-subnet20 +### SG test-vpc2--vsi0-subnet20 is attached to test-vpc2/vsi0-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi0-subnet20" { name = "sg-test-vpc2--vsi0-subnet20" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc2_id } -### SG attached to test-vpc2/vsi1-subnet20 +### SG test-vpc2--vsi1-subnet20 is attached to test-vpc2/vsi1-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi1-subnet20" { name = "sg-test-vpc2--vsi1-subnet20" resource_group = local.sg_synth_resource_group_id @@ -250,14 +250,14 @@ resource "ibm_is_security_group_rule" "test-vpc2--vsi1-subnet20-0" { remote = "0.0.0.0/0" } -### SG attached to test-vpc2/vsi2-subnet20 +### SG test-vpc2--vsi2-subnet20 is attached to test-vpc2/vsi2-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi2-subnet20" { name = "sg-test-vpc2--vsi2-subnet20" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc2_id } -### SG attached to test-vpc3/vsi0-subnet30 +### SG test-vpc3--vsi0-subnet30 is attached to test-vpc3/vsi0-subnet30 resource "ibm_is_security_group" "test-vpc3--vsi0-subnet30" { name = "sg-test-vpc3--vsi0-subnet30" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/sg_testing3_tf/sg_expected.tf b/test/expected/sg_testing3_tf/sg_expected.tf index 8bfb66a3..c7ced9bf 100644 --- a/test/expected/sg_testing3_tf/sg_expected.tf +++ b/test/expected/sg_testing3_tf/sg_expected.tf @@ -1,11 +1,11 @@ -### SG attached to test-vpc/appdata-endpoint-gateway +### SG test-vpc--appdata-endpoint-gateway is attached to test-vpc/appdata-endpoint-gateway resource "ibm_is_security_group" "test-vpc--appdata-endpoint-gateway" { name = "sg-test-vpc--appdata-endpoint-gateway" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc_id } -### SG attached to test-vpc/be +### SG test-vpc--be is attached to test-vpc/be resource "ibm_is_security_group" "test-vpc--be" { name = "sg-test-vpc--be" resource_group = local.sg_synth_resource_group_id @@ -32,7 +32,7 @@ resource "ibm_is_security_group_rule" "test-vpc--be-2" { remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id } -### SG attached to test-vpc/fe +### SG test-vpc--fe is attached to test-vpc/fe resource "ibm_is_security_group" "test-vpc--fe" { name = "sg-test-vpc--fe" resource_group = local.sg_synth_resource_group_id @@ -57,7 +57,7 @@ resource "ibm_is_security_group_rule" "test-vpc--fe-1" { } } -### SG attached to test-vpc/opa +### SG test-vpc--opa is attached to test-vpc/opa resource "ibm_is_security_group" "test-vpc--opa" { name = "sg-test-vpc--opa" resource_group = local.sg_synth_resource_group_id @@ -76,7 +76,7 @@ resource "ibm_is_security_group_rule" "test-vpc--opa-1" { remote = ibm_is_security_group.test-vpc--policydb-endpoint-gateway.id } -### SG attached to test-vpc/policydb-endpoint-gateway +### SG test-vpc--policydb-endpoint-gateway is attached to test-vpc/policydb-endpoint-gateway resource "ibm_is_security_group" "test-vpc--policydb-endpoint-gateway" { name = "sg-test-vpc--policydb-endpoint-gateway" resource_group = local.sg_synth_resource_group_id @@ -95,7 +95,7 @@ resource "ibm_is_security_group_rule" "test-vpc--policydb-endpoint-gateway-1" { remote = ibm_is_security_group.test-vpc--opa.id } -### SG attached to test-vpc/proxy +### SG test-vpc--proxy is attached to test-vpc/proxy resource "ibm_is_security_group" "test-vpc--proxy" { name = "sg-test-vpc--proxy" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf index 8f4979ba..1486e315 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc0.tf @@ -1,4 +1,4 @@ -### SG attached to test-vpc0/vsi0-subnet0 +### SG test-vpc0--vsi0-subnet0 is attached to test-vpc0/vsi0-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet0" { name = "sg-test-vpc0--vsi0-subnet0" resource_group = local.sg_synth_resource_group_id @@ -11,70 +11,70 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi0-subnet0-0" { remote = ibm_is_security_group.test-vpc0--vsi1-subnet4.id } -### SG attached to test-vpc0/vsi0-subnet1 +### SG test-vpc0--vsi0-subnet1 is attached to test-vpc0/vsi0-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet1" { name = "sg-test-vpc0--vsi0-subnet1" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi0-subnet2 +### SG test-vpc0--vsi0-subnet2 is attached to test-vpc0/vsi0-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet2" { name = "sg-test-vpc0--vsi0-subnet2" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi0-subnet3 +### SG test-vpc0--vsi0-subnet3 is attached to test-vpc0/vsi0-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet3" { name = "sg-test-vpc0--vsi0-subnet3" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi0-subnet4 +### SG test-vpc0--vsi0-subnet4 is attached to test-vpc0/vsi0-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet4" { name = "sg-test-vpc0--vsi0-subnet4" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi0-subnet5 +### SG test-vpc0--vsi0-subnet5 is attached to test-vpc0/vsi0-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi0-subnet5" { name = "sg-test-vpc0--vsi0-subnet5" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet0 +### SG test-vpc0--vsi1-subnet0 is attached to test-vpc0/vsi1-subnet0 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet0" { name = "sg-test-vpc0--vsi1-subnet0" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet1 +### SG test-vpc0--vsi1-subnet1 is attached to test-vpc0/vsi1-subnet1 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet1" { name = "sg-test-vpc0--vsi1-subnet1" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet2 +### SG test-vpc0--vsi1-subnet2 is attached to test-vpc0/vsi1-subnet2 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet2" { name = "sg-test-vpc0--vsi1-subnet2" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet3 +### SG test-vpc0--vsi1-subnet3 is attached to test-vpc0/vsi1-subnet3 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet3" { name = "sg-test-vpc0--vsi1-subnet3" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc0_id } -### SG attached to test-vpc0/vsi1-subnet4 +### SG test-vpc0--vsi1-subnet4 is attached to test-vpc0/vsi1-subnet4 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet4" { name = "sg-test-vpc0--vsi1-subnet4" resource_group = local.sg_synth_resource_group_id @@ -87,7 +87,7 @@ resource "ibm_is_security_group_rule" "test-vpc0--vsi1-subnet4-0" { remote = ibm_is_security_group.test-vpc0--vsi0-subnet0.id } -### SG attached to test-vpc0/vsi1-subnet5 +### SG test-vpc0--vsi1-subnet5 is attached to test-vpc0/vsi1-subnet5 resource "ibm_is_security_group" "test-vpc0--vsi1-subnet5" { name = "sg-test-vpc0--vsi1-subnet5" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf index 06e11954..9149e693 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc1.tf @@ -1,4 +1,4 @@ -### SG attached to test-vpc1/vsi0-subnet10 +### SG test-vpc1--vsi0-subnet10 is attached to test-vpc1/vsi0-subnet10 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet10" { name = "sg-test-vpc1--vsi0-subnet10" resource_group = local.sg_synth_resource_group_id @@ -13,7 +13,7 @@ resource "ibm_is_security_group_rule" "test-vpc1--vsi0-subnet10-0" { } } -### SG attached to test-vpc1/vsi0-subnet11 +### SG test-vpc1--vsi0-subnet11 is attached to test-vpc1/vsi0-subnet11 resource "ibm_is_security_group" "test-vpc1--vsi0-subnet11" { name = "sg-test-vpc1--vsi0-subnet11" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf index bf96f422..7adad885 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc2.tf @@ -1,4 +1,4 @@ -### SG attached to test-vpc2/vsi0-subnet20 +### SG test-vpc2--vsi0-subnet20 is attached to test-vpc2/vsi0-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi0-subnet20" { name = "sg-test-vpc2--vsi0-subnet20" resource_group = local.sg_synth_resource_group_id @@ -15,14 +15,14 @@ resource "ibm_is_security_group_rule" "test-vpc2--vsi0-subnet20-0" { } } -### SG attached to test-vpc2/vsi1-subnet20 +### SG test-vpc2--vsi1-subnet20 is attached to test-vpc2/vsi1-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi1-subnet20" { name = "sg-test-vpc2--vsi1-subnet20" resource_group = local.sg_synth_resource_group_id vpc = local.sg_synth_test-vpc2_id } -### SG attached to test-vpc2/vsi2-subnet20 +### SG test-vpc2--vsi2-subnet20 is attached to test-vpc2/vsi2-subnet20 resource "ibm_is_security_group" "test-vpc2--vsi2-subnet20" { name = "sg-test-vpc2--vsi2-subnet20" resource_group = local.sg_synth_resource_group_id diff --git a/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf b/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf index ef77175b..312dad54 100644 --- a/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf +++ b/test/expected/sg_tg_multiple_tf_separate/test-vpc3.tf @@ -1,4 +1,4 @@ -### SG attached to test-vpc3/vsi0-subnet30 +### SG test-vpc3--vsi0-subnet30 is attached to test-vpc3/vsi0-subnet30 resource "ibm_is_security_group" "test-vpc3--vsi0-subnet30" { name = "sg-test-vpc3--vsi0-subnet30" resource_group = local.sg_synth_resource_group_id From 5616f9ed4a6e86baeaf87ac4702a08a6534f278e Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 21 Oct 2024 11:41:20 +0300 Subject: [PATCH 74/79] fixed --- cmd/subcmds/output.go | 8 ++---- pkg/io/confio/optimizeSG.go | 57 +++++++++++++++++++++++++++++++++++++ pkg/io/confio/sg.go | 29 +++++++++++++------ pkg/synth/sg.go | 11 ++----- 4 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 pkg/io/confio/optimizeSG.go diff --git a/cmd/subcmds/output.go b/cmd/subcmds/output.go index 97acf01a..569d33e3 100644 --- a/cmd/subcmds/output.go +++ b/cmd/subcmds/output.go @@ -60,7 +60,7 @@ func writeOutput(args *inArgs, collection ir.Collection, vpcNames []string, isSy func writeCollection(args *inArgs, collection ir.Collection, vpc string, isSynth bool) (*bytes.Buffer, error) { var data bytes.Buffer - writer, err := pickWriter(args, &data, isSynth) + writer, err := pickWriter(args, &data) if err != nil { return nil, err } @@ -70,7 +70,7 @@ func writeCollection(args *inArgs, collection ir.Collection, vpc string, isSynth return &data, nil } -func pickWriter(args *inArgs, data *bytes.Buffer, isSynth bool) (ir.Writer, error) { +func pickWriter(args *inArgs, data *bytes.Buffer) (ir.Writer, error) { w := bufio.NewWriter(data) switch args.outputFmt { case tfOutputFormat: @@ -80,9 +80,7 @@ func pickWriter(args *inArgs, data *bytes.Buffer, isSynth bool) (ir.Writer, erro case mdOutputFormat: return io.NewMDWriter(w), nil case jsonOutputFormat: - if isSynth { - return confio.NewWriter(w, args.configFile) - } + return confio.NewWriter(w, args.configFile) } return nil, fmt.Errorf("bad output format: %q", args.outputFmt) } diff --git a/pkg/io/confio/optimizeSG.go b/pkg/io/confio/optimizeSG.go new file mode 100644 index 00000000..2c7f0851 --- /dev/null +++ b/pkg/io/confio/optimizeSG.go @@ -0,0 +1,57 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package confio + +import ( + "github.com/IBM/vpc-go-sdk/vpcv1" + + configModel "github.com/np-guard/cloud-resource-collector/pkg/ibm/datamodel" + + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +// updateSGs updates the config object file with the optimized SG rules +func updateSGs(model *configModel.ResourcesContainerModel, collection *ir.SGCollection) error { + sgRefMap := parseSGRefMap(model) + for _, sg := range model.SecurityGroupList { + if sg.Name == nil || sg.VPC == nil || sg.VPC.Name == nil { + continue + } + if err := updateSG(&sg.SecurityGroup, collection.SGs[*sg.VPC.Name][ir.SGName(*sg.Name)], sgRefMap); err != nil { + return err + } + } + return nil +} + +func updateSG(sg *vpcv1.SecurityGroup, optimizedSG *ir.SG, sgRefMap map[string]*vpcv1.SecurityGroupRuleRemoteSecurityGroupReference) error { + optimizedRules := optimizedSG.AllRules() + if len(optimizedRules) == len(sg.Rules) { + return nil + } + sg.Rules = make([]vpcv1.SecurityGroupRuleIntf, len(optimizedRules)) + for i, rule := range optimizedRules { + r, err := makeSGRuleItem(sgRefMap, rule, i) + if err != nil { + return err + } + sg.Rules[i] = r + } + return nil +} + +func parseSGRefMap(model *configModel.ResourcesContainerModel) map[string]*vpcv1.SecurityGroupRuleRemoteSecurityGroupReference { + res := make(map[string]*vpcv1.SecurityGroupRuleRemoteSecurityGroupReference) + for _, sg := range model.SecurityGroupList { + res[*sg.Name] = &vpcv1.SecurityGroupRuleRemoteSecurityGroupReference{ + ID: sg.ID, + CRN: sg.CRN, + Href: sg.Href, + Name: sg.Name, + } + } + return res +} diff --git a/pkg/io/confio/sg.go b/pkg/io/confio/sg.go index 90f1fd4f..fbbdd9f8 100644 --- a/pkg/io/confio/sg.go +++ b/pkg/io/confio/sg.go @@ -54,7 +54,7 @@ func sgRemote(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteSecurit st := rule.Remote.String() switch t := rule.Remote.(type) { case *netset.IPBlock: - if ipString := t.ToIPAddressString(); ipString != "" { // single IP address + if t.IsSingleIPAddress() { // single IP address return &vpcv1.SecurityGroupRuleRemoteIP{ Address: &st, } @@ -72,13 +72,20 @@ func makeSGRuleItem(nameToSGRemoteRef map[string]*vpcv1.SecurityGroupRuleRemoteS rule *ir.SGRule, i int) (vpcv1.SecurityGroupRuleIntf, error) { iPVersion := utils.Ptr(ipv4Const) direction := direction(rule.Direction) - cidrAll := netset.CidrAll - local := &vpcv1.SecurityGroupRuleLocal{ - CIDRBlock: &cidrAll, - } ref := allocateRef() remote := sgRemote(nameToSGRemoteRef, rule) + var local vpcv1.SecurityGroupRuleLocalIntf + if rule.Local.IsSingleIPAddress() { + local = &vpcv1.SecurityGroupRuleLocalIP{ + Address: utils.Ptr(rule.Local.FirstIPAddress()), + } + } else { + local = &vpcv1.SecurityGroupRuleLocalCIDR{ + CIDRBlock: utils.Ptr(rule.Local.ToCidrList()[0]), + } + } + switch p := rule.Protocol.(type) { case netp.TCPUDP: data := tcpudp(p) @@ -245,7 +252,7 @@ func updateSGEndpointGW(model *configModel.ResourcesContainerModel, collection * return nil } -func updateSG(model *configModel.ResourcesContainerModel, collection *ir.SGCollection) error { +func writeSGs(model *configModel.ResourcesContainerModel, collection *ir.SGCollection) error { nameToSGRemoteRef := make(map[string]*vpcv1.SecurityGroupRuleRemoteSecurityGroupReference) idToSGIndex := make(map[string]int, len(model.SecurityGroupList)) for i := range model.SecurityGroupList { @@ -254,13 +261,19 @@ func updateSG(model *configModel.ResourcesContainerModel, collection *ir.SGColle err1 := updateSGInstances(model, collection, nameToSGRemoteRef, idToSGIndex) err2 := updateSGEndpointGW(model, collection, nameToSGRemoteRef, idToSGIndex) - globalIndex = 0 // making test results more predictable return errors.Join(err1, err2) } func (w *Writer) WriteSG(collection *ir.SGCollection, _ string, isSynth bool) error { - if err := updateSG(w.model, collection); err != nil { + var err error + if isSynth { + err = writeSGs(w.model, collection) + } else { + err = updateSGs(w.model, collection) + } + if err != nil { return err } + globalIndex = 0 // making test results more predictable return w.writeModel() } diff --git a/pkg/synth/sg.go b/pkg/synth/sg.go index 4ffd887b..732303a1 100644 --- a/pkg/synth/sg.go +++ b/pkg/synth/sg.go @@ -9,6 +9,7 @@ import ( "fmt" "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" ) @@ -77,7 +78,7 @@ func (s *SGSynthesizer) generateSGRulesFromConnection(conn *ir.Connection) error } // if the endpoint in internal, a rule will be created to allow traffic. -func (s *SGSynthesizer) allowConnectionEndpoint(localEndpoint, remoteEndpoint *namedAddrs, protocol netp.Protocol, +func (s *SGSynthesizer) allowConnectionEndpoint(localEndpoint, remoteEndpoint *namedAddrs, p netp.Protocol, direction ir.Direction, internalEndpoint bool, ruleExplanation string) { if !internalEndpoint { return @@ -85,13 +86,7 @@ func (s *SGSynthesizer) allowConnectionEndpoint(localEndpoint, remoteEndpoint *n localSGName := ir.SGName(localEndpoint.Name) localSG := s.result.LookupOrCreate(localSGName) localSG.Targets = []ir.ID{ir.ID(localSGName)} - rule := &ir.SGRule{ - Remote: sgRemote(&s.spec.Defs, remoteEndpoint), - Direction: direction, - Protocol: protocol, - Explanation: ruleExplanation, - } - localSG.Add(rule) + localSG.Add(ir.NewSGRule(direction, sgRemote(&s.spec.Defs, remoteEndpoint), p, netset.GetCidrAll(), ruleExplanation)) } // generate SGs for blocked endpoints (endpoints that do not appear in Spec) From 93f805c26e3fe100c7b3c22b15849b1e04e34135 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Mon, 21 Oct 2024 11:52:58 +0300 Subject: [PATCH 75/79] added a test --- .../sg_expected.json | 2029 +++++++++++++++++ test/main_test_list.go | 9 + 2 files changed, 2038 insertions(+) create mode 100644 test/expected/optimize_sg_protocols_to_all_json/sg_expected.json diff --git a/test/expected/optimize_sg_protocols_to_all_json/sg_expected.json b/test/expected/optimize_sg_protocols_to_all_json/sg_expected.json new file mode 100644 index 00000000..34f2e08d --- /dev/null +++ b/test/expected/optimize_sg_protocols_to_all_json/sg_expected.json @@ -0,0 +1,2029 @@ +{ + "collector_version": "0.11.0", + "provider": "ibm", + "vpcs": [ + { + "classic_access": false, + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:1", + "cse_source_ips": [ + { + "ip": { + "address": "10.22.217.112" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "ip": { + "address": "10.12.160.153" + }, + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "ip": { + "address": "10.16.253.223" + }, + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "default_network_acl": { + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail" + }, + "default_routing_table": { + "crn": null, + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "default_security_group": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "dns": { + "enable_hub": false, + "resolution_binding_count": 0, + "resolver": { + "servers": [ + { + "address": "161.26.0.10" + }, + { + "address": "161.26.0.11" + } + ], + "type": "system", + "configuration": "default" + } + }, + "health_reasons": null, + "health_state": "ok", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "vpc", + "status": "available", + "region": "us-south", + "address_prefixes": [ + { + "cidr": "10.240.0.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": true, + "href": "href:18", + "id": "id:19", + "is_default": true, + "name": "filling-tasty-bacterium-parlor", + "zone": { + "href": "href:5", + "name": "us-south-1" + } + }, + { + "cidr": "10.240.64.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:20", + "id": "id:21", + "is_default": true, + "name": "relearn-ragweed-goon-feisty", + "zone": { + "href": "href:6", + "name": "us-south-2" + } + }, + { + "cidr": "10.240.128.0/18", + "created_at": "2024-09-09T09:09:50.000Z", + "has_subnets": false, + "href": "href:22", + "id": "id:23", + "is_default": true, + "name": "unruffled-penknife-snowshoe-ninetieth", + "zone": { + "href": "href:7", + "name": "us-south-3" + } + } + ], + "tags": [] + } + ], + "subnets": [ + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:51.000Z", + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.20.0/24", + "name": "subnet2", + "network_acl": { + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "crn": null, + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.20.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:33", + "id": "id:34", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:35", + "id": "id:36", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:37", + "id": "id:38", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:39", + "id": "id:40", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.20.4", + "auto_delete": true, + "created_at": "2024-09-09T09:11:08.000Z", + "href": "href:41", + "id": "id:42", + "lifecycle_state": "stable", + "name": "startle-percent-embellish-squeegee", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.20.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:51.000Z", + "href": "href:45", + "id": "id:46", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 250, + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.10.0/24", + "name": "subnet1", + "network_acl": { + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1" + }, + "public_gateway": { + "crn": "crn:30", + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "crn": null, + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.10.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:53", + "id": "id:54", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:55", + "id": "id:56", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:57", + "id": "id:58", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:59", + "id": "id:60", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.10.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:52.000Z", + "href": "href:61", + "id": "id:62", + "lifecycle_state": "stable", + "name": "tableware-sprawl-shrivel-popper", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.10.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:65", + "id": "id:66", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + }, + { + "available_ipv4_address_count": 249, + "created_at": "2024-09-09T09:10:18.000Z", + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "ip_version": "ipv4", + "ipv4_cidr_block": "10.240.30.0/24", + "name": "subnet3", + "network_acl": { + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3" + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "subnet", + "routing_table": { + "crn": null, + "href": "href:11", + "id": "id:12", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_type": "routing_table" + }, + "status": "available", + "total_ipv4_address_count": 256, + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "reserved_ips": [ + { + "address": "10.240.30.0", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:73", + "id": "id:74", + "lifecycle_state": "stable", + "name": "ibm-network-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.1", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:75", + "id": "id:76", + "lifecycle_state": "stable", + "name": "ibm-default-gateway", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.2", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:77", + "id": "id:78", + "lifecycle_state": "stable", + "name": "ibm-dns-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.3", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:79", + "id": "id:80", + "lifecycle_state": "stable", + "name": "ibm-reserved-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + }, + { + "address": "10.240.30.4", + "auto_delete": true, + "created_at": "2024-09-09T09:10:35.000Z", + "href": "href:81", + "id": "id:82", + "lifecycle_state": "stable", + "name": "disallow-oxidant-etching-selection", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.5", + "auto_delete": true, + "created_at": "2024-09-09T09:10:36.000Z", + "href": "href:85", + "id": "id:86", + "lifecycle_state": "stable", + "name": "reheat-joyride-little-overprice", + "owner": "user", + "resource_type": "subnet_reserved_ip", + "target": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + }, + { + "address": "10.240.30.255", + "auto_delete": false, + "created_at": "2024-09-09T09:10:18.000Z", + "href": "href:89", + "id": "id:90", + "lifecycle_state": "stable", + "name": "ibm-broadcast-address", + "owner": "provider", + "resource_type": "subnet_reserved_ip" + } + ], + "tags": [] + } + ], + "public_gateways": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:30", + "floating_ip": { + "address": "52.118.147.142", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1" + }, + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "public_gateway", + "status": "available", + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "floating_ips": [ + { + "address": "52.116.129.168", + "created_at": "2024-09-09T09:11:31.000Z", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + }, + { + "address": "52.118.147.142", + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:91", + "href": "href:92", + "id": "id:93", + "name": "public-gw1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "status": "available", + "target": { + "href": "href:31", + "id": "id:32", + "name": "public-gw1", + "resource_type": "public_gateway", + "crn": "crn:30" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "tags": [] + } + ], + "network_acls": [ + { + "created_at": "2024-09-09T09:10:15.000Z", + "crn": "crn:27", + "href": "href:28", + "id": "id:29", + "name": "acl2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:99", + "id": "id:100", + "name": "acl2-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:97", + "id": "id:98", + "ip_version": "ipv4", + "name": "acl2-out-1", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:101", + "id": "id:102", + "name": "acl2-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:99", + "id": "id:100", + "ip_version": "ipv4", + "name": "acl2-out-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:103", + "id": "id:104", + "name": "acl2-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:101", + "id": "id:102", + "ip_version": "ipv4", + "name": "acl2-in-1", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.20.0/24", + "direction": "inbound", + "href": "href:103", + "id": "id:104", + "ip_version": "ipv4", + "name": "acl2-in-2", + "source": "10.240.10.0/24", + "protocol": "all" + } + ], + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:50", + "href": "href:51", + "id": "id:52", + "name": "acl1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:107", + "id": "id:108", + "name": "acl1-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "172.217.22.46/32", + "direction": "outbound", + "href": "href:105", + "id": "id:106", + "ip_version": "ipv4", + "name": "acl1-out-1", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:109", + "id": "id:110", + "name": "acl1-out-3" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.20.0/24", + "direction": "outbound", + "href": "href:107", + "id": "id:108", + "ip_version": "ipv4", + "name": "acl1-out-2", + "source": "10.240.10.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:111", + "id": "id:112", + "name": "acl1-out-4" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:109", + "id": "id:110", + "ip_version": "ipv4", + "name": "acl1-out-3", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:113", + "id": "id:114", + "name": "acl1-in-1" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "outbound", + "href": "href:111", + "id": "id:112", + "ip_version": "ipv4", + "name": "acl1-out-4", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:115", + "id": "id:116", + "name": "acl1-in-2" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:113", + "id": "id:114", + "ip_version": "ipv4", + "name": "acl1-in-1", + "source": "172.217.22.46/32", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:117", + "id": "id:118", + "name": "acl1-in-3" + }, + "created_at": "2024-09-09T09:10:17.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:115", + "id": "id:116", + "ip_version": "ipv4", + "name": "acl1-in-2", + "source": "10.240.20.0/24", + "protocol": "all" + }, + { + "action": "allow", + "before": { + "href": "href:119", + "id": "id:120", + "name": "acl1-in-4" + }, + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:117", + "id": "id:118", + "ip_version": "ipv4", + "name": "acl1-in-3", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:18.000Z", + "destination": "10.240.10.0/24", + "direction": "inbound", + "href": "href:119", + "id": "id:120", + "ip_version": "ipv4", + "name": "acl1-in-4", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + } + ], + "subnets": [ + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:70", + "href": "href:71", + "id": "id:72", + "name": "acl3", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:123", + "id": "id:124", + "name": "acl3-out-2" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:121", + "id": "id:122", + "ip_version": "ipv4", + "name": "acl3-out-1", + "source": "10.240.30.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "before": { + "href": "href:125", + "id": "id:126", + "name": "acl3-in-1" + }, + "created_at": "2024-09-09T09:10:15.000Z", + "destination": "10.240.10.0/24", + "direction": "outbound", + "href": "href:123", + "id": "id:124", + "ip_version": "ipv4", + "name": "acl3-out-2", + "source": "10.240.30.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + }, + { + "action": "allow", + "before": { + "href": "href:127", + "id": "id:128", + "name": "acl3-in-2" + }, + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:125", + "id": "id:126", + "ip_version": "ipv4", + "name": "acl3-in-1", + "source": "10.240.10.0/24", + "destination_port_max": 443, + "destination_port_min": 443, + "protocol": "tcp", + "source_port_max": 65535, + "source_port_min": 1 + }, + { + "action": "allow", + "created_at": "2024-09-09T09:10:16.000Z", + "destination": "10.240.30.0/24", + "direction": "inbound", + "href": "href:127", + "id": "id:128", + "ip_version": "ipv4", + "name": "acl3-in-2", + "source": "10.240.10.0/24", + "destination_port_max": 65535, + "destination_port_min": 1, + "protocol": "tcp", + "source_port_max": 443, + "source_port_min": 443 + } + ], + "subnets": [ + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:8", + "href": "href:9", + "id": "id:10", + "name": "capitol-siren-chirpy-doornail", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "action": "allow", + "before": { + "href": "href:131", + "id": "id:132", + "name": "allow-outbound" + }, + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "inbound", + "href": "href:129", + "id": "id:130", + "ip_version": "ipv4", + "name": "allow-inbound", + "source": "0.0.0.0/0", + "protocol": "all" + }, + { + "action": "allow", + "created_at": "2024-09-09T09:09:50.000Z", + "destination": "0.0.0.0/0", + "direction": "outbound", + "href": "href:131", + "id": "id:132", + "ip_version": "ipv4", + "name": "allow-outbound", + "source": "0.0.0.0/0", + "protocol": "all" + } + ], + "subnets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "security_groups": [ + { + "created_at": "2024-09-09T09:10:14.000Z", + "crn": "crn:133", + "href": "href:134", + "id": "id:135", + "name": "sg1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "href:136", + "id": "id:137", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "href:138", + "id": "id:139", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": "2024-09-09T09:09:50.000Z", + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "href:140", + "id": "id:141", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/0" + }, + "protocol": "all" + }, + { + "direction": "inbound", + "href": "href:142", + "id": "id:143", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "crn:13", + "href": "href:14", + "id": "id:15", + "name": "wombat-hesitate-scorn-subprime" + }, + "protocol": "all" + } + ], + "targets": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "inbound", + "href": "fake:href:1", + "id": "fake:id:1", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + }, + "protocol": "all" + } + ], + "targets": [ + { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [ + { + "direction": "outbound", + "href": "fake:href:2", + "id": "fake:id:2", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + }, + "protocol": "all" + }, + { + "direction": "outbound", + "href": "fake:href:3", + "id": "fake:id:3", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/30" + }, + "protocol": "icmp" + }, + { + "direction": "outbound", + "href": "fake:href:4", + "id": "fake:id:4", + "ip_version": "ipv4", + "local": { + "cidr_block": "0.0.0.0/0" + }, + "remote": { + "cidr_block": "0.0.0.0/31" + }, + "protocol": "all" + } + ], + "targets": [ + { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:18", + "href": "fake:href:18", + "id": "fake:id:18", + "name": "test-vpc1--vsi3b", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + }, + { + "created_at": null, + "crn": "fake:crn:19", + "href": "fake:href:19", + "id": "fake:id:19", + "name": "test-vpc1--vsi3a", + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "rules": [], + "targets": [ + { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "resource_type": "network_interface" + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "tags": [] + } + ], + "endpoint_gateways": [], + "instances": [ + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:11:07.000Z", + "crn": "crn:144", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:145", + "id": "id:146", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi2", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:43", + "id": "id:44", + "name": "ni2", + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:149" + }, + "href": "href:147", + "id": "id:148", + "name": "falsetto-snowstorm-bankbook-agreement", + "volume": { + "crn": "crn:150", + "href": "href:151", + "id": "id:152", + "name": "prawn-trusting-pasty-dental", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:11:07.000Z", + "floating_ips": [], + "href": "href:43", + "id": "id:44", + "name": "ni2", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.20.4", + "href": "href:41", + "id": "id:42", + "name": "startle-percent-embellish-squeegee", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:7", + "href": "fake:href:7", + "id": "fake:id:7", + "name": "test-vpc1--vsi2" + } + ], + "status": "available", + "subnet": { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:52.000Z", + "crn": "crn:157", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:158", + "id": "id:159", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi1", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:63", + "id": "id:64", + "name": "ni1", + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:162" + }, + "href": "href:160", + "id": "id:161", + "name": "outskirts-oversized-roundish-ludicrous", + "volume": { + "crn": "crn:163", + "href": "href:164", + "id": "id:165", + "name": "family-tackling-foothold-train", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:52.000Z", + "floating_ips": [ + { + "address": "52.116.129.168", + "crn": "crn:94", + "href": "href:95", + "id": "id:96", + "name": "vsi1-fip" + } + ], + "href": "href:63", + "id": "id:64", + "name": "ni1", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.10.4", + "href": "href:61", + "id": "id:62", + "name": "tableware-sprawl-shrivel-popper", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:2", + "href": "fake:href:2", + "id": "fake:id:2", + "name": "test-vpc1--vsi1" + } + ], + "status": "available", + "subnet": { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:35.000Z", + "crn": "crn:166", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:167", + "id": "id:168", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3b", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:171" + }, + "href": "href:169", + "id": "id:170", + "name": "camera-yam-headfirst-scabiosa", + "volume": { + "crn": "crn:172", + "href": "href:173", + "id": "id:174", + "name": "sprinkler-avenue-playset-dislodge", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:87", + "id": "id:88", + "name": "ni3b", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.5", + "href": "href:85", + "id": "id:86", + "name": "reheat-joyride-little-overprice", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:18", + "href": "fake:href:18", + "id": "fake:id:18", + "name": "test-vpc1--vsi3b" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + }, + { + "availability_policy": { + "host_failure": "restart" + }, + "bandwidth": 4000, + "boot_volume_attachment": { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + }, + "confidential_compute_mode": "disabled", + "created_at": "2024-09-09T09:10:34.000Z", + "crn": "crn:175", + "disks": [], + "enable_secure_boot": false, + "health_reasons": [], + "health_state": "ok", + "href": "href:176", + "id": "id:177", + "image": { + "crn": "crn:153", + "href": "href:154", + "id": "id:155", + "name": "server-9080", + "resource_type": "image" + }, + "lifecycle_reasons": [], + "lifecycle_state": "stable", + "memory": 4, + "metadata_service": { + "enabled": false, + "protocol": "http", + "response_hop_limit": 1 + }, + "name": "vsi3a", + "network_attachments": [], + "numa_count": 1, + "primary_network_interface": { + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + }, + "profile": { + "href": "href:156", + "name": "cx2-2x4", + "resource_type": "instance_profile" + }, + "reservation_affinity": { + "policy": "disabled", + "pool": [] + }, + "resource_group": { + "href": "href:16", + "id": "id:17", + "name": "name:4" + }, + "resource_type": "instance", + "startable": true, + "status": "running", + "status_reasons": [], + "total_network_bandwidth": 3000, + "total_volume_bandwidth": 1000, + "vcpu": { + "architecture": "amd64", + "count": 2, + "manufacturer": "intel" + }, + "volume_attachments": [ + { + "device": { + "id": "id:180" + }, + "href": "href:178", + "id": "id:179", + "name": "cryptic-cork-saponify-lively", + "volume": { + "crn": "crn:181", + "href": "href:182", + "id": "id:183", + "name": "appraisal-mountains-itinerary-twine", + "resource_type": "volume" + } + } + ], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + }, + "zone": { + "href": "href:5", + "name": "us-south-1" + }, + "network_interfaces": [ + { + "allow_ip_spoofing": false, + "created_at": "2024-09-09T09:10:34.000Z", + "floating_ips": [], + "href": "href:83", + "id": "id:84", + "name": "ni3a", + "port_speed": 3000, + "primary_ip": { + "address": "10.240.30.4", + "href": "href:81", + "id": "id:82", + "name": "disallow-oxidant-etching-selection", + "resource_type": "subnet_reserved_ip" + }, + "resource_type": "network_interface", + "security_groups": [ + { + "crn": "fake:crn:19", + "href": "fake:href:19", + "id": "fake:id:19", + "name": "test-vpc1--vsi3a" + } + ], + "status": "available", + "subnet": { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + }, + "type": "primary" + } + ], + "tags": [] + } + ], + "virtual_nis": null, + "routing_tables": [ + { + "accept_routes_from": [ + { + "resource_type": "vpn_gateway" + }, + { + "resource_type": "vpn_server" + } + ], + "advertise_routes_to": [], + "created_at": "2024-09-09T09:09:51.000Z", + "crn": null, + "href": "href:11", + "id": "id:12", + "is_default": true, + "lifecycle_state": "stable", + "name": "fiscally-fresh-uncanny-ceramics", + "resource_group": null, + "resource_type": "routing_table", + "route_direct_link_ingress": false, + "route_internet_ingress": false, + "route_transit_gateway_ingress": false, + "route_vpc_zone_ingress": false, + "subnets": [ + { + "crn": "crn:24", + "href": "href:25", + "id": "id:26", + "name": "subnet2", + "resource_type": "subnet" + }, + { + "crn": "crn:47", + "href": "href:48", + "id": "id:49", + "name": "subnet1", + "resource_type": "subnet" + }, + { + "crn": "crn:67", + "href": "href:68", + "id": "id:69", + "name": "subnet3", + "resource_type": "subnet" + } + ], + "routes": [], + "vpc": { + "crn": "crn:1", + "href": "href:2", + "id": "id:3", + "name": "test-vpc1", + "resource_type": "vpc" + } + } + ], + "load_balancers": [], + "transit_connections": null, + "transit_gateways": null, + "iks_clusters": [] +} \ No newline at end of file diff --git a/test/main_test_list.go b/test/main_test_list.go index f9d63166..d6883aba 100644 --- a/test/main_test_list.go +++ b/test/main_test_list.go @@ -336,6 +336,15 @@ func optimizeSGTestsLists() []testCase { outputFile: "%s/optimize_sg_protocols_to_all_csv/sg_expected.csv", }, }, + { + testName: "optimize_sg_protocols_to_all_json", + args: &command{ + cmd: optimize, + subcmd: sg, + config: optimizeSGProtocolsToAllConfig, + outputFile: "%s/optimize_sg_protocols_to_all_json/sg_expected.json", + }, + }, { testName: "optimize_sg_protocols_to_all_md", args: &command{ From 3ec4c70810d4810d6b37d31ce5fab1e28623fee3 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 22 Oct 2024 13:13:00 +0300 Subject: [PATCH 76/79] fixed --- pkg/io/confio/parse_sgs.go | 35 ++++++++-------------- pkg/ir/sg.go | 29 +++++++++++++------ pkg/optimize/sg/ipCubesToRules.go | 30 ++++++++++--------- pkg/optimize/sg/sg.go | 48 +++++++++++++++++-------------- pkg/optimize/sg/sgCubesToRules.go | 12 ++++---- 5 files changed, 82 insertions(+), 72 deletions(-) diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index 5b0cdc95..f39f890d 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -27,14 +27,14 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { result := ir.NewSGCollection() for i, sg := range config.SecurityGroupList { - inbound, outbound, err := translateSGRules(&sg.SecurityGroup) - if err != nil { - return nil, err - } if sg.Name == nil || sg.VPC == nil || sg.VPC.Name == nil { log.Printf("Warning: missing SG/VPC name in sg at index %d\n", i) continue } + inbound, outbound, err := translateSGRules(&sg.SecurityGroup) + if err != nil { + return nil, err + } vpcName := *sg.VPC.Name if result.SGs[vpcName] == nil { result.SGs[vpcName] = make(map[ir.SGName]*ir.SG) @@ -49,16 +49,19 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { } // parse security rules, splitted into ingress and egress rules -func translateSGRules(sg *vpcv1.SecurityGroup) (ingressRules, egressRules []*ir.SGRule, err error) { +func translateSGRules(sg *vpcv1.SecurityGroup) (ingressRules, egressRules map[string][]*ir.SGRule, err error) { + ingressRules = make(map[string][]*ir.SGRule) + egressRules = make(map[string][]*ir.SGRule) for index := range sg.Rules { rule, err := translateSGRule(sg, index) if err != nil { return nil, nil, err } + local := rule.Local.String() if rule.Direction == ir.Inbound { - ingressRules = append(ingressRules, rule) + ingressRules[local] = append(ingressRules[local], rule) } else { - egressRules = append(egressRules, rule) + egressRules[local] = append(egressRules[local], rule) } } return ingressRules, egressRules, nil @@ -157,19 +160,13 @@ func translateRemote(remote vpcv1.SecurityGroupRuleRemoteIntf) (ir.RemoteType, e } func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, error) { - var err error - var ipAddrs *netset.IPBlock if l, ok := local.(*vpcv1.SecurityGroupRuleLocal); ok { if l.CIDRBlock != nil { - ipAddrs, err = netset.IPBlockFromCidr(*l.CIDRBlock) + return netset.IPBlockFromCidr(*l.CIDRBlock) } if l.Address != nil { - ipAddrs, err = netset.IPBlockFromIPAddress(*l.CIDRBlock) - } - if err != nil { - return nil, err + return netset.IPBlockFromIPAddress(*l.Address) } - return verifyLocalValue(ipAddrs) } return nil, fmt.Errorf("error parsing Local field") } @@ -190,14 +187,6 @@ func transalteTargets(sg *vpcv1.SecurityGroup) []string { return res } -// temporary - first version of optimization requires local = 0.0.0.0/32 -func verifyLocalValue(ipAddrs *netset.IPBlock) (*netset.IPBlock, error) { - if !ipAddrs.Equal(netset.GetCidrAll()) { - return nil, fmt.Errorf("only 0.0.0.0/32 CIDR block is supported for local values") - } - return ipAddrs, nil -} - func translateProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (netp.Protocol, error) { isTCP := *rule.Protocol == vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudpProtocolTCPConst minDstPort := utils.GetProperty(rule.PortMin, netp.MinPort) diff --git a/pkg/ir/sg.go b/pkg/ir/sg.go index 4ee2dd10..3a1957c3 100644 --- a/pkg/ir/sg.go +++ b/pkg/ir/sg.go @@ -44,8 +44,8 @@ type ( SG struct { SGName SGName - InboundRules []*SGRule - OutboundRules []*SGRule + InboundRules map[string][]*SGRule // the key is the locals value + OutboundRules map[string][]*SGRule // the key is the locals value Targets []ID } @@ -85,7 +85,11 @@ func NewSGRule(direction Direction, remote RemoteType, p netp.Protocol, local *n } func NewSG(sgName SGName) *SG { - return &SG{SGName: sgName, InboundRules: []*SGRule{}, OutboundRules: []*SGRule{}, Targets: []ID{}} + return &SG{SGName: sgName, + InboundRules: make(map[string][]*SGRule), + OutboundRules: make(map[string][]*SGRule), + Targets: []ID{}, + } } func NewSGCollection() *SGCollection { @@ -106,16 +110,25 @@ func (c *SGCollection) LookupOrCreate(name SGName) *SG { } func (a *SG) Add(rule *SGRule) { - if rule.Direction == Outbound && !rule.isRedundant(a.OutboundRules) { - a.OutboundRules = append(a.OutboundRules, rule) + local := rule.Local.String() + if rule.Direction == Outbound && !rule.isRedundant(a.OutboundRules[local]) { + a.OutboundRules[local] = append(a.OutboundRules[local], rule) } - if rule.Direction == Inbound && !rule.isRedundant(a.InboundRules) { - a.InboundRules = append(a.InboundRules, rule) + + if rule.Direction == Inbound && !rule.isRedundant(a.InboundRules[local]) { + a.InboundRules[local] = append(a.InboundRules[local], rule) } } func (a *SG) AllRules() []*SGRule { - return append(a.InboundRules, a.OutboundRules...) + res := make([]*SGRule, 0) + for _, key := range utils.SortedMapKeys(a.InboundRules) { + res = append(res, a.InboundRules[key]...) + } + for _, key := range utils.SortedMapKeys(a.OutboundRules) { + res = append(res, a.OutboundRules[key]...) + } + return res } func (c *SGCollection) VpcNames() []string { diff --git a/pkg/optimize/sg/ipCubesToRules.go b/pkg/optimize/sg/ipCubesToRules.go index f7b41bcf..40106f14 100644 --- a/pkg/optimize/sg/ipCubesToRules.go +++ b/pkg/optimize/sg/ipCubesToRules.go @@ -17,17 +17,17 @@ import ( // all protocol cubes, represented by a single ipblock that will be decomposed // into cidrs. Each cidr will be the remote of a SG rule -func allProtocolIPCubesIPToRules(cubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { +func allProtocolIPCubesIPToRules(cubes *netset.IPBlock, direction ir.Direction, l *netset.IPBlock) []*ir.SGRule { result := make([]*ir.SGRule, 0) for _, cidr := range cubes.SplitToCidrs() { - result = append(result, ir.NewSGRule(direction, cidr, netp.AnyProtocol{}, netset.GetCidrAll(), "")) + result = append(result, ir.NewSGRule(direction, cidr, netp.AnyProtocol{}, l, "")) } return result } // tcpudpIPCubesToRules converts cubes representing tcp or udp protocol rules to SG rules func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.PortSet], allCubes *netset.IPBlock, direction ir.Direction, - isTCP bool) []*ir.SGRule { + isTCP bool, l *netset.IPBlock) []*ir.SGRule { if len(cubes) == 0 { return []*ir.SGRule{} } @@ -38,7 +38,7 @@ func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.PortSet], all for i := range cubes { // if it is not possible to continue the rule between the cubes, generate all the existing rules if i > 0 && !continuation(cubes[i-1], cubes[i], allCubes) { - result = append(result, createActiveRules(activeRules, cubes[i-1].Left.LastIPAddressObject(), direction)...) + result = append(result, createActiveRules(activeRules, cubes[i-1].Left.LastIPAddressObject(), direction, l)...) activeRules = make(map[*netset.IPBlock]netp.Protocol) } @@ -48,7 +48,7 @@ func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.PortSet], all for ipb, protocol := range activeRules { if tcpudp, ok := protocol.(netp.TCPUDP); ok { if !tcpudp.DstPorts().ToSet().IsSubset(cubes[i].Right) { - result = append(result, createNewRules(protocol, ipb, cubes[i-1].Left.LastIPAddressObject(), direction)...) + result = append(result, createNewRules(protocol, ipb, cubes[i-1].Left.LastIPAddressObject(), direction, l)...) } else { activePorts.AddInterval(tcpudp.DstPorts()) } @@ -64,11 +64,12 @@ func tcpudpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.PortSet], all } } // generate all the existing rules - return append(result, createActiveRules(activeRules, cubes[len(cubes)-1].Left.LastIPAddressObject(), direction)...) + return append(result, createActiveRules(activeRules, cubes[len(cubes)-1].Left.LastIPAddressObject(), direction, l)...) } // icmpIPCubesToRules converts cubes representing icmp protocol rules to SG rules -func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCubes *netset.IPBlock, direction ir.Direction) []*ir.SGRule { +func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCubes *netset.IPBlock, direction ir.Direction, + l *netset.IPBlock) []*ir.SGRule { if len(cubes) == 0 { return []*ir.SGRule{} } @@ -79,7 +80,7 @@ func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCu for i := range cubes { // if it is not possible to continue the rule between the cubes, generate all the existing rules if i > 0 && !continuation(cubes[i-1], cubes[i], allCubes) { - result = append(result, createActiveRules(activeRules, cubes[i-1].Left.LastIPAddressObject(), direction)...) + result = append(result, createActiveRules(activeRules, cubes[i-1].Left.LastIPAddressObject(), direction, l)...) activeRules = make(map[*netset.IPBlock]netp.Protocol) } @@ -90,7 +91,7 @@ func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCu if icmp, ok := protocol.(netp.ICMP); ok { ruleIcmpSet := optimize.IcmpRuleToIcmpSet(icmp) if !ruleIcmpSet.IsSubset(cubes[i].Right) { - result = append(result, createNewRules(protocol, ipb, cubes[i-1].Left.LastIPAddressObject(), direction)...) + result = append(result, createNewRules(protocol, ipb, cubes[i-1].Left.LastIPAddressObject(), direction, l)...) } else { activeICMP.Union(ruleIcmpSet) } @@ -106,7 +107,7 @@ func icmpIPCubesToRules(cubes []ds.Pair[*netset.IPBlock, *netset.ICMPSet], allCu } // generate all the existing rules - return append(result, createActiveRules(activeRules, cubes[len(cubes)-1].Left.LastIPAddressObject(), direction)...) + return append(result, createActiveRules(activeRules, cubes[len(cubes)-1].Left.LastIPAddressObject(), direction, l)...) } // continuation returns true if the rules can be continued between the two cubes @@ -124,20 +125,21 @@ func continuation[T ds.Set[T]](prevPair, currPair ds.Pair[*netset.IPBlock, T], a } // creates sgRules from SG active rules -func createActiveRules(activeRules map[*netset.IPBlock]netp.Protocol, endIP *netset.IPBlock, direction ir.Direction) []*ir.SGRule { +func createActiveRules(activeRules map[*netset.IPBlock]netp.Protocol, endIP *netset.IPBlock, direction ir.Direction, + l *netset.IPBlock) []*ir.SGRule { res := make([]*ir.SGRule, 0) for ipb, protocol := range activeRules { - res = append(res, createNewRules(protocol, ipb, endIP, direction)...) + res = append(res, createNewRules(protocol, ipb, endIP, direction, l)...) } return res } // createNewRules breaks the startIP-endIP ip range into cidrs and creates SG rules -func createNewRules(protocol netp.Protocol, startIP, endIP *netset.IPBlock, direction ir.Direction) []*ir.SGRule { +func createNewRules(protocol netp.Protocol, startIP, endIP *netset.IPBlock, direction ir.Direction, l *netset.IPBlock) []*ir.SGRule { res := make([]*ir.SGRule, 0) ipRange, _ := netset.IPBlockFromIPRange(startIP, endIP) for _, cidr := range ipRange.SplitToCidrs() { - res = append(res, ir.NewSGRule(direction, cidr, protocol, netset.GetCidrAll(), "")) + res = append(res, ir.NewSGRule(direction, cidr, protocol, l, "")) } return res } diff --git a/pkg/optimize/sg/sg.go b/pkg/optimize/sg/sg.go index 0da688a2..f2f443d8 100644 --- a/pkg/optimize/sg/sg.go +++ b/pkg/optimize/sg/sg.go @@ -90,17 +90,23 @@ func (s *sgOptimizer) optimizeSG(vpcName string, sgName ir.SGName) { reducedRules := 0 // reduce inbound rules first - newInboundRules := s.reduceRules(sg.InboundRules, ir.Inbound) - if len(sg.InboundRules) > len(newInboundRules) { - reducedRules += len(sg.InboundRules) - len(newInboundRules) - s.sgCollection.SGs[vpcName][sgName].InboundRules = newInboundRules + for l, rules := range sg.InboundRules { + local, _ := netset.IPBlockFromCidr(l) + newInboundRules := s.reduceRules(rules, ir.Inbound, local) + if len(rules) > len(newInboundRules) { + reducedRules += len(rules) - len(newInboundRules) + sg.InboundRules[l] = newInboundRules + } } // reduce outbound rules second - newOutboundRules := s.reduceRules(sg.OutboundRules, ir.Outbound) - if len(sg.OutboundRules) > len(newOutboundRules) { - reducedRules += len(sg.OutboundRules) - len(newOutboundRules) - s.sgCollection.SGs[vpcName][sgName].OutboundRules = newOutboundRules + for l, rules := range sg.OutboundRules { + local, _ := netset.IPBlockFromCidr(l) + newOutboundRules := s.reduceRules(rules, ir.Outbound, local) + if len(rules) > len(newOutboundRules) { + reducedRules += len(rules) - len(newOutboundRules) + sg.OutboundRules[l] = newOutboundRules + } } // print a message to the log @@ -115,19 +121,19 @@ func (s *sgOptimizer) optimizeSG(vpcName string, sgName ir.SGName) { } // reduceSGRules attempts to reduce the number of rules with different remote types separately -func (s *sgOptimizer) reduceRules(rules []*ir.SGRule, direction ir.Direction) []*ir.SGRule { +func (s *sgOptimizer) reduceRules(rules []*ir.SGRule, direction ir.Direction, l *netset.IPBlock) []*ir.SGRule { // separate all rules to groups of protocol X remote ([tcp, udp, icmp, protocolAll] X [ip, sg]) ruleGroups := divideSGRules(rules) // rules with SG as a remote - optimizedRulesToSG := reduceRulesSGRemote(rulesToSGCubes(ruleGroups.sgRemoteRules), direction) + optimizedRulesToSG := reduceRulesSGRemote(rulesToSGCubes(ruleGroups.sgRemoteRules), direction, l) originlRulesToSG := ruleGroups.sgRemoteRules.allRules() if len(originlRulesToSG) < len(optimizedRulesToSG) { // failed to reduce number of rules optimizedRulesToSG = originlRulesToSG } // rules with IPBlock as a remote - optimizedRulesToIPAddrs := reduceRulesIPRemote(rulesToIPCubes(ruleGroups.ipRemoteRules), direction) + optimizedRulesToIPAddrs := reduceRulesIPRemote(rulesToIPCubes(ruleGroups.ipRemoteRules), direction, l) originalRulesToIPAddrs := ruleGroups.ipRemoteRules.allRules() if len(originalRulesToIPAddrs) < len(optimizedRulesToSG) { // failed to reduce number of rules optimizedRulesToIPAddrs = originalRulesToIPAddrs @@ -136,27 +142,27 @@ func (s *sgOptimizer) reduceRules(rules []*ir.SGRule, direction ir.Direction) [] return append(optimizedRulesToSG, optimizedRulesToIPAddrs...) } -func reduceRulesSGRemote(cubes *sgCubesPerProtocol, direction ir.Direction) []*ir.SGRule { +func reduceRulesSGRemote(cubes *sgCubesPerProtocol, direction ir.Direction, l *netset.IPBlock) []*ir.SGRule { reduceSGCubes(cubes) // cubes to SG rules - tcpRules := tcpudpSGCubesToRules(cubes.tcp, direction, true) - udpRules := tcpudpSGCubesToRules(cubes.udp, direction, false) - icmpRules := icmpSGCubesToRules(cubes.icmp, direction) - allRules := protocolAllCubesToRules(cubes.all, direction) + tcpRules := tcpudpSGCubesToRules(cubes.tcp, direction, true, l) + udpRules := tcpudpSGCubesToRules(cubes.udp, direction, false, l) + icmpRules := icmpSGCubesToRules(cubes.icmp, direction, l) + allRules := protocolAllCubesToRules(cubes.all, direction, l) // return all rules return append(tcpRules, append(udpRules, append(icmpRules, allRules...)...)...) } -func reduceRulesIPRemote(cubes *ipCubesPerProtocol, direction ir.Direction) []*ir.SGRule { +func reduceRulesIPRemote(cubes *ipCubesPerProtocol, direction ir.Direction, l *netset.IPBlock) []*ir.SGRule { reduceIPCubes(cubes) // cubes to SG rules - tcpRules := tcpudpIPCubesToRules(cubes.tcp, cubes.all, direction, true) - udpRules := tcpudpIPCubesToRules(cubes.udp, cubes.all, direction, false) - icmpRules := icmpIPCubesToRules(cubes.icmp, cubes.all, direction) - allRules := allProtocolIPCubesIPToRules(cubes.all, direction) + tcpRules := tcpudpIPCubesToRules(cubes.tcp, cubes.all, direction, true, l) + udpRules := tcpudpIPCubesToRules(cubes.udp, cubes.all, direction, false, l) + icmpRules := icmpIPCubesToRules(cubes.icmp, cubes.all, direction, l) + allRules := allProtocolIPCubesIPToRules(cubes.all, direction, l) // return all rules return append(tcpRules, append(udpRules, append(icmpRules, allRules...)...)...) diff --git a/pkg/optimize/sg/sgCubesToRules.go b/pkg/optimize/sg/sgCubesToRules.go index 4ed229c7..03698f78 100644 --- a/pkg/optimize/sg/sgCubesToRules.go +++ b/pkg/optimize/sg/sgCubesToRules.go @@ -14,33 +14,33 @@ import ( ) // cubes (SGName X portSet) to SG rules -func tcpudpSGCubesToRules(span map[ir.SGName]*netset.PortSet, direction ir.Direction, isTCP bool) []*ir.SGRule { +func tcpudpSGCubesToRules(span map[ir.SGName]*netset.PortSet, direction ir.Direction, isTCP bool, l *netset.IPBlock) []*ir.SGRule { result := make([]*ir.SGRule, 0) for sgName, portSet := range span { for _, dstPorts := range portSet.Intervals() { p, _ := netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(dstPorts.Start()), int(dstPorts.End())) - result = append(result, ir.NewSGRule(direction, sgName, p, netset.GetCidrAll(), "")) + result = append(result, ir.NewSGRule(direction, sgName, p, l, "")) } } return result } // cubes (SGName X icmpset) to SG rules -func icmpSGCubesToRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction) []*ir.SGRule { +func icmpSGCubesToRules(span map[ir.SGName]*netset.ICMPSet, direction ir.Direction, l *netset.IPBlock) []*ir.SGRule { result := make([]*ir.SGRule, 0) for sgName, icmpSet := range span { for _, icmp := range optimize.IcmpsetPartitions(icmpSet) { - result = append(result, ir.NewSGRule(direction, sgName, icmp, netset.GetCidrAll(), "")) + result = append(result, ir.NewSGRule(direction, sgName, icmp, l, "")) } } return result } // cubes (slice of SGs) to SG rules -func protocolAllCubesToRules(span []ir.SGName, direction ir.Direction) []*ir.SGRule { +func protocolAllCubesToRules(span []ir.SGName, direction ir.Direction, l *netset.IPBlock) []*ir.SGRule { result := make([]*ir.SGRule, len(span)) for i, sgName := range span { - result[i] = ir.NewSGRule(direction, sgName, netp.AnyProtocol{}, netset.GetCidrAll(), "") + result[i] = ir.NewSGRule(direction, sgName, netp.AnyProtocol{}, l, "") } return result } From 5ed05427ffa3275551bee33467c22acd25380449 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 29 Oct 2024 11:50:50 +0200 Subject: [PATCH 77/79] read acls --- pkg/io/confio/parse_acls.go | 135 +++++++++++++++++++++++++++++++++++- pkg/io/confio/parse_sgs.go | 67 ++++++------------ pkg/io/tfio/acl.go | 3 +- pkg/ir/acl.go | 2 + 4 files changed, 157 insertions(+), 50 deletions(-) diff --git a/pkg/io/confio/parse_acls.go b/pkg/io/confio/parse_acls.go index 13481978..09647519 100644 --- a/pkg/io/confio/parse_acls.go +++ b/pkg/io/confio/parse_acls.go @@ -5,8 +5,137 @@ SPDX-License-Identifier: Apache-2.0 package confio -import "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +import ( + "errors" + "fmt" + "log" -func ReadACLs(_ string) (*ir.ACLCollection, error) { - return nil, nil + "github.com/IBM/vpc-go-sdk/vpcv1" + + "github.com/np-guard/models/pkg/netp" + "github.com/np-guard/models/pkg/netset" + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" +) + +// ReadACLs translates ACLs from a config_object file to ir.ACLCollection +func ReadACLs(filename string) (*ir.ACLCollection, error) { + config, err := readModel(filename) + if err != nil { + return nil, err + } + + result := ir.NewACLCollection() + for i, acl := range config.NetworkACLList { + if acl.Name == nil || acl.VPC == nil || acl.VPC.Name == nil { + log.Printf("Warning: missing acl/VPC name in acl at index %d\n", i) + continue + } + inbound, outbound, err := translateACLRules(&acl.NetworkACL) + if err != nil { + return nil, err + } + vpcName := *acl.VPC.Name + if result.ACLs[vpcName] == nil { + result.ACLs[vpcName] = make(map[string]*ir.ACL) + } + result.ACLs[vpcName][*acl.Name] = &ir.ACL{Inbound: inbound, Outbound: outbound} + } + return result, nil +} + +func translateACLRules(acl *vpcv1.NetworkACL) (inbound, outbound []*ir.ACLRule, err error) { + inbound = make([]*ir.ACLRule, 0) + outbound = make([]*ir.ACLRule, 0) + for index := range acl.Rules { + rule, err := translateACLRule(acl, index) + if err != nil { + return nil, nil, err + } + if rule.Direction == ir.Inbound { + inbound = append(inbound, rule) + } else { + outbound = append(outbound, rule) + } + } + return inbound, outbound, nil +} + +func translateACLRule(acl *vpcv1.NetworkACL, i int) (*ir.ACLRule, error) { + switch r := acl.Rules[i].(type) { + case *vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolAll: + return translateACLRuleProtocolAll(r) + case *vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolTcpudp: + return translateACLRuleProtocolTCPUDP(r) + case *vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolIcmp: + return translateACLRuleProtocolIcmp(r) + } + return nil, fmt.Errorf("error parsing rule number %d in acl %s in VPC %s", i, *acl.Name, *acl.VPC.Name) +} + +func translateACLRuleProtocolAll(rule *vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolAll) (*ir.ACLRule, error) { + action, err1 := translateAction(rule.Action) + direction, err2 := translateDirection(*rule.Direction) + src, err3 := translateResource(rule.Source) + dst, err4 := translateResource(rule.Destination) + if err := errors.Join(err1, err2, err3, err4); err != nil { + return nil, err + } + return &ir.ACLRule{ + Action: action, + Direction: direction, + Source: src, + Destination: dst, + Protocol: netp.AnyProtocol{}, + }, nil +} + +func translateACLRuleProtocolTCPUDP(rule *vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolTcpudp) (*ir.ACLRule, error) { + action, err1 := translateAction(rule.Action) + direction, err2 := translateDirection(*rule.Direction) + src, err3 := translateResource(rule.Source) + dst, err4 := translateResource(rule.Destination) + protocol, err5 := translateProtocolTCPUDP(*rule.Protocol, rule.DestinationPortMin, rule.DestinationPortMax) + if err := errors.Join(err1, err2, err3, err4, err5); err != nil { + return nil, err + } + + return &ir.ACLRule{ + Action: action, + Direction: direction, + Source: src, + Destination: dst, + Protocol: protocol, + }, nil +} + +func translateACLRuleProtocolIcmp(rule *vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolIcmp) (*ir.ACLRule, error) { + action, err1 := translateAction(rule.Action) + direction, err2 := translateDirection(*rule.Direction) + src, err3 := translateResource(rule.Source) + dst, err4 := translateResource(rule.Destination) + protocol, err5 := netp.ICMPFromTypeAndCode64WithoutRFCValidation(rule.Type, rule.Code) + if err := errors.Join(err1, err2, err3, err4, err5); err != nil { + return nil, err + } + + return &ir.ACLRule{ + Action: action, + Direction: direction, + Source: src, + Destination: dst, + Protocol: protocol, + }, nil +} + +func translateAction(action *string) (ir.Action, error) { + if *action == vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolAllActionAllowConst { + return ir.Allow, nil + } else if *action == vpcv1.NetworkACLRuleItemNetworkACLRuleProtocolAllActionDenyConst { + return ir.Deny, nil + } + return ir.Deny, fmt.Errorf("an nACL rule action must be either allow or deny") +} + +func translateResource(ipAddrs *string) (*netset.IPBlock, error) { + return netset.IPBlockFromCidrOrAddress(*ipAddrs) } diff --git a/pkg/io/confio/parse_sgs.go b/pkg/io/confio/parse_sgs.go index f39f890d..840317dc 100644 --- a/pkg/io/confio/parse_sgs.go +++ b/pkg/io/confio/parse_sgs.go @@ -6,6 +6,7 @@ SPDX-License-Identifier: Apache-2.0 package confio import ( + "errors" "fmt" "log" @@ -42,7 +43,7 @@ func ReadSGs(filename string) (*ir.SGCollection, error) { result.SGs[vpcName][ir.SGName(*sg.Name)] = &ir.SG{SGName: ir.SGName(*sg.Name), InboundRules: inbound, OutboundRules: outbound, - Targets: transalteTargets(&sg.SecurityGroup), + Targets: translateTargets(&sg.SecurityGroup), } } return result, nil @@ -81,56 +82,32 @@ func translateSGRule(sg *vpcv1.SecurityGroup, index int) (sgRule *ir.SGRule, err } func translateSGRuleProtocolAll(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolAll) (sgRule *ir.SGRule, err error) { - direction, err := translateDirection(*rule.Direction) - if err != nil { - return nil, err - } - remote, err := translateRemote(rule.Remote) - if err != nil { - return nil, err - } - local, err := translateLocal(rule.Local) - if err != nil { + direction, err1 := translateDirection(*rule.Direction) + remote, err2 := translateRemote(rule.Remote) + local, err3 := translateLocal(rule.Local) + if err := errors.Join(err1, err2, err3); err != nil { return nil, err } return &ir.SGRule{Direction: direction, Remote: remote, Protocol: netp.AnyProtocol{}, Local: local}, nil } func translateSGRuleProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (sgRule *ir.SGRule, err error) { - direction, err := translateDirection(*rule.Direction) - if err != nil { - return nil, err - } - remote, err := translateRemote(rule.Remote) - if err != nil { - return nil, err - } - local, err := translateLocal(rule.Local) - if err != nil { - return nil, err - } - protocol, err := translateProtocolTCPUDP(rule) - if err != nil { + direction, err1 := translateDirection(*rule.Direction) + remote, err2 := translateRemote(rule.Remote) + local, err3 := translateLocal(rule.Local) + protocol, err4 := translateProtocolTCPUDP(*rule.Protocol, rule.PortMin, rule.PortMax) + if err := errors.Join(err1, err2, err3, err4); err != nil { return nil, err } return &ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil } func translateSGRuleProtocolIcmp(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolIcmp) (sgRule *ir.SGRule, err error) { - direction, err := translateDirection(*rule.Direction) - if err != nil { - return nil, err - } - remote, err := translateRemote(rule.Remote) - if err != nil { - return nil, err - } - local, err := translateLocal(rule.Local) - if err != nil { - return nil, err - } - protocol, err := netp.ICMPFromTypeAndCode64WithoutRFCValidation(rule.Type, rule.Code) - if err != nil { + direction, err1 := translateDirection(*rule.Direction) + remote, err2 := translateRemote(rule.Remote) + local, err3 := translateLocal(rule.Local) + protocol, err4 := netp.ICMPFromTypeAndCode64WithoutRFCValidation(rule.Type, rule.Code) + if err := errors.Join(err1, err2, err3, err4); err != nil { return nil, err } return &ir.SGRule{Direction: direction, Remote: remote, Protocol: protocol, Local: local}, nil @@ -142,7 +119,7 @@ func translateDirection(direction string) (ir.Direction, error) { } else if direction == "outbound" { return ir.Outbound, nil } - return ir.Inbound, fmt.Errorf("SG rule direction must be either inbound or outbound") + return ir.Inbound, fmt.Errorf("a firewall rule direction must be either inbound or outbound") } func translateRemote(remote vpcv1.SecurityGroupRuleRemoteIntf) (ir.RemoteType, error) { @@ -172,7 +149,7 @@ func translateLocal(local vpcv1.SecurityGroupRuleLocalIntf) (*netset.IPBlock, er } // translate SG targets -func transalteTargets(sg *vpcv1.SecurityGroup) []string { +func translateTargets(sg *vpcv1.SecurityGroup) []string { if len(sg.Targets) == 0 { log.Printf("Warning: Security Groups %s does not have attached resources", *sg.Name) } @@ -187,9 +164,9 @@ func transalteTargets(sg *vpcv1.SecurityGroup) []string { return res } -func translateProtocolTCPUDP(rule *vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudp) (netp.Protocol, error) { - isTCP := *rule.Protocol == vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudpProtocolTCPConst - minDstPort := utils.GetProperty(rule.PortMin, netp.MinPort) - maxDstPort := utils.GetProperty(rule.PortMax, netp.MaxPort) +func translateProtocolTCPUDP(protocolName string, portMin, portMax *int64) (netp.Protocol, error) { + isTCP := protocolName == vpcv1.SecurityGroupRuleSecurityGroupRuleProtocolTcpudpProtocolTCPConst + minDstPort := utils.GetProperty(portMin, netp.MinPort) + maxDstPort := utils.GetProperty(portMax, netp.MaxPort) return netp.NewTCPUDP(isTCP, netp.MinPort, netp.MaxPort, int(minDstPort), int(maxDstPort)) } diff --git a/pkg/io/tfio/acl.go b/pkg/io/tfio/acl.go index 15b31afe..24f52ca6 100644 --- a/pkg/io/tfio/acl.go +++ b/pkg/io/tfio/acl.go @@ -28,8 +28,7 @@ func (w *Writer) WriteACL(c *ir.ACLCollection, vpc string, _ bool) error { if err != nil { return err } - err = w.w.Flush() - return err + return w.w.Flush() } func aclProtocol(t netp.Protocol) []tf.Block { diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 938a74e8..54e27a5f 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -31,6 +31,8 @@ type ( Subnet string Internal []*ACLRule External []*ACLRule + Inbound []*ACLRule + Outbound []*ACLRule } ACLCollection struct { From 0372fb5aca1972cf0e4a0f0e04020e403ae56f70 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 29 Oct 2024 12:19:29 +0200 Subject: [PATCH 78/79] fixed flags --- cmd/subcmds/optimize.go | 5 +++-- cmd/subcmds/optimizeACL.go | 17 +++++++++++++---- pkg/ir/acl.go | 3 +-- pkg/optimize/acl/acl.go | 31 +++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 pkg/optimize/acl/acl.go diff --git a/cmd/subcmds/optimize.go b/cmd/subcmds/optimize.go index 353a86eb..5bde4287 100644 --- a/cmd/subcmds/optimize.go +++ b/cmd/subcmds/optimize.go @@ -17,12 +17,13 @@ import ( func NewOptimizeCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "optimize", - Short: "optimization of existing SG (nACLS are not supported yet)", - Long: `optimization of existing SG (nACLS are not supported yet)`, + Short: "optimization of existing SG and nACLs", + Long: `optimization of existing SG and nACLs`, } // sub cmds cmd.AddCommand(NewOptimizeSGCommand(args)) + cmd.AddCommand(NewOptimizeACLCommand(args)) return cmd } diff --git a/cmd/subcmds/optimizeACL.go b/cmd/subcmds/optimizeACL.go index beb8e09b..67487ba2 100644 --- a/cmd/subcmds/optimizeACL.go +++ b/cmd/subcmds/optimizeACL.go @@ -5,18 +5,27 @@ SPDX-License-Identifier: Apache-2.0 package subcmds -import "github.com/spf13/cobra" +import ( + "github.com/spf13/cobra" + + acloptimizer "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize/acl" +) + +const aclNameFlag = "acl-name" func NewOptimizeACLCommand(args *inArgs) *cobra.Command { cmd := &cobra.Command{ Use: "acl", - Short: "OptimizeACL is not supported yet", - Long: `OptimizeACL is not supported yet`, + Short: "OptimizeACL attempts to reduce the number of nACL rules in an nACL without changing the semantic.", + Long: `OptimizeACL attempts to reduce the number of nACL rules in an nACL without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return nil + return optimization(cmd, args, acloptimizer.NewSGOptimizer, false) }, } + // flags + cmd.PersistentFlags().StringVarP(&args.firewallName, aclNameFlag, "n", "", "which nacl to optimize") + return cmd } diff --git a/pkg/ir/acl.go b/pkg/ir/acl.go index 54e27a5f..ea2cd065 100644 --- a/pkg/ir/acl.go +++ b/pkg/ir/acl.go @@ -76,8 +76,7 @@ func (r *ACLRule) Target() *netset.IPBlock { func (a *ACL) Rules() []*ACLRule { rules := a.Internal if len(a.External) != 0 { - rules = append(rules, makeDenyInternal()...) - rules = append(rules, a.External...) + rules = append(rules, append(makeDenyInternal(), a.External...)...) } return rules } diff --git a/pkg/optimize/acl/acl.go b/pkg/optimize/acl/acl.go new file mode 100644 index 00000000..1c13fab2 --- /dev/null +++ b/pkg/optimize/acl/acl.go @@ -0,0 +1,31 @@ +/* +Copyright 2023- IBM Inc. All Rights Reserved. +SPDX-License-Identifier: Apache-2.0 +*/ + +package acloptimizer + +import ( + "github.com/np-guard/vpc-network-config-synthesis/pkg/ir" + "github.com/np-guard/vpc-network-config-synthesis/pkg/optimize" +) + +type ( + aclOptimizer struct { + aclCollection *ir.ACLCollection + aclName string + aclVPC *string + } +) + +func NewSGOptimizer(collection ir.Collection, aclName string) optimize.Optimizer { + components := ir.ScopingComponents(aclName) + if len(components) == 1 { + return &aclOptimizer{aclCollection: collection.(*ir.ACLCollection), aclName: aclName, aclVPC: nil} + } + return &aclOptimizer{aclCollection: collection.(*ir.ACLCollection), aclName: components[1], aclVPC: &components[0]} +} + +func (a *aclOptimizer) Optimize() (ir.Collection, error) { + return nil, nil +} From 706623208da203f7bf2bbc7f610d988273f22136 Mon Sep 17 00:00:00 2001 From: Yair Slobodin Date: Tue, 29 Oct 2024 16:30:08 +0200 Subject: [PATCH 79/79] typo --- cmd/subcmds/optimizeACL.go | 2 +- pkg/optimize/acl/acl.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/subcmds/optimizeACL.go b/cmd/subcmds/optimizeACL.go index 67487ba2..c40d38a7 100644 --- a/cmd/subcmds/optimizeACL.go +++ b/cmd/subcmds/optimizeACL.go @@ -20,7 +20,7 @@ func NewOptimizeACLCommand(args *inArgs) *cobra.Command { Long: `OptimizeACL attempts to reduce the number of nACL rules in an nACL without changing the semantic.`, Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, _ []string) error { - return optimization(cmd, args, acloptimizer.NewSGOptimizer, false) + return optimization(cmd, args, acloptimizer.NewACLOptimizer, false) }, } diff --git a/pkg/optimize/acl/acl.go b/pkg/optimize/acl/acl.go index 1c13fab2..33fcbba2 100644 --- a/pkg/optimize/acl/acl.go +++ b/pkg/optimize/acl/acl.go @@ -18,7 +18,7 @@ type ( } ) -func NewSGOptimizer(collection ir.Collection, aclName string) optimize.Optimizer { +func NewACLOptimizer(collection ir.Collection, aclName string) optimize.Optimizer { components := ir.ScopingComponents(aclName) if len(components) == 1 { return &aclOptimizer{aclCollection: collection.(*ir.ACLCollection), aclName: aclName, aclVPC: nil}