Skip to content

Commit

Permalink
Use OpenConnect Runner Config in ocrunner
Browse files Browse the repository at this point in the history
Signed-off-by: hwipl <33433250+hwipl@users.noreply.github.com>
  • Loading branch information
hwipl committed Aug 15, 2023
1 parent 0066a0c commit 3b64b3d
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 44 deletions.
4 changes: 2 additions & 2 deletions internal/daemon/daemon.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ func (d *Daemon) handleProfileUpdate() {

// cleanup cleans up after a failed shutdown
func (d *Daemon) cleanup() {
ocrunner.CleanupConnect()
ocrunner.CleanupConnect(ocrunner.NewConfig())
cleanupVPNConfig(vpnDevice)
splitrt.Cleanup()
trafpol.Cleanup()
Expand Down Expand Up @@ -795,7 +795,7 @@ func NewDaemon() *Daemon {

dns: dnsproxy.NewProxy(dnsproxy.NewConfig()),

runner: ocrunner.NewConnect(xmlProfile, vpncScript, vpnDevice),
runner: ocrunner.NewConnect(ocrunner.NewConfig()),

status: vpnstatus.New(),

Expand Down
107 changes: 82 additions & 25 deletions internal/ocrunner/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,14 @@ import (
"fmt"
"os"
"os/exec"
"os/user"
"strconv"
"strings"

log "github.com/sirupsen/logrus"
"github.com/telekom-mms/oc-daemon/pkg/logininfo"
)

const (
// pidFile is the pid file for openconnect
pidFile = "/run/oc-daemon/openconnect.pid"
)

// ConnectEvent is a connect runner event
type ConnectEvent struct {
// Connect indicates connect and disconnect
Expand All @@ -32,19 +28,15 @@ type ConnectEvent struct {

// Connect is a openconnect connection runner
type Connect struct {
// connection runner configuration
config *Config

// openconnect command
command *exec.Cmd

// channel for openconnect exits
exits chan struct{}

// xml profile and vpnc-script paths
profile string
script string

// tunnel device name
device string

// channels for commands from user
commands chan *ConnectEvent
done chan struct{}
Expand All @@ -53,16 +45,79 @@ type Connect struct {
events chan *ConnectEvent
}

// setPIDOwner sets the owner of the pid file
func (c *Connect) setPIDOwner() {
if c.config.PIDOwner == "" {
// do not change owner
return
}

user, err := user.Lookup(c.config.PIDOwner)
if err != nil {
log.WithError(err).Error("OC-Runner could not get UID of pid file owner")
return
}

uid, err := strconv.Atoi(user.Uid)
if err != nil {
log.WithError(err).Error("OC-Runner could not convert UID of pid file owner to int")
return
}

if err := os.Chown(c.config.PIDFile, uid, -1); err != nil {
log.WithError(err).Error("OC-Runner could not change owner of pid file")
}
}

// setPIDGroup sets the group of the pid file
func (c *Connect) setPIDGroup() {
if c.config.PIDGroup == "" {
// do not change group
return
}

group, err := user.LookupGroup(c.config.PIDGroup)
if err != nil {
log.WithError(err).Error("OC-Runner could not get GID of pid file group")
return
}

gid, err := strconv.Atoi(group.Gid)
if err != nil {
log.WithError(err).Error("OC-Runner could not convert GID of pid file group to int")
return
}

if err := os.Chown(c.config.PIDFile, -1, gid); err != nil {
log.WithError(err).Error("OC-Runner could not change group of pid file")
}
}

// savePidFile saves the running command to pid file
func (c *Connect) savePidFile() {
if c.command == nil || c.command.Process == nil {
return
}

// get pid
pid := fmt.Sprintf("%d\n", c.command.Process.Pid)
err := os.WriteFile(pidFile, []byte(pid), 0600)

// convert permissions
perm, err := strconv.ParseUint(c.config.PIDPermissions, 8, 32)
if err != nil {
log.WithError(err).Error("OC-Runner could not convert permissions of pid file to uint")
return
}

// write pid to file with permissions
err = os.WriteFile(c.config.PIDFile, []byte(pid), os.FileMode(perm))
if err != nil {
log.WithError(err).Error("OC-Runner writing pid error")
}

// set owner and group
c.setPIDOwner()
c.setPIDGroup()
}

// handleConnect establishes the connection by starting openconnect
Expand All @@ -80,8 +135,8 @@ func (c *Connect) handleConnect(e *ConnectEvent) {
// openconnect --cookie-on-stdin $HOST --servercert $FINGERPRINT
//
serverCert := fmt.Sprintf("--servercert=%s", e.login.Fingerprint)
xmlConfig := fmt.Sprintf("--xmlconfig=%s", c.profile)
script := fmt.Sprintf("--script=%s", c.script)
xmlConfig := fmt.Sprintf("--xmlconfig=%s", c.config.XMLProfile)
script := fmt.Sprintf("--script=%s", c.config.VPNCScript)
host := e.login.Host
if e.login.ConnectURL != "" {
host = e.login.ConnectURL
Expand All @@ -92,24 +147,28 @@ func (c *Connect) handleConnect(e *ConnectEvent) {
"--cookie-on-stdin",
host,
serverCert,
"--no-proxy",
}
if c.config.NoProxy {
parameters = append(parameters, "--no-proxy")
}
if e.login.Resolve != "" {
resolve := fmt.Sprintf("--resolve=%s", e.login.Resolve)
parameters = append(parameters, resolve)
}
if c.device != "" {
device := fmt.Sprintf("--interface=%s", c.device)
if c.config.VPNDevice != "" {
device := fmt.Sprintf("--interface=%s", c.config.VPNDevice)
parameters = append(parameters, device)
}
parameters = append(parameters, c.config.ExtraArgs...)
c.command = exec.Command("openconnect", parameters...)

// run command, pass login info to stdin
b := bytes.NewBufferString(e.login.Cookie)
c.command.Stdin = b
c.command.Stdout = os.Stdout
c.command.Stderr = os.Stderr
c.command.Env = append(os.Environ(), e.env...)
c.command.Env = append(os.Environ(), c.config.ExtraEnv...)
c.command.Env = append(c.command.Env, e.env...)

if err := c.command.Start(); err != nil {
log.WithError(err).Error("OC-Runner executing connect error")
Expand Down Expand Up @@ -225,11 +284,9 @@ func (c *Connect) Events() chan *ConnectEvent {
}

// NewConnect returns a new Connect
func NewConnect(xmlProfile, vpncScript, device string) *Connect {
func NewConnect(config *Config) *Connect {
return &Connect{
profile: xmlProfile,
script: vpncScript,
device: device,
config: config,

exits: make(chan struct{}),

Expand All @@ -241,9 +298,9 @@ func NewConnect(xmlProfile, vpncScript, device string) *Connect {
}

// CleanupConnect cleans up connect after a failed shutdown
func CleanupConnect() {
func CleanupConnect(config *Config) {
// get pid from file
b, err := os.ReadFile(pidFile)
b, err := os.ReadFile(config.PIDFile)
if err != nil {
return
}
Expand Down
30 changes: 14 additions & 16 deletions internal/ocrunner/connect_test.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
package ocrunner

import "testing"
import (
"reflect"
"testing"
)

// TestConnectStartStop tests Start and Stop of Connect
func TestConnectStartStop(t *testing.T) {
c := NewConnect("", "", "")
c := NewConnect(NewConfig())
c.Start()
c.Stop()
}

// TestConnectDisconnect tests Disconnect of Connect
func TestConnectDisconnect(t *testing.T) {
c := NewConnect("", "", "")
c := NewConnect(NewConfig())
c.Start()
c.Disconnect()
c.Stop()
}

// TestConnectEvents tests Events of Connect
func TestConnectEvents(t *testing.T) {
c := NewConnect("", "", "")
c := NewConnect(NewConfig())

want := c.events
got := c.Events()
Expand All @@ -30,18 +33,13 @@ func TestConnectEvents(t *testing.T) {

// TestNewConnect tests NewConnect
func TestNewConnect(t *testing.T) {
profile := "/some/profile/file"
script := "/some/vpnc/script"
device := "tun999"
c := NewConnect(profile, script, device)
if c.profile != profile {
t.Errorf("got %s, want %s", c.profile, profile)
}
if c.script != script {
t.Errorf("got %s, want %s", c.script, script)
}
if c.device != device {
t.Errorf("got %s, want %s", c.script, script)
config := NewConfig()
config.XMLProfile = "/some/profile/file"
config.VPNCScript = "/some/vpnc/script"
config.VPNDevice = "tun999"
c := NewConnect(config)
if !reflect.DeepEqual(c.config, config) {
t.Errorf("got %v, want %v", c.config, config)
}
if c.exits == nil ||
c.commands == nil ||
Expand Down
5 changes: 4 additions & 1 deletion tools/ocrunner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,10 @@ func main() {
}

// connect client
c := ocrunner.NewConnect(*profile, *script, "oc-daemon-tun0")
ocrConf := ocrunner.NewConfig()
ocrConf.XMLProfile = *profile
ocrConf.VPNCScript = *script
c := ocrunner.NewConnect(ocrConf)
done := make(chan struct{})
go c.Start()
go func() {
Expand Down

0 comments on commit 3b64b3d

Please sign in to comment.