Skip to content

Commit

Permalink
forward_auth: user mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
mazzz1y committed Dec 10, 2024
1 parent 2ce8d03 commit be2cb8c
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 52 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
.idea
config-example.yaml
config.yaml
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@ entrypoints:
# For use with OAuth2 Proxy, Authelia, and other authorization proxies.
# Requests with a valid username in the header will be forwarded without additional authorization.
# If the username is not valid, a 403 error will be returned.
forwarded_auth_header: X-Forwarded-User
forward_auth:
header: X-Forwarded-User
# Mapping of incoming usernames to internal usernames.
# For example, the user coming from the header 'mazzz1y' will be logged as the 'admin' internal user.
mapping:
mazzz1y: admin

devices:
- tag: keenetic-home
Expand Down
20 changes: 11 additions & 9 deletions cmd/keenetic-auth-gw/main.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package main

import (
"os"
"sync"

"github.com/mazzz1y/keenetic-auth-gw/internal/config"
"github.com/mazzz1y/keenetic-auth-gw/internal/device"
"github.com/mazzz1y/keenetic-auth-gw/internal/entrypoint"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/urfave/cli/v2"
"os"
"sync"
)

var version = "custom"
Expand Down Expand Up @@ -83,18 +84,19 @@ func startServersAction(c *cli.Context) error {
func startServer(dm *device.DeviceManager, entryCfg config.EntrypointConfig, wg *sync.WaitGroup) {
defer wg.Done()

d, ok := dm.GetDeviceByTag(entryCfg.DeviceTag)
d, ok := dm.Devices[entryCfg.DeviceTag]
if !ok {
log.Fatal().Msgf("%s: \"%s\" device not found", entryCfg.Listen, entryCfg.DeviceTag)
}

err := entrypoint.NewEntrypoint(entrypoint.EntrypointOptions{
Device: d,
ListenAddr: entryCfg.Listen,
ForwardAuthHeader: entryCfg.ForwardedAuthHeader,
BasicAuth: entryCfg.BasicAuthMap(),
AllowedEndpoints: entryCfg.AllowedEndpoints,
OnlyGet: entryCfg.ReadOnly,
Device: d,
ListenAddr: entryCfg.Listen,
ForwardAuthHeader: entryCfg.ForwardAuth.Header,
ForwardAuthMapping: entryCfg.ForwardAuth.Mapping,
BasicAuth: entryCfg.BasicAuthMap(),
AllowedEndpoints: entryCfg.AllowedEndpoints,
OnlyGet: entryCfg.ReadOnly,
}).Start()

if err != nil {
Expand Down
20 changes: 13 additions & 7 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package config
import (
"bytes"
"fmt"
"gopkg.in/yaml.v3"
"io"
"os"

"gopkg.in/yaml.v3"
)

type Config struct {
Expand All @@ -14,12 +15,12 @@ type Config struct {
}

type EntrypointConfig struct {
Listen string `yaml:"listen"`
DeviceTag string `yaml:"device_tag"`
ReadOnly bool `yaml:"read_only,omitempty"`
ForwardedAuthHeader string `yaml:"forwarded_auth_header,omitempty"`
BasicAuth []BasicAuthConfig `yaml:"basic_auth,omitempty"`
AllowedEndpoints []string `yaml:"allowed_endpoints"`
Listen string `yaml:"listen"`
DeviceTag string `yaml:"device_tag"`
ReadOnly bool `yaml:"read_only,omitempty"`
ForwardAuth ForwardAuthConfig `yaml:"forward_auth,omitempty"`
BasicAuth []BasicAuthConfig `yaml:"basic_auth,omitempty"`
AllowedEndpoints []string `yaml:"allowed_endpoints"`
}

type DeviceConfig struct {
Expand All @@ -39,6 +40,11 @@ type BasicAuthConfig struct {
Password string `yaml:"password"`
}

type ForwardAuthConfig struct {
Header string `yaml:"header"`
Mapping map[string]string `yaml:"mapping"`
}

// BasicAuthMap converts a list of BasicAuthConfig entries into a map for easy lookup
func (ec EntrypointConfig) BasicAuthMap() map[string]string {
basicAuthMap := make(map[string]string)
Expand Down
13 changes: 12 additions & 1 deletion internal/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package config_test

import (
"github.com/mazzz1y/keenetic-auth-gw/internal/config"
"os"
"testing"

"github.com/mazzz1y/keenetic-auth-gw/internal/config"

"github.com/stretchr/testify/assert"
)

Expand All @@ -16,6 +17,10 @@ entrypoints:
- username: xxx
password: xxx
allowed_endpoints: ["/status", "/health"]
forward_auth:
header: X-Forwared-User
mapping:
user1: user2
devices:
- tag: "device123"
url: "http://device.local"
Expand Down Expand Up @@ -43,6 +48,12 @@ func TestLoadConfig_Success(t *testing.T) {
},
},
AllowedEndpoints: []string{"/status", "/health"},
ForwardAuth: config.ForwardAuthConfig{
Header: "X-Forwared-User",
Mapping: map[string]string{
"user1": "user2",
},
},
}},
Devices: []config.DeviceConfig{{
Tag: "device123",
Expand Down
5 changes: 0 additions & 5 deletions internal/device/device.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ func NewDeviceManager(cfg []config.DeviceConfig, auth bool) (*DeviceManager, err
return deviceManager, nil
}

func (dm *DeviceManager) GetDeviceByTag(tag string) (Device, bool) {
device, exists := dm.Devices[tag]
return device, exists
}

func initClients(c config.DeviceConfig, auth bool) ([]User, error) {
users := make([]User, len(c.Users))
for i, v := range c.Users {
Expand Down
19 changes: 2 additions & 17 deletions internal/device/device_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package device_test

import (
"testing"

"github.com/mazzz1y/keenetic-auth-gw/internal/config"
"github.com/mazzz1y/keenetic-auth-gw/internal/device"
"testing"

"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -31,19 +32,3 @@ func TestNewDeviceManager(t *testing.T) {
assert.Equal(t, 2, len(manager.Devices["Device1"].Users))
})
}

func TestGetDeviceByTag(t *testing.T) {
manager, _ := device.NewDeviceManager(mockConfig.Devices, false)

t.Run("DeviceFound", func(t *testing.T) {
d, found := manager.GetDeviceByTag("Device1")
assert.True(t, found)
assert.Equal(t, "Device1", d.Tag)
})

t.Run("DeviceNotFound", func(t *testing.T) {
d, found := manager.GetDeviceByTag("InvalidTag")
assert.False(t, found)
assert.Equal(t, device.Device{}, d)
})
}
13 changes: 7 additions & 6 deletions internal/entrypoint/entrypoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ type Entrypoint struct {
}

type EntrypointOptions struct {
Device device.Device
ListenAddr string
ForwardAuthHeader string
BasicAuth map[string]string
AllowedEndpoints []string
OnlyGet bool
Device device.Device
ListenAddr string
ForwardAuthHeader string
ForwardAuthMapping map[string]string
BasicAuth map[string]string
AllowedEndpoints []string
OnlyGet bool
}

func NewEntrypoint(options EntrypointOptions) *Entrypoint {
Expand Down
14 changes: 9 additions & 5 deletions internal/entrypoint/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package entrypoint
import (
"context"
"fmt"
"github.com/mazzz1y/keenetic-auth-gw/internal/device"
"github.com/mazzz1y/keenetic-auth-gw/pkg/keenetic"
"net/http"
"strings"

"github.com/mazzz1y/keenetic-auth-gw/pkg/keenetic"
)

func (e *Entrypoint) authenticateMiddleware(next http.HandlerFunc) http.HandlerFunc {
Expand Down Expand Up @@ -46,7 +46,7 @@ func (e *Entrypoint) authenticate(r *http.Request) (keenetic.ClientWrapper, erro
if user == "" {
return nil, fmt.Errorf("missing forward auth header: %s", header)
}
client, ok := getClientByName(e.Options.Device, user)
client, ok := e.getClientByName(user)
if !ok {
return nil, fmt.Errorf("user not found for forward auth header: %s", user)
}
Expand Down Expand Up @@ -93,8 +93,12 @@ func (e *Entrypoint) isAllowed(r *http.Request) error {
return fmt.Errorf("forbidden")
}

func getClientByName(device device.Device, name string) (keenetic.ClientWrapper, bool) {
for _, user := range device.Users {
func (e *Entrypoint) getClientByName(name string) (keenetic.ClientWrapper, bool) {
if len(e.Options.ForwardAuthMapping) > 0 {
name = e.Options.ForwardAuthMapping[name]
}

for _, user := range e.Options.Device.Users {
if user.Name == name {
return user.Client, true
}
Expand Down

0 comments on commit be2cb8c

Please sign in to comment.