Compare commits

..

7 Commits

Author SHA1 Message Date
Christoph Haas
edfa509828 execute make helm-docs 2026-02-20 19:15:01 +01:00
htiryaki-oe24
2d18776834 Updates chart documentation #629 2026-02-19 23:28:16 +01:00
htiryaki-oe24
ee02916ce5 Fixes minor chart issues #629 2026-02-19 23:19:00 +01:00
h44z
e62db0d62e Merge commit from fork
Some checks failed
Docker / Build and Push (push) Has been cancelled
github-pages / deploy (push) Has been cancelled
Docker / release (push) Has been cancelled
* fix: prevent open redirect in OAuth return URL validation

* reformat check

---------

Co-authored-by: Arne Cools <arne.cools@intigriti.com>
2026-01-29 22:37:16 +01:00
dependabot[bot]
129cd0d408 chore(deps): bump the actions group with 2 updates (#618)
Some checks failed
Docker / Build and Push (push) Has been cancelled
github-pages / deploy (push) Has been cancelled
Docker / release (push) Has been cancelled
Bumps the actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [actions/setup-python](https://github.com/actions/setup-python).


Updates `actions/checkout` from 6.0.1 to 6.0.2
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](8e8c483db8...de0fac2e45)

Updates `actions/setup-python` from 6.1.0 to 6.2.0
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](83679a892e...a309ff8b42)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: actions/setup-python
  dependency-version: 6.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-26 22:24:34 +01:00
h44z
70cc44cc4d feat: add live traffic stats (#530) (#616) 2026-01-26 22:24:10 +01:00
h44z
e53b8c8087 fix: improve import of existing allowed-IPs (#615)
Some checks failed
Docker / Build and Push (push) Has been cancelled
github-pages / deploy (push) Has been cancelled
Docker / release (push) Has been cancelled
2026-01-25 00:33:33 +01:00
9 changed files with 138 additions and 10 deletions

View File

@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }}
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
@@ -35,7 +35,7 @@ jobs:
# ct lint requires Python 3.x to run following packages:
# - yamale (https://github.com/23andMe/Yamale)
# - yamllint (https://github.com/adrienverge/yamllint)
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: '3.x'
@@ -60,7 +60,7 @@ jobs:
permissions:
packages: write
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up QEMU
uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0

View File

@@ -15,11 +15,11 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with:
python-version: 3.x

View File

@@ -8,6 +8,9 @@ spec:
{{- with .Values.revisionHistoryLimit }}
revisionHistoryLimit: {{ . }}
{{- end }}
{{- with .Values.replicas }}
replicas: {{ . }}
{{- end }}
{{- with .Values.strategy }}
strategy: {{- toYaml . | nindent 4 }}
{{- end }}

View File

@@ -15,7 +15,7 @@ spec:
http:
paths:
- path: {{ default "/" (urlParse (tpl .Values.config.web.external_url .)).path }}
pathType: {{ default "ImplementationSpecific" .pathType }}
pathType: {{ default "ImplementationSpecific" .Values.ingress.pathType }}
backend:
service:
name: {{ include "wg-portal.fullname" . }}

View File

@@ -8,6 +8,9 @@ spec:
{{- with .Values.revisionHistoryLimit }}
revisionHistoryLimit: {{ . }}
{{- end }}
{{- with .Values.replicas }}
replicas: {{ . }}
{{- end }}
{{- with .Values.strategy }}
updateStrategy: {{- toYaml . | nindent 4 }}
{{- end }}

View File

@@ -6,7 +6,6 @@ import (
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/go-pkgz/routegroup"
@@ -449,7 +448,17 @@ func (e AuthEndpoint) handleLogoutPost() http.HandlerFunc {
// isValidReturnUrl checks if the given return URL matches the configured external URL of the application.
func (e AuthEndpoint) isValidReturnUrl(returnUrl string) bool {
if !strings.HasPrefix(returnUrl, e.cfg.Web.ExternalUrl) {
expectedUrl, err := url.Parse(e.cfg.Web.ExternalUrl)
if err != nil {
return false
}
returnUrlParsed, err := url.Parse(returnUrl)
if err != nil {
return false
}
if returnUrlParsed.Scheme != expectedUrl.Scheme || returnUrlParsed.Host != expectedUrl.Host {
return false
}

View File

@@ -985,7 +985,26 @@ func (m Manager) importPeer(ctx context.Context, in *domain.Interface, p *domain
peer.InterfaceIdentifier = in.Identifier
peer.EndpointPublicKey = domain.NewConfigOption(in.PublicKey, true)
peer.AllowedIPsStr = domain.NewConfigOption(in.PeerDefAllowedIPsStr, true)
peer.Interface.Addresses = p.AllowedIPs // use allowed IP's as the peer IP's TODO: Should this also match server interface address' prefix length?
// split allowed IP's into interface addresses and extra allowed IP's
var interfaceAddresses []domain.Cidr
var extraAllowedIPs []domain.Cidr
for _, allowedIP := range p.AllowedIPs {
isHost := (allowedIP.IsV4() && allowedIP.NetLength == 32) || (!allowedIP.IsV4() && allowedIP.NetLength == 128)
isNetworkAddr := allowedIP.Addr == allowedIP.NetworkAddr().Addr
// Network addresses (e.g. 10.0.0.0/24) will always be extra allowed IP's.
// For IP addresses, such as 10.0.0.1/24, it is challenging to tell whether it is an interface address or
// an extra allowed IP, therefore we treat such addresses as interface addresses.
if !isHost && isNetworkAddr {
extraAllowedIPs = append(extraAllowedIPs, allowedIP)
} else {
interfaceAddresses = append(interfaceAddresses, allowedIP)
}
}
peer.Interface.Addresses = interfaceAddresses
peer.ExtraAllowedIPsStr = domain.CidrsToString(extraAllowedIPs)
peer.Interface.DnsStr = domain.NewConfigOption(in.PeerDefDnsStr, true)
peer.Interface.DnsSearchStr = domain.NewConfigOption(in.PeerDefDnsSearchStr, true)
peer.Interface.Mtu = domain.NewConfigOption(in.PeerDefMtu, true)

View File

@@ -0,0 +1,94 @@
package wireguard
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/h44z/wg-portal/internal/domain"
)
func TestImportPeer_AddressMapping(t *testing.T) {
tests := []struct {
name string
allowedIPs []string
expectedInterface []string
expectedExtraAllowed string
}{
{
name: "IPv4 host address",
allowedIPs: []string{"10.0.0.1/32"},
expectedInterface: []string{"10.0.0.1/32"},
expectedExtraAllowed: "",
},
{
name: "IPv6 host address",
allowedIPs: []string{"fd00::1/128"},
expectedInterface: []string{"fd00::1/128"},
expectedExtraAllowed: "",
},
{
name: "IPv4 network address",
allowedIPs: []string{"10.0.1.0/24"},
expectedInterface: []string{},
expectedExtraAllowed: "10.0.1.0/24",
},
{
name: "IPv4 normal address with mask",
allowedIPs: []string{"10.0.1.5/24"},
expectedInterface: []string{"10.0.1.5/24"},
expectedExtraAllowed: "",
},
{
name: "Mixed addresses",
allowedIPs: []string{
"10.0.0.1/32", "192.168.1.0/24", "172.16.0.5/24", "fd00::1/128", "fd00:1::/64",
},
expectedInterface: []string{"10.0.0.1/32", "172.16.0.5/24", "fd00::1/128"},
expectedExtraAllowed: "192.168.1.0/24,fd00:1::/64",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
db := &mockDB{}
m := Manager{
db: db,
}
iface := &domain.Interface{
Identifier: "wg0",
Type: domain.InterfaceTypeServer,
}
allowedIPs := make([]domain.Cidr, len(tt.allowedIPs))
for i, s := range tt.allowedIPs {
cidr, _ := domain.CidrFromString(s)
allowedIPs[i] = cidr
}
p := &domain.PhysicalPeer{
Identifier: "peer1",
KeyPair: domain.KeyPair{PublicKey: "peer1-public-key-is-long-enough"},
AllowedIPs: allowedIPs,
}
err := m.importPeer(context.Background(), iface, p)
assert.NoError(t, err)
savedPeer := db.savedPeers["peer1"]
assert.NotNil(t, savedPeer)
// Check interface addresses
actualInterface := make([]string, len(savedPeer.Interface.Addresses))
for i, addr := range savedPeer.Interface.Addresses {
actualInterface[i] = addr.String()
}
assert.ElementsMatch(t, tt.expectedInterface, actualInterface)
// Check extra allowed IPs
assert.Equal(t, tt.expectedExtraAllowed, savedPeer.ExtraAllowedIPsStr)
})
}
}