go.ligato.io/vpp-agent/v3@v3.5.0/tests/integration/vpp/160_wireguard_test.go (about) 1 // Copyright (c) 2020 Doc.ai 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 23 _ "go.ligato.io/vpp-agent/v3/plugins/vpp/ifplugin" 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 _ "go.ligato.io/vpp-agent/v3/plugins/vpp/wireguardplugin" 27 wgplugin_vppcalls "go.ligato.io/vpp-agent/v3/plugins/vpp/wireguardplugin/vppcalls" 28 interfaces "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/interfaces" 29 wg "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/wireguard" 30 ) 31 32 type testEntry struct { 33 name string 34 wgInt *interfaces.WireguardLink 35 wgInt2 *interfaces.WireguardLink 36 peer *wg.Peer 37 peer2 *wg.Peer 38 shouldFail bool 39 skip string 40 skipFor string 41 } 42 43 func TestWireguard(t *testing.T) { 44 ctx := setupVPP(t) 45 defer ctx.teardownVPP() 46 47 release := ctx.versionInfo.Release() 48 if release < "20.09" { 49 t.Skipf("Wireguard: skipped for VPP < 20.09 (%s)", release) 50 } 51 52 ifHandler := ifplugin_vppcalls.CompatibleInterfaceVppHandler(ctx.vppClient, logrus.NewLogger("test")) 53 ifIndexes := ifaceidx.NewIfaceIndex(logrus.NewLogger("test"), "test-ifidx") 54 55 tests := []testEntry{ 56 { 57 name: "Create Wireguard tunnel (IPv4)", 58 wgInt: &interfaces.WireguardLink{ 59 PrivateKey: "gIjXzrQfIFf80d0O8Hd2KhcfkKLRncc+8C70OjotIW8=", 60 Port: 12312, 61 SrcAddr: "10.10.0.1", 62 }, 63 shouldFail: false, 64 }, 65 { 66 name: "Create Wireguard tunnel with invalid privateKey", 67 wgInt: &interfaces.WireguardLink{ 68 PrivateKey: "d0O8Hd2KhcfkKLRncc+8C70OjotIW8=", 69 Port: 12312, 70 SrcAddr: "10.10.0.1", 71 }, 72 shouldFail: true, 73 }, 74 { 75 name: "Create Wireguard 2 tunnels (IPv4)", 76 wgInt: &interfaces.WireguardLink{ 77 PrivateKey: "gIjXzrQfIFf80d0O8Hd2KhcfkKLRncc+8C70OjotIW8=", 78 Port: 12322, 79 SrcAddr: "10.10.0.1", 80 }, 81 wgInt2: &interfaces.WireguardLink{ 82 PrivateKey: "qDUQL8I5RNMWfbi3qgFs237FYD+SyZTj5g0Ix3qRvGs=", 83 Port: 12323, 84 SrcAddr: "10.11.0.1", 85 }, 86 shouldFail: false, 87 }, 88 { 89 name: "Create Wireguard tunnel with peer", 90 wgInt: &interfaces.WireguardLink{ 91 PrivateKey: "gIjXzrQfIFf80d0O8Hd2KhcfkKLRncc+8C70OjotIW8=", 92 Port: 12332, 93 SrcAddr: "10.10.0.1", 94 }, 95 peer: &wg.Peer{ 96 PublicKey: "dIjXzrQfIFf80d0O8Hd2KhcfkKLRncc+8C70OjotIW8=", 97 WgIfName: "wg3", 98 Port: 12314, 99 PersistentKeepalive: 10, 100 Endpoint: "10.10.0.2", 101 Flags: 0, 102 AllowedIps: []string{"10.10.0.0/24"}, 103 }, 104 shouldFail: false, 105 }, 106 { 107 name: "Create Wireguard tunnel with 2 itfs and 2 peers", 108 wgInt: &interfaces.WireguardLink{ 109 PrivateKey: "gIjXzrQfIFf80d0O8Hd2KhcfkKLRncc+8C70OjotIW8=", 110 Port: 12342, 111 SrcAddr: "10.10.0.1", 112 }, 113 wgInt2: &interfaces.WireguardLink{ 114 PrivateKey: "qDUQL8I5RNMWfbi3qgFs237FYD+SyZTj5g0Ix3qRvGs=", 115 Port: 12343, 116 SrcAddr: "10.11.0.1", 117 }, 118 peer: &wg.Peer{ 119 PublicKey: "dIjXzrQfIFf80d0O8Hd2KhcfkKLRncc+8C70OjotIW8=", 120 WgIfName: "wg4", 121 Port: 12314, 122 PersistentKeepalive: 10, 123 Endpoint: "10.10.0.2", 124 Flags: 0, 125 AllowedIps: []string{"10.10.0.0/24"}, 126 }, 127 peer2: &wg.Peer{ 128 PublicKey: "33GyVvUQalLCscTfN8TxtTp/ixtSWg55PhHy0aWABHQ=", 129 WgIfName: "wg4-2", 130 Port: 12314, 131 PersistentKeepalive: 10, 132 Endpoint: "10.11.0.2", 133 Flags: 0, 134 AllowedIps: []string{"10.11.0.0/24"}, 135 }, 136 shouldFail: false, 137 }, 138 } 139 for i, test := range tests { 140 t.Run(test.name, func(t *testing.T) { 141 if test.skipFor != "" && ctx.versionInfo.Release() == test.skipFor { 142 t.Skipf("SKIP for VPP %s: %s", test.skipFor, test.skip) 143 } 144 145 ifIndexes.Clear() 146 147 ifName := fmt.Sprintf("wg%d", i) 148 ifIdx, err := ifHandler.AddWireguardTunnel(ifName, test.wgInt) 149 150 ifIndexes.Put(ifName, &ifaceidx.IfaceMetadata{ 151 SwIfIndex: ifIdx, 152 }) 153 154 if err != nil { 155 if test.shouldFail { 156 return 157 } 158 t.Fatalf("create Wireguard tunnel failed: %v\n", err) 159 } else { 160 if test.shouldFail && test.wgInt2 == nil { 161 t.Fatal("create Wireguard tunnel must fail, but it's not") 162 } 163 } 164 165 var ( 166 ifName2 string 167 ifIdx2 uint32 168 ) 169 if test.wgInt2 != nil { 170 ifName2 := fmt.Sprintf("wg%d-2", i) 171 ifIdx2, err = ifHandler.AddWireguardTunnel(ifName2, test.wgInt2) 172 ifIndexes.Put(ifName2, &ifaceidx.IfaceMetadata{ 173 SwIfIndex: ifIdx2, 174 }) 175 176 if err != nil { 177 if test.shouldFail { 178 return 179 } 180 t.Fatalf("create Wireguard tunnel failed: %v\n", err) 181 } else { 182 if test.shouldFail { 183 t.Fatal("create Wireguard tunnel must fail, but it's not") 184 } 185 } 186 } 187 188 ifaces, err := ifHandler.DumpInterfaces(ctx.Ctx) 189 if err != nil { 190 t.Fatalf("dumping interfaces failed: %v", err) 191 } 192 193 t.Logf("DumpInterfaces:\n%v\n", pretty(ifaces)) 194 195 iface, ok := ifaces[ifIdx] 196 if !ok { 197 t.Fatalf("Wireguard interface was not found in dump") 198 } 199 if test.wgInt2 != nil { 200 _, ok := ifaces[ifIdx2] 201 if !ok { 202 t.Fatalf("Wireguard interface2 was not found in dump") 203 } 204 } 205 206 err = peersTest(&test, ifIndexes, ctx) 207 if err != nil { 208 t.Fatalf("Peers failed: %v", err) 209 } 210 211 if iface.Interface.GetType() != interfaces.Interface_WIREGUARD_TUNNEL { 212 t.Fatalf("Interface is not an Wireguard tunnel") 213 } 214 215 wgLink := iface.Interface.GetWireguard() 216 if test.wgInt.SrcAddr != wgLink.SrcAddr { 217 t.Fatalf("expected source address <%s>, got: <%s>", test.wgInt.SrcAddr, wgLink.SrcAddr) 218 } 219 220 err = ifHandler.DeleteWireguardTunnel(ifName, ifIdx) 221 if err != nil { 222 t.Fatalf("delete Wireguard tunnel failed: %v\n", err) 223 } 224 if test.wgInt2 != nil { 225 err = ifHandler.DeleteWireguardTunnel(ifName2, ifIdx2) 226 if err != nil { 227 t.Fatalf("delete Wireguard tunnel failed: %v\n", err) 228 } 229 } 230 231 ifaces, err = ifHandler.DumpInterfaces(ctx.Ctx) 232 if err != nil { 233 t.Fatalf("dumping interfaces failed: %v", err) 234 } 235 236 if _, ok := ifaces[ifIdx]; ok { 237 t.Fatalf("Wireguard interface was found in dump after removing") 238 } 239 if test.wgInt2 != nil { 240 if _, ok := ifaces[ifIdx2]; ok { 241 t.Fatalf("Wireguard interface2 was found in dump after removing") 242 } 243 } 244 }) 245 } 246 } 247 248 func peersTest(test *testEntry, ifIdx ifaceidx.IfaceMetadataIndex, ctx *TestCtx) (err error) { 249 if test.peer == nil { 250 return err 251 } 252 253 wgHandler := wgplugin_vppcalls.CompatibleWgVppHandler(ctx.vppClient, ifIdx, logrus.NewLogger("test")) 254 if wgHandler == nil { 255 return fmt.Errorf("no compatible wireguard handler") 256 } 257 peerIdx1, err := wgHandler.AddPeer(test.peer) 258 259 if err != nil { 260 if test.shouldFail { 261 return 262 } 263 return err 264 } else { 265 if test.shouldFail && test.peer2 == nil { 266 return fmt.Errorf("create peer must fail, but it's not") 267 } 268 } 269 270 var ( 271 peerIdx2 uint32 272 ) 273 if test.peer2 != nil { 274 peerIdx2, err = wgHandler.AddPeer(test.peer2) 275 276 if err != nil { 277 if test.shouldFail { 278 return 279 } 280 return err 281 } else { 282 if test.shouldFail { 283 return fmt.Errorf("create peer must fail, but it's not") 284 } 285 } 286 } 287 288 peers, err := wgHandler.DumpWgPeers() 289 if err != nil { 290 return err 291 } 292 peer := peers[peerIdx1] 293 294 ctx.t.Logf("DumpWgPeers:\n%+v\n", peers) 295 296 if test.peer2 != nil { 297 if len(peers) != 2 { 298 return fmt.Errorf("expected 2 peers in dump, got %d", len(peers)) 299 } 300 } else { 301 if len(peers) != 1 { 302 return fmt.Errorf("expected 1 peer in dump, got %d", len(peers)) 303 } 304 } 305 306 if test.peer.PublicKey != peer.PublicKey { 307 return fmt.Errorf("expected source address <%s>, got: <%s>", test.peer.PublicKey, peer.PublicKey) 308 } 309 310 err = wgHandler.RemovePeer(peerIdx1) 311 if err != nil { 312 return fmt.Errorf("delete peer failed: %v\n", err) 313 } 314 if test.peer2 != nil { 315 err = wgHandler.RemovePeer(peerIdx2) 316 if err != nil { 317 return fmt.Errorf("delete peer failed: %v\n", err) 318 } 319 } 320 321 peers, err = wgHandler.DumpWgPeers() 322 if err != nil { 323 return err 324 } 325 326 if len(peers) != 0 { 327 return fmt.Errorf("expected 0 peers in dump, got %d", len(peers)) 328 } 329 330 return 331 }