go.ligato.io/vpp-agent/v3@v3.5.0/tests/integration/vpp/130_ipsec_test.go (about)

     1  //  Copyright (c) 2021 Cisco and/or its affiliates.
     2  //
     3  //  Licensed under the Apache License, Version 2.0 (the "License");
     4  //  you may not use this file except in compliance with the License.
     5  //  You may obtain a copy of the License at:
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  //  Unless required by applicable law or agreed to in writing, software
    10  //  distributed under the License is distributed on an "AS IS" BASIS,
    11  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  //  See the License for the specific language governing permissions and
    13  //  limitations under the License.
    14  
    15  package vpp
    16  
    17  import (
    18  	"fmt"
    19  	"testing"
    20  
    21  	"go.ligato.io/cn-infra/v2/logging/logrus"
    22  	"google.golang.org/protobuf/proto"
    23  
    24  	"go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/ifaceidx"
    25  	ifplugin_vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin/vppcalls"
    26  	ipsec_vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin/vppcalls"
    27  	interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces"
    28  	ipsec "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/ipsec"
    29  
    30  	_ "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin"
    31  	_ "go.ligato.io/vpp-agent/v3/plugins/vpp/ipsecplugin"
    32  )
    33  
    34  func TestIPSec(t *testing.T) {
    35  	ctx := setupVPP(t)
    36  	defer ctx.teardownVPP()
    37  
    38  	spdIfaceDumpOk := false // determines if ipsec_spd_interface_dump works correctly
    39  
    40  	ifIndexes := ifaceidx.NewIfaceIndex(logrus.NewLogger("test"), "test-ifidx")
    41  	ifHandler := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.vppClient, logrus.NewLogger("test-if"))
    42  	ipsecHandler := ipsec_vppcalls.CompatibleIPSecVppHandler(ctx.vppClient, ifIndexes, logrus.NewLogger("test-ipsec"))
    43  
    44  	tests := []struct {
    45  		name  string
    46  		ipip  *interfaces.IPIPLink
    47  		saOut *ipsec.SecurityAssociation
    48  		saIn  *ipsec.SecurityAssociation
    49  		spd   *ipsec.SecurityPolicyDatabase
    50  		spOut *ipsec.SecurityPolicy
    51  		spIn  *ipsec.SecurityPolicy
    52  		tp    *ipsec.TunnelProtection
    53  	}{
    54  		{
    55  			name: "Create IPSec tunnel (IPv4)",
    56  			ipip: &interfaces.IPIPLink{
    57  				SrcAddr: "20.30.40.50",
    58  				DstAddr: "50.40.30.20",
    59  			},
    60  			saOut: &ipsec.SecurityAssociation{
    61  				Index:          10,
    62  				Spi:            123,
    63  				Protocol:       ipsec.SecurityAssociation_ESP,
    64  				CryptoAlg:      ipsec.CryptoAlg_AES_CBC_128,
    65  				CryptoKey:      "d9a4ec50aed76f1bf80bc915d8fcfe1c",
    66  				IntegAlg:       ipsec.IntegAlg_SHA1_96,
    67  				IntegKey:       "bf9b150aaf5c2a87d79898b11eabd055e70abdbe",
    68  				EnableUdpEncap: true,
    69  			},
    70  			saIn: &ipsec.SecurityAssociation{
    71  				Index:          20,
    72  				Spi:            456,
    73  				Protocol:       ipsec.SecurityAssociation_ESP,
    74  				CryptoAlg:      ipsec.CryptoAlg_AES_CBC_128,
    75  				CryptoKey:      "d9a4ec50aed76f1bf80bc915d8fcfe1c",
    76  				IntegAlg:       ipsec.IntegAlg_SHA1_96,
    77  				IntegKey:       "bf9b150aaf5c2a87d79898b11eabd055e70abdbe",
    78  				EnableUdpEncap: true,
    79  			},
    80  			spd: &ipsec.SecurityPolicyDatabase{
    81  				Index: 100,
    82  			},
    83  			spOut: &ipsec.SecurityPolicy{
    84  				SpdIndex:        100,
    85  				SaIndex:         10,
    86  				Priority:        0,
    87  				IsOutbound:      true,
    88  				RemoteAddrStart: "10.10.1.1",
    89  				RemoteAddrStop:  "10.10.1.255",
    90  				LocalAddrStart:  "10.10.2.1",
    91  				LocalAddrStop:   "10.10.2.255",
    92  				Protocol:        0,
    93  				Action:          ipsec.SecurityPolicy_PROTECT,
    94  			},
    95  			spIn: &ipsec.SecurityPolicy{
    96  				SpdIndex:        100,
    97  				SaIndex:         20,
    98  				Priority:        0,
    99  				IsOutbound:      false,
   100  				RemoteAddrStart: "10.10.1.1",
   101  				RemoteAddrStop:  "10.10.1.255",
   102  				LocalAddrStart:  "10.10.2.1",
   103  				LocalAddrStop:   "10.10.2.255",
   104  				Protocol:        0,
   105  				RemotePortStart: 1000,
   106  				RemotePortStop:  5000,
   107  				LocalPortStart:  2000,
   108  				LocalPortStop:   7000,
   109  				Action:          ipsec.SecurityPolicy_PROTECT,
   110  			},
   111  			tp: &ipsec.TunnelProtection{
   112  				SaOut: []uint32{10},
   113  				SaIn:  []uint32{20},
   114  			},
   115  		},
   116  		{
   117  			name: "Create IPSec tunnel (IPv6)",
   118  			ipip: &interfaces.IPIPLink{
   119  				SrcAddr: "2001:db8:0:1:1:1:1:1",
   120  				DstAddr: "2002:db8:0:1:1:1:1:1",
   121  			},
   122  			saOut: &ipsec.SecurityAssociation{
   123  				Index:     1,
   124  				Spi:       789,
   125  				Protocol:  ipsec.SecurityAssociation_ESP,
   126  				CryptoAlg: ipsec.CryptoAlg_AES_CBC_128,
   127  				CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c",
   128  				IntegAlg:  ipsec.IntegAlg_SHA1_96,
   129  				IntegKey:  "bf9b150aaf5c2a87d79898b11eabd055e70abdbe",
   130  			},
   131  			saIn: &ipsec.SecurityAssociation{
   132  				Index:     2,
   133  				Spi:       321,
   134  				Protocol:  ipsec.SecurityAssociation_ESP,
   135  				CryptoAlg: ipsec.CryptoAlg_AES_CBC_128,
   136  				CryptoKey: "d9a4ec50aed76f1bf80bc915d8fcfe1c",
   137  				IntegAlg:  ipsec.IntegAlg_SHA1_96,
   138  				IntegKey:  "bf9b150aaf5c2a87d79898b11eabd055e70abdbe",
   139  			},
   140  			tp: &ipsec.TunnelProtection{
   141  				SaOut: []uint32{1},
   142  				SaIn:  []uint32{2},
   143  			},
   144  			spd: &ipsec.SecurityPolicyDatabase{
   145  				Index: 101,
   146  			},
   147  			spOut: &ipsec.SecurityPolicy{
   148  				SpdIndex:        101,
   149  				SaIndex:         1,
   150  				Priority:        0,
   151  				IsOutbound:      true,
   152  				RemoteAddrStart: "2001:1000::1",
   153  				RemoteAddrStop:  "2001:1000::1000",
   154  				LocalAddrStart:  "2001:2000::1",
   155  				LocalAddrStop:   "2001:2000::1000",
   156  				Protocol:        0,
   157  				Action:          ipsec.SecurityPolicy_PROTECT,
   158  			},
   159  			spIn: &ipsec.SecurityPolicy{
   160  				SpdIndex:        101,
   161  				SaIndex:         2,
   162  				Priority:        0,
   163  				IsOutbound:      false,
   164  				RemoteAddrStart: "2001:1000::1",
   165  				RemoteAddrStop:  "2001:1000::1000",
   166  				LocalAddrStart:  "2001:2000::1",
   167  				LocalAddrStop:   "2001:2000::1000",
   168  				Protocol:        0,
   169  				RemotePortStart: 1000,
   170  				RemotePortStop:  5000,
   171  				LocalPortStart:  2000,
   172  				LocalPortStop:   7000,
   173  				Action:          ipsec.SecurityPolicy_PROTECT,
   174  			},
   175  		},
   176  		{
   177  			name: "Create multipoint IPSec tunnel",
   178  			ipip: &interfaces.IPIPLink{
   179  				SrcAddr:    "20.30.40.50",
   180  				TunnelMode: interfaces.IPIPLink_POINT_TO_MULTIPOINT,
   181  			},
   182  			saOut: &ipsec.SecurityAssociation{
   183  				Index:          100,
   184  				Spi:            123,
   185  				Protocol:       ipsec.SecurityAssociation_ESP,
   186  				CryptoAlg:      ipsec.CryptoAlg_AES_CBC_128,
   187  				CryptoKey:      "d9a4ec50aed76f1bf80bc915d8fcfe1c",
   188  				IntegAlg:       ipsec.IntegAlg_SHA1_96,
   189  				IntegKey:       "bf9b150aaf5c2a87d79898b11eabd055e70abdbe",
   190  				EnableUdpEncap: true,
   191  			},
   192  			saIn: &ipsec.SecurityAssociation{
   193  				Index:          101,
   194  				Spi:            456,
   195  				Protocol:       ipsec.SecurityAssociation_ESP,
   196  				CryptoAlg:      ipsec.CryptoAlg_AES_CBC_128,
   197  				CryptoKey:      "d9a4ec50aed76f1bf80bc915d8fcfe1c",
   198  				IntegAlg:       ipsec.IntegAlg_SHA1_96,
   199  				IntegKey:       "bf9b150aaf5c2a87d79898b11eabd055e70abdbe",
   200  				EnableUdpEncap: true,
   201  			},
   202  			spd: &ipsec.SecurityPolicyDatabase{
   203  				Index: 102,
   204  			},
   205  			spOut: &ipsec.SecurityPolicy{
   206  				SpdIndex:        102,
   207  				SaIndex:         100,
   208  				Priority:        0,
   209  				IsOutbound:      true,
   210  				RemoteAddrStart: "10.10.1.1",
   211  				RemoteAddrStop:  "10.10.1.255",
   212  				LocalAddrStart:  "10.10.2.1",
   213  				LocalAddrStop:   "10.10.2.255",
   214  				Protocol:        0,
   215  				Action:          ipsec.SecurityPolicy_PROTECT,
   216  			},
   217  			spIn: &ipsec.SecurityPolicy{
   218  				SpdIndex:        102,
   219  				SaIndex:         101,
   220  				Priority:        0,
   221  				IsOutbound:      false,
   222  				RemoteAddrStart: "10.10.1.1",
   223  				RemoteAddrStop:  "10.10.1.255",
   224  				LocalAddrStart:  "10.10.2.1",
   225  				LocalAddrStop:   "10.10.2.255",
   226  				Protocol:        0,
   227  				RemotePortStart: 1000,
   228  				RemotePortStop:  5000,
   229  				LocalPortStart:  2000,
   230  				LocalPortStop:   7000,
   231  				Action:          ipsec.SecurityPolicy_PROTECT,
   232  			},
   233  			tp: &ipsec.TunnelProtection{
   234  				SaOut:       []uint32{100},
   235  				SaIn:        []uint32{101},
   236  				NextHopAddr: "4.5.6.7",
   237  			},
   238  		},
   239  	}
   240  	for i, test := range tests {
   241  		t.Run(test.name, func(t *testing.T) {
   242  			// create IPIP tunnel + SAs + tunnel protection + SPs
   243  			ifName := fmt.Sprintf("ipip%d", i)
   244  			ifIdx, err := ifHandler.AddIpipTunnel(ifName, 0, test.ipip)
   245  			if err != nil {
   246  				t.Fatalf("IPIP tunnel add failed: %v", err)
   247  			}
   248  			ifIndexes.Clear()
   249  			ifIndexes.Put(ifName, &ifaceidx.IfaceMetadata{
   250  				SwIfIndex: ifIdx,
   251  			})
   252  			err = ipsecHandler.AddSA(test.saOut)
   253  			if err != nil {
   254  				t.Fatalf("IPSec SA add failed: %v", err)
   255  			}
   256  			err = ipsecHandler.AddSA(test.saIn)
   257  			if err != nil {
   258  				t.Fatalf("IPSec SA add failed: %v", err)
   259  			}
   260  			test.tp.Interface = ifName
   261  			err = ipsecHandler.AddTunnelProtection(test.tp)
   262  			if err != nil {
   263  				t.Fatalf("add tunnel protection failed: %v\n", err)
   264  			}
   265  			err = ipsecHandler.AddSPD(test.spd.Index)
   266  			if err != nil {
   267  				t.Fatalf("add SPD failed: %v\n", err)
   268  			}
   269  			err = ipsecHandler.AddSPDInterface(test.spd.Index, &ipsec.SecurityPolicyDatabase_Interface{Name: ifName})
   270  			if err != nil {
   271  				t.Fatalf("add SPD-Interface failed: %v\n", err)
   272  			}
   273  			err = ipsecHandler.AddSP(test.spOut)
   274  			if err != nil {
   275  				t.Fatalf("add SP failed: %v\n", err)
   276  			}
   277  			err = ipsecHandler.AddSP(test.spIn)
   278  			if err != nil {
   279  				t.Fatalf("add SP failed: %v\n", err)
   280  			}
   281  
   282  			// check created SAs + tunnel protection + SPs
   283  			saList, err := ipsecHandler.DumpIPSecSA()
   284  			if err != nil {
   285  				t.Fatalf("dumping SAs failed: %v", err)
   286  			}
   287  			if len(saList) != 2 {
   288  				t.Fatalf("Invalid number of SAs: %d", len(saList))
   289  			}
   290  			for _, sa := range saList {
   291  				if sa.Sa.Index != test.saOut.Index && sa.Sa.Index != test.saIn.Index {
   292  					t.Fatalf("Invalid SA index: %d", sa.Sa.Index)
   293  				}
   294  			}
   295  			tpList, err := ipsecHandler.DumpTunnelProtections()
   296  			if err != nil {
   297  				t.Fatalf("dumping tunnel protections failed: %v", err)
   298  			}
   299  			if len(tpList) != 1 {
   300  				t.Fatalf("Invalid number of tunnel protections: %d", len(tpList))
   301  			}
   302  			if tpList[0].Interface != ifName {
   303  				t.Fatalf("Invalid interface name in tunnel protections: %s", tpList[0].Interface)
   304  			}
   305  			if tpList[0].SaIn[0] != test.saIn.Index || tpList[0].SaOut[0] != test.saOut.Index {
   306  				t.Fatalf("tunnel protection SA mismatch (%d != %d || %d != %d)",
   307  					tpList[0].SaIn[0], test.saIn.Index, tpList[0].SaOut[0], test.saOut.Index)
   308  			}
   309  			if tpList[0].NextHopAddr != test.tp.NextHopAddr {
   310  				t.Fatalf("tunnel protection next hop mismatch (%v != %v)", tpList[0].NextHopAddr, test.tp.NextHopAddr)
   311  			}
   312  			spdList, err := ipsecHandler.DumpIPSecSPD()
   313  			if err != nil {
   314  				t.Fatalf("dumping of SPDs failed: %v", err)
   315  			}
   316  			if len(spdList) != 1 {
   317  				t.Fatalf("Invalid number of SPDs: %d", len(spdList))
   318  			}
   319  			if spdList[0].Index != test.spd.Index {
   320  				t.Fatalf("Invalid SPD index: %d", spdList[0].Index)
   321  			}
   322  			if spdIfaceDumpOk {
   323  				if len(spdList[0].Interfaces) != 1 {
   324  					t.Fatalf("Invalid number of interfaces inside SPDs: %d", len(spdList[0].Interfaces))
   325  				}
   326  				if spdList[0].Interfaces[0].Name != ifName {
   327  					t.Fatalf("Invalid interface name in tunnel protections: %s", spdList[0].Interfaces[0].Name)
   328  				}
   329  			}
   330  			spList, err := ipsecHandler.DumpIPSecSP()
   331  			if err != nil {
   332  				t.Fatalf("dumping of SPs failed: %v", err)
   333  			}
   334  			if len(spList) != 2 {
   335  				t.Fatalf("Invalid number of SPs: %d", len(spList))
   336  			}
   337  			for _, sp := range spList {
   338  				if !proto.Equal(sp, test.spOut) && !proto.Equal(sp, test.spIn) {
   339  					t.Fatalf("Invalid SP: %+v", sp)
   340  				}
   341  			}
   342  
   343  			// delete SPs, tunnel protection, SAs and IPIP tunnel
   344  			err = ipsecHandler.DeleteSP(test.spIn)
   345  			if err != nil {
   346  				t.Fatalf("delete of security policy failed: %v\n", err)
   347  			}
   348  			err = ipsecHandler.DeleteSP(test.spOut)
   349  			if err != nil {
   350  				t.Fatalf("delete of security policy failed: %v\n", err)
   351  			}
   352  			spList, err = ipsecHandler.DumpIPSecSP()
   353  			if err != nil {
   354  				t.Fatalf("dumping of security policies failed: %v", err)
   355  			}
   356  			if len(spList) != 0 {
   357  				t.Fatalf("%d SPs found in dump after removing", len(spList))
   358  			}
   359  			err = ipsecHandler.DeleteSPDInterface(test.spd.Index, &ipsec.SecurityPolicyDatabase_Interface{Name: ifName})
   360  			if err != nil {
   361  				t.Fatalf("delete of SPD failed: %v\n", err)
   362  			}
   363  			err = ipsecHandler.DeleteSPD(test.spd.Index)
   364  			if err != nil {
   365  				t.Fatalf("delete of SPD failed: %v\n", err)
   366  			}
   367  			spdList, err = ipsecHandler.DumpIPSecSPD()
   368  			if err != nil {
   369  				t.Fatalf("dumping of SPDs failed: %v", err)
   370  			}
   371  			if len(spdList) != 0 {
   372  				t.Fatalf("%d SPDs found in dump after removing", len(spdList))
   373  			}
   374  			err = ipsecHandler.DeleteTunnelProtection(test.tp)
   375  			if err != nil {
   376  				t.Fatalf("delete tunnel protection failed: %v\n", err)
   377  			}
   378  			tpList, err = ipsecHandler.DumpTunnelProtections()
   379  			if err != nil {
   380  				t.Fatalf("dumping tunnel protections failed: %v", err)
   381  			}
   382  			if len(tpList) != 0 {
   383  				t.Fatalf("%d tunnel protections found in dump after removing", len(tpList))
   384  			}
   385  			err = ipsecHandler.DeleteSA(test.saOut)
   386  			if err != nil {
   387  				t.Fatalf("delete SA failed: %v\n", err)
   388  			}
   389  			err = ipsecHandler.DeleteSA(test.saIn)
   390  			if err != nil {
   391  				t.Fatalf("delete SA failed: %v\n", err)
   392  			}
   393  			saList, err = ipsecHandler.DumpIPSecSA()
   394  			if err != nil {
   395  				t.Fatalf("dumping SAs failed: %v", err)
   396  			}
   397  			if len(saList) != 0 {
   398  				t.Fatalf("%d SAs found in dump after removing", len(saList))
   399  			}
   400  			err = ifHandler.DelIpipTunnel(ifName, ifIdx)
   401  			if err != nil {
   402  				t.Fatalf("delete IPIP tunnel failed: %v\n", err)
   403  			}
   404  			ifaces, err := ifHandler.DumpInterfaces(ctx.Ctx)
   405  			if err != nil {
   406  				t.Fatalf("dumping interfaces failed: %v", err)
   407  			}
   408  			if _, ok := ifaces[ifIdx]; ok {
   409  				t.Fatalf("IPIP interface was found in dump after removing")
   410  			}
   411  		})
   412  	}
   413  }