-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
revert integration tests, they are on their own pr
- Loading branch information
Showing
2 changed files
with
242 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
#!/bin/sh | ||
# (c) Ain Ghazal 2022 | ||
# this file converts an inline openvpn config file into | ||
# a standalone config plus separate files for the ca.crt, | ||
# cert.pem and key.pem. | ||
|
||
FILE=$1 | ||
tail=0 | ||
|
||
# first lets extract the inline blocks | ||
# ca block | ||
tag=ca | ||
f=ca.crt | ||
sed -n "/<$tag>/,/<\/$tag>/p" $FILE > $f | ||
n=$(wc -l $f | cut -f 1 -d ' ') | ||
tail=$(($tail+n)) | ||
cat $f | tail -n $(($n-1)) | head -n $(($n-2)) | tee $f >/dev/null | ||
|
||
# key block | ||
tag=key | ||
f=key.pem | ||
sed -n "/<$tag>/,/<\/$tag>/p" $FILE > $f | ||
n=$(wc -l $f | cut -f 1 -d ' ') | ||
tail=$(($tail+n)) | ||
cat $f | tail -n $(($n-1)) | head -n $(($n-2)) | tee $f >/dev/null | ||
|
||
# cert block | ||
tag=cert | ||
f=cert.pem | ||
sed -n "/<$tag>/,/<\/$tag>/p" $FILE > $f | ||
n=$(wc -l $f | cut -f 1 -d ' ') | ||
tail=$(($tail+n)) | ||
cat $f | tail -n $(($n-1)) | head -n $(($n-2)) | tee $f >/dev/null | ||
|
||
# tls-auth (ignored) | ||
tag=tls-auth | ||
f=ta.pem | ||
sed -n "/<$tag>/,/<\/$tag>/p" $FILE > $f | ||
n=$(wc -l $f | cut -f 1 -d ' ') | ||
tail=$(($tail+n)) | ||
cat $f | tail -n $(($n-4)) | head -n $(($n-5)) | tee $f >/dev/null | ||
|
||
all=$(wc -l $FILE | cut -f -1 -d ' ') | ||
cp $FILE config.bk | ||
|
||
echo "------------------------" | ||
echo "Config file:" | ||
echo "------------------------" | ||
head -n $(($all-$tail)) $FILE | tee config | ||
echo "------------------------" | ||
|
||
# now enable the paths for ca, cert and key | ||
sed -i "s/;ca ca.crt/ca ca.crt/g" config | ||
sed -i "s/;cert cert.pem/cert cert.pem/g" config | ||
sed -i "s/;key key.pem/key key.pem/g" config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
//build: +integration | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"io/ioutil" | ||
"log" | ||
"net/http" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"testing" | ||
"time" | ||
|
||
"github.com/ory/dockertest/v3" | ||
dc "github.com/ory/dockertest/v3/docker" | ||
|
||
"github.com/ooni/minivpn/extras/ping" | ||
"github.com/ooni/minivpn/vpn" | ||
) | ||
|
||
const ( | ||
parseConfig = "extract.sh" | ||
dockerImage = "ainghazal/openvpn" | ||
dockerTag = "latest" | ||
) | ||
|
||
var ( | ||
target = "172.17.0.1" | ||
count = 3 | ||
) | ||
|
||
func copyFile(src, dst string) error { | ||
input, err := ioutil.ReadFile(src) | ||
if err != nil { | ||
fmt.Println(err) | ||
return nil | ||
} | ||
|
||
dstFile := filepath.Join(dst, src) | ||
err = ioutil.WriteFile(dstFile, input, 0744) | ||
if err != nil { | ||
fmt.Println("Error creating", dstFile) | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func launchDocker(cipher, auth string) ([]byte, *dockertest.Pool, *dockertest.Resource, error) { | ||
pool, err := dockertest.NewPool("") | ||
if err != nil { | ||
log.Fatalf("Could not connect to docker: %s", err) | ||
} | ||
|
||
options := &dockertest.RunOptions{ | ||
Repository: dockerImage, | ||
Tag: dockerTag, | ||
PortBindings: map[dc.Port][]dc.PortBinding{ | ||
"1194/udp": {{HostPort: "1194"}}, | ||
"8080/tcp": {{HostPort: "8080"}}, | ||
}, | ||
Env: []string{"OPENVPN_CIPHER=" + cipher, "OPENVPN_AUTH=" + auth}, | ||
CapAdd: []string{"NET_ADMIN"}, | ||
} | ||
resource, err := pool.RunWithOptions(options) | ||
if err != nil { | ||
log.Fatalf("Could not start resource: %s", err) | ||
} | ||
// exponential backoff-retry, because the application in the container might not be ready to accept connections yet | ||
// the minio client does not do service discovery for you (i.e. it does not check if connection can be established), so we have to use the health check | ||
var config []byte | ||
if err := pool.Retry(func() error { | ||
url := fmt.Sprintf("http://localhost:8080/") | ||
resp, err := http.Get(url) | ||
if err != nil { | ||
return err | ||
} | ||
if resp.StatusCode != http.StatusOK { | ||
return fmt.Errorf("status code not OK") | ||
} | ||
config, err = ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
panic(err) | ||
} | ||
fmt.Println("Got OpenVPN client config") | ||
return nil | ||
}); err != nil { | ||
log.Fatalf("Could not connect to docker: %s", err) | ||
} | ||
return config, pool, resource, nil | ||
} | ||
|
||
func stopContainer(p *dockertest.Pool, res *dockertest.Resource) { | ||
fmt.Println("Stopping container") | ||
if err := p.Purge(res); err != nil { | ||
log.Printf("Could not purge resource: %s\n", err) | ||
} | ||
} | ||
|
||
func TestClientAES256GCM(t *testing.T) { | ||
if testing.Short() { | ||
t.Skip("skipping test in short mode.") | ||
} | ||
tmp := t.TempDir() | ||
|
||
copyFile(parseConfig, tmp) | ||
os.Chdir(tmp) | ||
err := os.Chmod(parseConfig, 0700) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
config, pool, resource, err := launchDocker("AES-256-GCM", "SHA256") | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
// when all test done, time to kill and remove the container | ||
defer stopContainer(pool, resource) | ||
|
||
cfgFile, err := ioutil.TempFile(tmp, "minivpn-e2e-") | ||
defer cfgFile.Close() | ||
if err != nil { | ||
log.Fatal("Cannot create temporary file", err) | ||
} | ||
fmt.Println("Config written to: " + cfgFile.Name()) | ||
|
||
if _, err = cfgFile.Write(config); err != nil { | ||
log.Fatal("Failed to write config to temporary file", err) | ||
} | ||
|
||
// execute the extract.sh shell script, to process key blocks piecewise | ||
cmd := exec.Command("./"+parseConfig, cfgFile.Name()) | ||
cmd.Dir = tmp | ||
var out bytes.Buffer | ||
cmd.Stdout = &out | ||
cmd.Run() | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
c, err := readLines("config") | ||
fmt.Println("Remote:", c[len(c)-1]) | ||
// can assert that this is a remote line | ||
|
||
// actual test begins | ||
opt, err := vpn.NewOptionsFromFilePath(filepath.Join(tmp, "config")) | ||
if err != nil { | ||
log.Fatalf("Could not parse file: %s", err) | ||
} | ||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
defer cancel() | ||
|
||
tunnel := vpn.NewClientFromOptions(opt) | ||
tunnel.Start(ctx) | ||
pinger := ping.New(target, tunnel) | ||
pinger.Count = count | ||
err = pinger.Run(ctx) | ||
defer pinger.Stop() | ||
if err != nil { | ||
log.Fatalf("VPN Error: %s", err) | ||
} | ||
if pinger.PacketLoss() != 0 { | ||
log.Fatalf("packet loss is not zero") | ||
} | ||
// let's assert something wise about the pings | ||
// can we parse the logs? get initialization etc | ||
} | ||
|
||
func readLines(f string) ([]string, error) { | ||
var ll []string | ||
rf, err := os.Open(f) | ||
defer rf.Close() | ||
if err != nil { | ||
return ll, err | ||
} | ||
fs := bufio.NewScanner(rf) | ||
fs.Split(bufio.ScanLines) | ||
for fs.Scan() { | ||
ll = append(ll, fs.Text()) | ||
} | ||
return ll, nil | ||
} |