forked from antrea-io/antrea
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ipsec_test.go
148 lines (129 loc) · 4.99 KB
/
ipsec_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2019 Antrea Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package e2e
import (
"fmt"
"regexp"
"strconv"
"testing"
"time"
"k8s.io/apimachinery/pkg/util/wait"
"github.com/vmware-tanzu/antrea/pkg/agent/util"
)
func (data *TestData) readSecurityAssociationsStatus(nodeName string) (up int, connecting int, err error) {
antreaPodName, err := data.getAntreaPodOnNode(nodeName)
if err != nil {
return 0, 0, err
}
cmd := []string{"ipsec", "status"}
stdout, stderr, err := data.runCommandFromPod(antreaNamespace, antreaPodName, "antrea-ipsec", cmd)
if err != nil {
return 0, 0, fmt.Errorf("error when running 'ipsec status' on '%s': %v - stdout: %s - stderr: %s", nodeName, err, stdout, stderr)
}
re := regexp.MustCompile(`Security Associations \((\d+) up, (\d+) connecting\)`)
matches := re.FindStringSubmatch(stdout)
if len(matches) == 0 {
return 0, 0, fmt.Errorf("unexpected 'ipsec status' output: %s", stdout)
}
if v, err := strconv.ParseUint(matches[1], 10, 32); err != nil {
return 0, 0, fmt.Errorf("error when retrieving 'up' SAs from 'ipsec status' output: %v", err)
} else {
up = int(v)
}
if v, err := strconv.ParseUint(matches[2], 10, 32); err != nil {
return 0, 0, fmt.Errorf("error when retrieving 'connecting' SAs from 'ipsec status' output: %v", err)
} else {
connecting = int(v)
}
return up, connecting, nil
}
// TestIPSecTunnelConnectivity checks that Pod traffic across two Nodes over
// the IPSec tunnel, by creating multiple Pods across distinct Nodes and having
// them ping each other.
func TestIPSecTunnelConnectivity(t *testing.T) {
skipIfProviderIs(t, "kind", "IPSec tunnel does not work with Kind")
skipIfIPv6Cluster(t)
skipIfNumNodesLessThan(t, 2)
data, err := setupTest(t)
if err != nil {
t.Fatalf("Error when setting up test: %v", err)
}
defer teardownTest(t, data)
t.Logf("Redeploy Antrea with IPSec tunnel enabled")
data.redeployAntrea(t, true)
data.testPodConnectivityDifferentNodes(t)
// We know that testPodConnectivityDifferentNodes always creates a Pod on Node 0 for the
// inter-Node ping test.
nodeName := nodeName(0)
if up, _, err := data.readSecurityAssociationsStatus(nodeName); err != nil {
t.Errorf("Error when reading Security Associations: %v", err)
} else if up == 0 {
t.Errorf("Expected at least one 'up' Security Association, but got %d", up)
} else {
t.Logf("Found %d 'up' SecurityAssociation(s) for Node '%s'", up, nodeName)
}
// Restore normal Antrea deployment with IPSec disabled.
data.redeployAntrea(t, false)
}
// TestIPSecDeleteStaleTunnelPorts checks that when switching from IPsec mode to
// non-encrypted mode, the previously created tunnel ports are deleted
// correctly.
func TestIPSecDeleteStaleTunnelPorts(t *testing.T) {
skipIfProviderIs(t, "kind", "IPSec tunnel does not work with Kind")
skipIfIPv6Cluster(t)
skipIfNumNodesLessThan(t, 2)
data, err := setupTest(t)
if err != nil {
t.Fatalf("Error when setting up test: %v", err)
}
defer teardownTest(t, data)
t.Logf("Redeploy Antrea with IPSec tunnel enabled")
data.redeployAntrea(t, true)
nodeName0 := nodeName(0)
nodeName1 := nodeName(1)
antreaPodName := func() string {
antreaPodName, err := data.getAntreaPodOnNode(nodeName0)
if err != nil {
t.Fatalf("Error when retrieving the name of the Antrea Pod running on Node '%s': %v", nodeName0, err)
}
t.Logf("The Antrea Pod for Node '%s' is '%s'", nodeName0, antreaPodName)
return antreaPodName
}
portName := util.GenerateNodeTunnelInterfaceName(nodeName1)
doesOVSPortExist := func() bool {
exists, err := data.doesOVSPortExist(antreaPodName(), portName)
if err != nil {
t.Fatalf("Cannot determine if OVS port exists: %v", err)
}
return exists
}
t.Logf("Checking that tunnel port has been created")
if err := wait.PollImmediate(1*time.Second, defaultTimeout, func() (found bool, err error) {
return doesOVSPortExist(), nil
}); err == wait.ErrWaitTimeout {
t.Fatalf("Timed out while waiting for OVS tunnel port to be created")
} else if err != nil {
t.Fatalf("Error while waiting for OVS tunnel port to be created")
}
t.Logf("Redeploy Antrea with IPSec tunnel disabled")
data.redeployAntrea(t, false)
t.Logf("Checking that tunnel port has been deleted")
if err := wait.PollImmediate(1*time.Second, defaultTimeout, func() (found bool, err error) {
return !doesOVSPortExist(), nil
}); err == wait.ErrWaitTimeout {
t.Fatalf("Timed out while waiting for OVS tunnel port to be deleted")
} else if err != nil {
t.Fatalf("Error while waiting for OVS tunnel port to be deleted")
}
}