Repository: jkroepke/openvpn-auth-oauth2
Pull request #199 (2024-02-27 20:49:23)

Log client IP
#### What this PR does / why we need it

#### Which issue this PR fixes

*(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #

- fixes #

#### Special notes for your reviewer

#### Particularly user-facing changes

#### Checklist

Complete these before marking the PR as `ready to review`:

<!-- [Place an '[x]' (no spaces) in all applicable fields.] -->

- [ ] [DCO](https://github.com/prometheus-community/helm-charts/blob/main/CONTRIBUTING.md#sign-off-your-work) signed
- [ ] The PR title has a summary of the changes
- [ ] The PR body has a summary to reflect any significant (and particularly user-facing) changes introduced by this PR


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/jkroepke/openvpn-auth-oauth2/pull/199?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke) Report
Attention: Patch coverage is `92.00000%` with `2 lines` in your changes are missing coverage. Please review.
> Project coverage is 83.78%. Comparing base [(`97be0d2`)](https://app.codecov.io/gh/jkroepke/openvpn-auth-oauth2/commit/97be0d2acbdaa44910955c3eb7e146f6b78d3ae2?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke) to head [(`27ccda5`)](https://app.codecov.io/gh/jkroepke/openvpn-auth-oauth2/pull/199?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke).

| [Files](https://app.codecov.io/gh/jkroepke/openvpn-auth-oauth2/pull/199?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke) | Patch % | Lines |
|---|---|---|
| [internal/openvpn/connection/client.go](https://app.codecov.io/gh/jkroepke/openvpn-auth-oauth2/pull/199?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke#diff-aW50ZXJuYWwvb3BlbnZwbi9jb25uZWN0aW9uL2NsaWVudC5nbw==) | 0.00% | [2 Missing :warning: ](https://app.codecov.io/gh/jkroepke/openvpn-auth-oauth2/pull/199?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #199      +/-   ##
==========================================
- Coverage   83.79%   83.78%   -0.02%     
==========================================
  Files          46       46              
  Lines        2074     2085      +11     
==========================================
+ Hits         1738     1747       +9     
- Misses        226      228       +2     
  Partials      110      110              
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/jkroepke/openvpn-auth-oauth2/pull/199?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Jan-Otto+Kr%C3%B6pke).


Patch:
diff --git a/internal/oauth2/handler.go b/internal/oauth2/handler.go
index acb3603..01d92a1 100644
--- a/internal/oauth2/handler.go
+++ b/internal/oauth2/handler.go
@@ -67,6 +67,7 @@ func (p *Provider) oauth2Start() http.Handler {
 		}
 
 		logger := p.logger.With(
+			slog.String("ip", fmt.Sprintf("%s:%s", session.IPAddr, session.IPPort)),
 			slog.Uint64("cid", session.Client.CID),
 			slog.Uint64("kid", session.Client.KID),
 			slog.String("common_name", session.CommonName),
@@ -125,8 +126,8 @@ func checkClientIPAddr(r *http.Request, logger *slog.Logger, session state.State
 		}
 	}
 
-	if clientIP != session.Ipaddr {
-		reason := utils.StringConcat("http client ip ", clientIP, " and vpn ip ", session.Ipaddr, " is different.")
+	if clientIP != session.IPAddr {
+		reason := utils.StringConcat("http client ip ", clientIP, " and vpn ip ", session.IPAddr, " is different.")
 		logger.Warn(reason)
 
 		return false, http.StatusForbidden, reason
@@ -158,6 +159,7 @@ func (p *Provider) oauth2Callback() http.Handler {
 		}
 
 		logger := p.logger.With(
+			slog.String("ip", fmt.Sprintf("%s:%s", session.IPAddr, session.IPPort)),
 			slog.Uint64("cid", session.Client.CID),
 			slog.Uint64("kid", session.Client.KID),
 			slog.String("session_id", session.Client.SessionID),
diff --git a/internal/oauth2/provider.go b/internal/oauth2/provider.go
index 97835de..aa6bb6e 100644
--- a/internal/oauth2/provider.go
+++ b/internal/oauth2/provider.go
@@ -234,6 +234,7 @@ func errorHandler(
 	session := state.NewEncoded(encryptedSession)
 	if err := session.Decode(conf.HTTP.Secret.String()); err == nil {
 		logger = logger.With(
+			slog.String("ip", fmt.Sprintf("%s:%s", session.IPAddr, session.IPPort)),
 			slog.Uint64("cid", session.Client.CID),
 			slog.Uint64("kid", session.Client.KID),
 			slog.String("common_name", session.CommonName),
diff --git a/internal/oauth2/providers/generic/check.go b/internal/oauth2/providers/generic/check.go
index 532496d..2ad0f82 100644
--- a/internal/oauth2/providers/generic/check.go
+++ b/internal/oauth2/providers/generic/check.go
@@ -109,9 +109,9 @@ func (p *Provider) CheckIPAddress(session state.State, tokens *oidc.Tokens[*idto
 		return fmt.Errorf("%w: ipaddr", ErrMissingClaim)
 	}
 
-	if tokens.IDTokenClaims.IPAddr != session.Ipaddr {
+	if tokens.IDTokenClaims.IPAddr != session.IPAddr {
 		return fmt.Errorf("ipaddr %w: openvpn client: %s - oidc token: %s",
-			ErrMismatch, tokens.IDTokenClaims.IPAddr, session.Ipaddr)
+			ErrMismatch, tokens.IDTokenClaims.IPAddr, session.IPAddr)
 	}
 
 	return nil
diff --git a/internal/oauth2/refresh.go b/internal/oauth2/refresh.go
index ff244ea..b3c8976 100644
--- a/internal/oauth2/refresh.go
+++ b/internal/oauth2/refresh.go
@@ -53,7 +53,7 @@ func (p *Provider) RefreshClientAuth(logger *slog.Logger, client connection.Clie
 		return false, fmt.Errorf("error from token exchange: %w", err)
 	}
 
-	session := state.New(state.ClientIdentifier{CID: client.CID, KID: client.KID}, client.IPAddr, client.CommonName)
+	session := state.New(state.ClientIdentifier{CID: client.CID, KID: client.KID}, client.IPAddr, client.IPPort, client.CommonName)
 
 	user, err := p.OIDC.GetUser(ctx, tokens)
 	if err != nil {
diff --git a/internal/openvpn/client.go b/internal/openvpn/client.go
index 60679e2..168690c 100644
--- a/internal/openvpn/client.go
+++ b/internal/openvpn/client.go
@@ -32,6 +32,7 @@ func (c *Client) processClient(client connection.Client) error {
 // clientConnect handles CONNECT events from OpenVPN management interface.
 func (c *Client) clientConnect(client connection.Client) error {
 	logger := c.logger.With(
+		slog.String("ip", fmt.Sprintf("%s:%s", client.IPAddr, client.IPPort)),
 		slog.Uint64("cid", client.CID),
 		slog.Uint64("kid", client.KID),
 		slog.String("common_name", client.CommonName),
@@ -48,6 +49,7 @@ func (c *Client) clientConnect(client connection.Client) error {
 // clientReauth handles REAUTH events from OpenVPN management interface.
 func (c *Client) clientReauth(client connection.Client) error {
 	logger := c.logger.With(
+		slog.String("ip", fmt.Sprintf("%s:%s", client.IPAddr, client.IPPort)),
 		slog.Uint64("cid", client.CID),
 		slog.Uint64("kid", client.KID),
 		slog.String("common_name", client.CommonName),
@@ -77,12 +79,7 @@ func (c *Client) handleClientAuthentication(logger *slog.Logger, client connecti
 
 	commonName := utils.TransformCommonName(c.conf.OpenVpn.CommonName.Mode, client.CommonName)
 
-	var ipAddr string
-	if c.conf.OAuth2.Validate.IPAddr {
-		ipAddr = client.IPAddr
-	}
-
-	session := state.New(ClientIdentifier, ipAddr, commonName)
+	session := state.New(ClientIdentifier, client.IPAddr, client.IPPort, commonName)
 	if err := session.Encode(c.conf.HTTP.Secret.String()); err != nil {
 		return fmt.Errorf("error encoding state: %w", err)
 	}
@@ -151,6 +148,8 @@ func (c *Client) checkReauth(logger *slog.Logger, client connection.Client) bool
 func (c *Client) clientEstablished(client connection.Client) {
 	c.logger.LogAttrs(context.Background(),
 		slog.LevelInfo, "client established",
+		slog.String("ip", fmt.Sprintf("%s:%s", client.IPAddr, client.IPPort)),
+		slog.String("vpn_ip", client.VPNAddress),
 		slog.Uint64("cid", client.CID),
 		slog.String("common_name", client.CommonName),
 		slog.String("reason", client.Reason),
@@ -161,6 +160,7 @@ func (c *Client) clientEstablished(client connection.Client) {
 
 func (c *Client) clientDisconnect(client connection.Client) {
 	logger := c.logger.With(
+		slog.String("ip", fmt.Sprintf("%s:%s", client.IPAddr, client.IPPort)),
 		slog.Uint64("cid", client.CID),
 		slog.String("common_name", client.CommonName),
 		slog.String("reason", client.Reason),
diff --git a/internal/openvpn/connection/client.go b/internal/openvpn/connection/client.go
index 921aab9..f74ed44 100644
--- a/internal/openvpn/connection/client.go
+++ b/internal/openvpn/connection/client.go
@@ -13,6 +13,8 @@ type Client struct {
 	CID          uint64
 	Reason       string
 	IPAddr       string
+	IPPort       string
+	VPNAddress   string
 	CommonName   string
 	SessionID    string
 	SessionState string
@@ -34,12 +36,23 @@ func NewClient(conf config.Config, message string) (Client, error) { //nolint:cy
 		line, clientMessage, ok = strings.Cut(clientMessage, "\r\n")
 		line = strings.TrimSpace(line)
 
-		if client.Reason == "" && isClientReason(line) {
+		switch {
+		case client.Reason == "" && isClientReason(line):
 			client.Reason, client.CID, client.KID, err = parseClientReason(line)
 			if err != nil {
 				return Client{}, err
 			}
-		} else if strings.HasPrefix(line, ">CLIENT:ENV,") {
+		case strings.HasPrefix(line, ">CLIENT:ADDRESS"):
+			vpnIP, found := strings.CutPrefix(line, ">CLIENT:ADDRESS,")
+			if !found {
+				return Client{}, fmt.Errorf("unable to parse line: %s", line)
+			}
+
+			client.VPNAddress, _, found = strings.Cut(vpnIP, ",")
+			if !found {
+				return Client{}, fmt.Errorf("unable to parse line: %s", line)
+			}
+		case strings.HasPrefix(line, ">CLIENT:ENV,"):
 			envKey, envValue := parseClientEnv(line)
 			if envKey == "" || envValue == "" {
 				continue
@@ -50,6 +63,8 @@ func NewClient(conf config.Config, message string) (Client, error) { //nolint:cy
 				client.IPAddr = envValue
 			case "untrusted_ip6":
 				client.IPAddr = envValue
+			case "untrusted_port":
+				client.IPPort = envValue
 			case conf.OpenVpn.CommonName.EnvironmentVariableName:
 				client.CommonName = envValue
 			case "IV_SSO":
diff --git a/internal/state/state.go b/internal/state/state.go
index 4d02950..9f1d7a4 100644
--- a/internal/state/state.go
+++ b/internal/state/state.go
@@ -13,7 +13,8 @@ import (
 
 type State struct {
 	Client     ClientIdentifier
-	Ipaddr     string
+	IPAddr     string
+	IPPort     string
 	CommonName string
 	Issued     int64
 
@@ -28,10 +29,11 @@ type ClientIdentifier struct {
 	AuthControlFile      string
 }
 
-func New(client ClientIdentifier, ipaddr, commonName string) State {
+func New(client ClientIdentifier, ipAddr, ipPort, commonName string) State {
 	return State{
 		Client:     client,
-		Ipaddr:     ipaddr,
+		IPAddr:     ipAddr,
+		IPPort:     ipPort,
 		CommonName: commonName,
 		Issued:     time.Now().Round(time.Second).Unix(),
 	}
@@ -64,7 +66,8 @@ func (state *State) Decode(secretKey string) error {
 		&state.Client.AuthFailedReasonFile,
 		&state.Client.AuthControlFile,
 		&state.Client.SessionID,
-		&state.Ipaddr,
+		&state.IPAddr,
+		&state.IPPort,
 		&state.CommonName,
 		&state.Issued,
 	)
@@ -75,7 +78,8 @@ func (state *State) Decode(secretKey string) error {
 	state.Client.AuthFailedReasonFile = decodeString(state.Client.AuthFailedReasonFile)
 	state.Client.AuthControlFile = decodeString(state.Client.AuthControlFile)
 	state.Client.SessionID = decodeString(state.Client.SessionID)
-	state.Ipaddr = decodeString(state.Ipaddr)
+	state.IPAddr = decodeString(state.IPAddr)
+	state.IPPort = decodeString(state.IPPort)
 	state.CommonName = decodeString(state.CommonName)
 
 	issuedSince := time.Since(time.Unix(state.Issued, 0))
@@ -103,7 +107,9 @@ func (state *State) Encode(secretKey string) error {
 	data.WriteString(" ")
 	data.WriteString(encodeString(state.Client.SessionID))
 	data.WriteString(" ")
-	data.WriteString(encodeString(state.Ipaddr))
+	data.WriteString(encodeString(state.IPAddr))
+	data.WriteString(" ")
+	data.WriteString(encodeString(state.IPPort))
 	data.WriteString(" ")
 	data.WriteString(encodeString(state.CommonName))
 	data.WriteString(" ")
diff --git a/pkg/plugin/client.go b/pkg/plugin/client.go
index d554d1a..107eed4 100644
--- a/pkg/plugin/client.go
+++ b/pkg/plugin/client.go
@@ -14,6 +14,7 @@ type Client struct {
 	AuthPendingFile      string
 	AuthControlFile      string
 	IpAddr               string
+	IpPort               string
 	CommonName           string
 }
 
@@ -34,6 +35,8 @@ func NewClient(pointer unsafe.Pointer) Client {
 			client.IpAddr = envParts[1]
 		case "untrusted_ip6":
 			client.IpAddr = envParts[1]
+		case "untrusted_port":
+			client.IpPort = envParts[1]
 		case "common_name":
 			client.CommonName = envParts[1]
 		default:
diff --git a/pkg/plugin/plugin.go b/pkg/plugin/plugin.go
index df1238f..feb75f0 100644
--- a/pkg/plugin/plugin.go
+++ b/pkg/plugin/plugin.go
@@ -126,7 +126,7 @@ func openvpn_plugin_func_v3_go(v3structver C.int, args *C.struct_openvpn_plugin_
 		AuthControlFile:      client.AuthControlFile,
 		AuthFailedReasonFile: client.AuthFailedReasonFile,
 	}
-	session := state.New(clientIdentifier, client.IpAddr, client.CommonName)
+	session := state.New(clientIdentifier, client.IpAddr, client.IpPort, client.CommonName)
 	if err := session.Encode(handle.conf.HTTP.Secret.String()); err != nil {
 		handle.logger.Error(fmt.Errorf("encoding state: %w", err).Error())
 		return C.OPENVPN_PLUGIN_FUNC_ERROR


Test patch:
diff --git a/internal/oauth2/handler_test.go b/internal/oauth2/handler_test.go
index fa2756b..41eb7fa 100644
--- a/internal/oauth2/handler_test.go
+++ b/internal/oauth2/handler_test.go
@@ -376,7 +376,7 @@ func TestHandler(t *testing.T) {
 			session := tt.state
 
 			if tt.state == "-" {
-				sessionState := state.New(state.ClientIdentifier{CID: 0, KID: 1}, tt.ipaddr, "name")
+				sessionState := state.New(state.ClientIdentifier{CID: 0, KID: 1}, tt.ipaddr, "12345", "name")
 				require.NoError(t, sessionState.Encode(tt.conf.HTTP.Secret.String()))
 
 				session = sessionState.Encoded()
diff --git a/internal/oauth2/providers/generic/check_test.go b/internal/oauth2/providers/generic/check_test.go
index 71291c7..3e5a223 100644
--- a/internal/oauth2/providers/generic/check_test.go
+++ b/internal/oauth2/providers/generic/check_test.go
@@ -354,7 +354,7 @@ func TestValidateIpAddr(t *testing.T) {
 			}
 
 			session := state.State{
-				Ipaddr: tt.requiredIPAddr,
+				IPAddr: tt.requiredIPAddr,
 			}
 
 			provider, err := generic.NewProvider(context.Background(), conf, http.DefaultClient)
diff --git a/internal/openvpn/connection/client_test.go b/internal/openvpn/connection/client_test.go
index 9cad7fc..0f21677 100644
--- a/internal/openvpn/connection/client_test.go
+++ b/internal/openvpn/connection/client_test.go
@@ -24,16 +24,21 @@ func TestNewClientConnection(t *testing.T) {
 			"client CONNECT",
 			config.Defaults,
 			[]string{
+				">CLIENT:ADDRESS,127.0.1.1,1",
 				">CLIENT:CONNECT,0,1",
 				">CLIENT:ENV,common_name=common_name",
 				">CLIENT:ENV,username=username",
 				">CLIENT:ENV,untrusted_ip=127.0.0.1",
+				">CLIENT:ENV,untrusted_port=12345",
 				">CLIENT:ENV,IV_SSO=webauth",
 				">CLIENT:ENV,session_id=K3waLcCGyUuzkdXh",
 				">CLIENT:ENV,END",
 			},
 			connection.Client{
-				CID: 0, KID: 1, Reason: "CONNECT", CommonName: "common_name", IPAddr: "127.0.0.1", IvSSO: "webauth", SessionID: "K3waLcCGyUuzkdXh",
+				CID: 0, KID: 1, Reason: "CONNECT", CommonName: "common_name",
+				IPAddr: "127.0.0.1", IPPort: "12345",
+				VPNAddress: "127.0.1.1", IvSSO: "webauth",
+				SessionID: "K3waLcCGyUuzkdXh",
 			},
 			"",
 		},
@@ -119,6 +124,34 @@ func TestNewClientConnection(t *testing.T) {
 			},
 			"",
 		},
+		{
+			"invalid CLIENT:ADDRESS line",
+			config.Defaults,
+			[]string{
+				">CLIENT:ADDRESS,127.0.0.1",
+				">CLIENT:CR_RESPONSE,1,2,YmFzZTY0",
+				">CLIENT:ENV,name1=val1",
+				">CLIENT:ENV,END",
+			},
+			connection.Client{
+				CID: 1, KID: 2, Reason: "CR_RESPONSE",
+			},
+			"unable to parse line: >CLIENT:ADDRESS,127.0.0.1",
+		},
+		{
+			"invalid CLIENT:ADDRESS line 2",
+			config.Defaults,
+			[]string{
+				">CLIENT:ADDRESS",
+				">CLIENT:CR_RESPONSE,1,2,YmFzZTY0",
+				">CLIENT:ENV,name1=val1",
+				">CLIENT:ENV,END",
+			},
+			connection.Client{
+				CID: 1, KID: 2, Reason: "CR_RESPONSE",
+			},
+			"unable to parse line: >CLIENT:ADDRESS",
+		},
 		{
 			"client invalid reason",
 			config.Defaults,
diff --git a/internal/openvpn/main_test.go b/internal/openvpn/main_test.go
index 87ea222..0a783f2 100644
--- a/internal/openvpn/main_test.go
+++ b/internal/openvpn/main_test.go
@@ -312,7 +312,7 @@ func TestClientFull(t *testing.T) {
 					assert.Equal(t, uint64(1), sessionState.Client.CID)
 					assert.Equal(t, uint64(2), sessionState.Client.KID)
 					assert.Equal(t, "test", sessionState.CommonName)
-					assert.Equal(t, "127.0.0.1", sessionState.Ipaddr)
+					assert.Equal(t, "127.0.0.1", sessionState.IPAddr)
 				}
 			}()
 
diff --git a/internal/state/bench_test.go b/internal/state/bench_test.go
index a03e7dc..db8660f 100644
--- a/internal/state/bench_test.go
+++ b/internal/state/bench_test.go
@@ -11,7 +11,7 @@ func BenchmarkState(b *testing.B) {
 	b.StopTimer()
 
 	encryptionKey := testutils.Secret
-	token := state.New(state.ClientIdentifier{CID: 9223372036854775807, KID: 2}, "127.0.0.1", "test")
+	token := state.New(state.ClientIdentifier{CID: 9223372036854775807, KID: 2}, "127.0.0.1", "12345", "test")
 
 	b.StartTimer()
 
diff --git a/internal/state/state_test.go b/internal/state/state_test.go
index dbcc1b9..b6dbb41 100644
--- a/internal/state/state_test.go
+++ b/internal/state/state_test.go
@@ -16,7 +16,7 @@ func TestState(t *testing.T) {
 	encryptionKey := testutils.Secret
 
 	for i := 1; i < 50; i++ {
-		token := state.New(state.ClientIdentifier{CID: 9223372036854775807, KID: 2}, "127.0.0.1", "test")
+		token := state.New(state.ClientIdentifier{CID: 9223372036854775807, KID: 2}, "127.0.0.1", "12345", "test")
 		require.NoError(t, token.Encode(encryptionKey))
 
 		encodedToken := state.NewEncoded(token.Encoded())
@@ -24,7 +24,7 @@ func TestState(t *testing.T) {
 
 		assert.Equal(t, token.Client.CID, encodedToken.Client.CID)
 		assert.Equal(t, token.Client.KID, encodedToken.Client.KID)
-		assert.Equal(t, token.Ipaddr, encodedToken.Ipaddr)
+		assert.Equal(t, token.IPAddr, encodedToken.IPAddr)
 		assert.Equal(t, token.CommonName, encodedToken.CommonName)
 	}
 }
@@ -34,7 +34,7 @@ func TestStateWithEmptyValues(t *testing.T) {
 
 	encryptionKey := testutils.Secret
 
-	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "")
+	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "12345", "")
 	require.NoError(t, token.Encode(encryptionKey))
 
 	encodedToken := state.NewEncoded(token.Encoded())
@@ -42,7 +42,7 @@ func TestStateWithEmptyValues(t *testing.T) {
 
 	assert.Equal(t, token.Client.CID, encodedToken.Client.CID)
 	assert.Equal(t, token.Client.KID, encodedToken.Client.KID)
-	assert.Equal(t, token.Ipaddr, encodedToken.Ipaddr)
+	assert.Equal(t, token.IPAddr, encodedToken.IPAddr)
 	assert.Equal(t, token.CommonName, encodedToken.CommonName)
 }
 
@@ -51,7 +51,7 @@ func TestStateInvalid_Key(t *testing.T) {
 
 	encryptionKey := "01234567891011"
 
-	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "test")
+	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "12345", "test")
 	require.Error(t, token.Encode(encryptionKey), "crypto/aes: invalid key size 14")
 }
 
@@ -60,7 +60,7 @@ func TestStateInvalid_Future(t *testing.T) {
 
 	encryptionKey := testutils.Secret
 
-	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "test")
+	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "12345", "test")
 	token.Issued = time.Now().Add(time.Hour).Unix()
 
 	require.NoError(t, token.Encode(encryptionKey))
@@ -72,7 +72,7 @@ func TestState_WithSpace(t *testing.T) {
 
 	encryptionKey := testutils.Secret
 
-	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "te st")
+	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "12345", "te st")
 
 	require.NoError(t, token.Encode(encryptionKey))
 
@@ -81,7 +81,7 @@ func TestState_WithSpace(t *testing.T) {
 
 	assert.Equal(t, token.Client.CID, encodedToken.Client.CID)
 	assert.Equal(t, token.Client.KID, encodedToken.Client.KID)
-	assert.Equal(t, token.Ipaddr, encodedToken.Ipaddr)
+	assert.Equal(t, token.IPAddr, encodedToken.IPAddr)
 	assert.Equal(t, token.CommonName, encodedToken.CommonName)
 }
 
@@ -90,7 +90,7 @@ func TestStateInvalid_TooOld(t *testing.T) {
 
 	encryptionKey := testutils.Secret
 
-	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "test")
+	token := state.New(state.ClientIdentifier{CID: 1, KID: 2}, "127.0.0.1", "12345", "test")
 	token.Issued = time.Now().Add(-1 * time.Hour).Unix()
 
 	require.NoError(t, token.Encode(encryptionKey))
diff --git a/tests/docker-compose.yaml b/tests/docker-compose.yaml
index 1a502c8..a3ebe0d 100644
--- a/tests/docker-compose.yaml
+++ b/tests/docker-compose.yaml
@@ -57,8 +57,11 @@ services:
         persist-tun
         explicit-exit-notify
 
-        #verify-client-cert none
-        #username-as-common-name
+        verify-client-cert none
+        username-as-common-name
+
+        status /etc/openvpn/openvpn-status.log
+        ifconfig-pool-persist /etc/openvpn/ipp.txt
 
         tls-cert-profile preferred