mirror of
https://github.com/steveiliop56/tinyauth.git
synced 2026-01-11 01:42:30 +00:00
Compare commits
4 Commits
0374370b0c
...
ed28e7a218
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed28e7a218 | ||
|
|
7db81121e1 | ||
|
|
195b70b4d7 | ||
|
|
c4529be557 |
@@ -14,6 +14,8 @@ TINYAUTH_DISABLEANALYTICS=false
|
|||||||
TINYAUTH_DISABLERESOURCES=false
|
TINYAUTH_DISABLERESOURCES=false
|
||||||
# Disable UI warning messages
|
# Disable UI warning messages
|
||||||
TINYAUTH_DISABLEUIWARNINGS=false
|
TINYAUTH_DISABLEUIWARNINGS=false
|
||||||
|
# Enable JSON formatted logs
|
||||||
|
TINYAUTH_LOGJSON=false
|
||||||
|
|
||||||
# Server Configuration
|
# Server Configuration
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/nightly.yml
vendored
4
.github/workflows/nightly.yml
vendored
@@ -80,7 +80,7 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cp -r frontend/dist internal/assets/dist
|
cp -r frontend/dist internal/assets/dist
|
||||||
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64 cmd/*
|
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64 ./cmd/tinyauth
|
||||||
env:
|
env:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cp -r frontend/dist internal/assets/dist
|
cp -r frontend/dist internal/assets/dist
|
||||||
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64 cmd/*
|
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64 ./cmd/tinyauth
|
||||||
env:
|
env:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cp -r frontend/dist internal/assets/dist
|
cp -r frontend/dist internal/assets/dist
|
||||||
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64 cmd/*
|
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-amd64 ./cmd/tinyauth
|
||||||
env:
|
env:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
cp -r frontend/dist internal/assets/dist
|
cp -r frontend/dist internal/assets/dist
|
||||||
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64 cmd/*
|
go build -ldflags "-s -w -X tinyauth/internal/config.Version=${{ needs.generate-metadata.outputs.VERSION }} -X tinyauth/internal/config.CommitHash=${{ needs.generate-metadata.outputs.COMMIT_HASH }} -X tinyauth/internal/config.BuildTimestamp=${{ needs.generate-metadata.outputs.BUILD_TIMESTAMP }}" -o tinyauth-arm64 ./cmd/tinyauth
|
||||||
env:
|
env:
|
||||||
CGO_ENABLED: 0
|
CGO_ENABLED: 0
|
||||||
|
|
||||||
|
|||||||
25
.gitignore
vendored
25
.gitignore
vendored
@@ -1,29 +1,36 @@
|
|||||||
# dist
|
# dist
|
||||||
internal/assets/dist
|
/internal/assets/dist
|
||||||
|
|
||||||
# binaries
|
# binaries
|
||||||
tinyauth
|
/tinyauth
|
||||||
|
|
||||||
# test docker compose
|
# test docker compose
|
||||||
docker-compose.test*
|
/docker-compose.test*
|
||||||
|
|
||||||
# users file
|
# users file
|
||||||
users.txt
|
/users.txt
|
||||||
|
|
||||||
# secret test file
|
# secret test file
|
||||||
secret*
|
/secret*
|
||||||
|
|
||||||
# apple stuff
|
# apple stuff
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# env
|
# env
|
||||||
.env
|
/.env
|
||||||
|
|
||||||
# tmp directory
|
# tmp directory
|
||||||
tmp
|
/tmp
|
||||||
|
|
||||||
# version files
|
# version files
|
||||||
internal/assets/version
|
/internal/assets/version
|
||||||
|
|
||||||
# data directory
|
# data directory
|
||||||
data
|
/data
|
||||||
|
|
||||||
|
# config file
|
||||||
|
/config.yml
|
||||||
|
|
||||||
|
# binary out
|
||||||
|
/tinyauth.db
|
||||||
|
/resources
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
app_url: "https://tinyauth.example.com"
|
|
||||||
log_level: "info"
|
|
||||||
resources_dir: "/etc/tinyauth/resources"
|
|
||||||
database_path: "/var/lib/tinyauth/tinyauth.db"
|
|
||||||
disable_analytics: false
|
|
||||||
disable_resources: false
|
|
||||||
disable_ui_warnings: false
|
|
||||||
|
|
||||||
server:
|
|
||||||
port: 8080
|
|
||||||
address: "0.0.0.0"
|
|
||||||
socket_path: "/var/run/tinyauth.sock"
|
|
||||||
trusted_proxies: "10.10.10.0/24"
|
|
||||||
|
|
||||||
auth:
|
|
||||||
users: "user:hash"
|
|
||||||
users_file: "/etc/tinyauth/users.yaml"
|
|
||||||
secure_cookie: true
|
|
||||||
session_expiry: 3600
|
|
||||||
login_timeout: 300
|
|
||||||
login_max_retries: 5
|
|
||||||
|
|
||||||
oauth:
|
|
||||||
whitelist: "example.com"
|
|
||||||
auto_redirect: "pocketid"
|
|
||||||
providers:
|
|
||||||
google:
|
|
||||||
client_id: "some-client-id"
|
|
||||||
client_secret: "some-client-secret"
|
|
||||||
client_secret_file: "some-client-secret-file"
|
|
||||||
scopes:
|
|
||||||
- "openid"
|
|
||||||
- "email"
|
|
||||||
- "profile"
|
|
||||||
redirect_url: "https://tinyauth.example.com/oauth/callback/google"
|
|
||||||
auth_url: "https://accounts.google.com/o/oauth2/auth"
|
|
||||||
token_url: "https://oauth2.googleapis.com/token"
|
|
||||||
user_info_url: "https://www.googleapis.com/oauth2/v3/userinfo"
|
|
||||||
insecure: false
|
|
||||||
name: "Google"
|
|
||||||
|
|
||||||
ui:
|
|
||||||
title: "Tinyauth"
|
|
||||||
forgot_password_message: "Contact your administrator to reset your password."
|
|
||||||
background_image: "/static/background.jpg"
|
|
||||||
|
|
||||||
ldap:
|
|
||||||
address: "ldap.example.com:389"
|
|
||||||
base_dn: "dc=example,dc=com"
|
|
||||||
bind_dn: "cn=admin,dc=example,dc=com"
|
|
||||||
bind_password: "password"
|
|
||||||
search_filter: "(uid={username})"
|
|
||||||
insecure: false
|
|
||||||
@@ -37,7 +37,7 @@ COPY ./cmd ./cmd
|
|||||||
COPY ./internal ./internal
|
COPY ./internal ./internal
|
||||||
COPY --from=frontend-builder /frontend/dist ./internal/assets/dist
|
COPY --from=frontend-builder /frontend/dist ./internal/assets/dist
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X tinyauth/internal/config.Version=${VERSION} -X tinyauth/internal/config.CommitHash=${COMMIT_HASH} -X tinyauth/internal/config.BuildTimestamp=${BUILD_TIMESTAMP}" cmd/*
|
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X tinyauth/internal/config.Version=${VERSION} -X tinyauth/internal/config.CommitHash=${COMMIT_HASH} -X tinyauth/internal/config.BuildTimestamp=${BUILD_TIMESTAMP}" ./cmd/tinyauth
|
||||||
|
|
||||||
# Runner
|
# Runner
|
||||||
FROM alpine:3.23 AS runner
|
FROM alpine:3.23 AS runner
|
||||||
@@ -52,6 +52,10 @@ EXPOSE 3000
|
|||||||
|
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
|
ENV DATABASEPATH=/data/tinyauth.db
|
||||||
|
|
||||||
|
ENV RESOURCESDIR=/data/resources
|
||||||
|
|
||||||
ENV GIN_MODE=release
|
ENV GIN_MODE=release
|
||||||
|
|
||||||
ENV PATH=$PATH:/tinyauth
|
ENV PATH=$PATH:/tinyauth
|
||||||
|
|||||||
@@ -16,4 +16,8 @@ COPY ./air.toml ./
|
|||||||
|
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV DATABASEPATH=/data/tinyauth.db
|
||||||
|
|
||||||
|
ENV RESOURCESDIR=/data/resources
|
||||||
|
|
||||||
ENTRYPOINT ["air", "-c", "air.toml"]
|
ENTRYPOINT ["air", "-c", "air.toml"]
|
||||||
@@ -33,14 +33,13 @@ COPY go.sum ./
|
|||||||
|
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
||||||
COPY ./main.go ./
|
|
||||||
COPY ./cmd ./cmd
|
COPY ./cmd ./cmd
|
||||||
COPY ./internal ./internal
|
COPY ./internal ./internal
|
||||||
COPY --from=frontend-builder /frontend/dist ./internal/assets/dist
|
COPY --from=frontend-builder /frontend/dist ./internal/assets/dist
|
||||||
|
|
||||||
RUN mkdir -p data
|
RUN mkdir -p data
|
||||||
|
|
||||||
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X tinyauth/internal/config.Version=${VERSION} -X tinyauth/internal/config.CommitHash=${COMMIT_HASH} -X tinyauth/internal/config.BuildTimestamp=${BUILD_TIMESTAMP}" cmd/*
|
RUN CGO_ENABLED=0 go build -ldflags "-s -w -X tinyauth/internal/config.Version=${VERSION} -X tinyauth/internal/config.CommitHash=${COMMIT_HASH} -X tinyauth/internal/config.BuildTimestamp=${BUILD_TIMESTAMP}" ./cmd/tinyauth
|
||||||
|
|
||||||
# Runner
|
# Runner
|
||||||
FROM gcr.io/distroless/static-debian12:latest AS runner
|
FROM gcr.io/distroless/static-debian12:latest AS runner
|
||||||
@@ -56,6 +55,10 @@ EXPOSE 3000
|
|||||||
|
|
||||||
VOLUME ["/data"]
|
VOLUME ["/data"]
|
||||||
|
|
||||||
|
ENV DATABASEPATH=/data/tinyauth.db
|
||||||
|
|
||||||
|
ENV RESOURCESDIR=/data/resources
|
||||||
|
|
||||||
ENV GIN_MODE=release
|
ENV GIN_MODE=release
|
||||||
|
|
||||||
ENV PATH=$PATH:/tinyauth
|
ENV PATH=$PATH:/tinyauth
|
||||||
|
|||||||
2
air.toml
2
air.toml
@@ -3,7 +3,7 @@ tmp_dir = "tmp"
|
|||||||
|
|
||||||
[build]
|
[build]
|
||||||
pre_cmd = ["mkdir -p internal/assets/dist", "mkdir -p /data", "echo 'backend running' > internal/assets/dist/index.html"]
|
pre_cmd = ["mkdir -p internal/assets/dist", "mkdir -p /data", "echo 'backend running' > internal/assets/dist/index.html"]
|
||||||
cmd = "CGO_ENABLED=0 go build -gcflags=\"all=-N -l\" -o tmp/tinyauth cmd/*"
|
cmd = "CGO_ENABLED=0 go build -gcflags=\"all=-N -l\" -o tmp/tinyauth ./cmd/tinyauth"
|
||||||
bin = "tmp/tinyauth"
|
bin = "tmp/tinyauth"
|
||||||
full_bin = "dlv --listen :4000 --headless=true --api-version=2 --accept-multiclient --log=true exec tmp/tinyauth --continue --check-go-version=false"
|
full_bin = "dlv --listen :4000 --headless=true --api-version=2 --accept-multiclient --log=true exec tmp/tinyauth --continue --check-go-version=false"
|
||||||
include_ext = ["go"]
|
include_ext = ["go"]
|
||||||
|
|||||||
@@ -41,7 +41,9 @@ func healthcheckCmd() *cli.Command {
|
|||||||
|
|
||||||
log.Info().Str("app_url", appUrl).Msg("Performing health check")
|
log.Info().Str("app_url", appUrl).Msg("Performing health check")
|
||||||
|
|
||||||
client := http.Client{}
|
client := http.Client{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", appUrl+"/api/healthz", nil)
|
req, err := http.NewRequest("GET", appUrl+"/api/healthz", nil)
|
||||||
|
|
||||||
@@ -14,17 +14,28 @@ import (
|
|||||||
"github.com/traefik/paerser/cli"
|
"github.com/traefik/paerser/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TinyauthCmdConfiguration struct {
|
func NewTinyauthCmdConfiguration() *config.Config {
|
||||||
config.Config
|
return &config.Config{
|
||||||
// ConfigFile string `description:"Path to config file."`
|
LogLevel: "info",
|
||||||
}
|
ResourcesDir: "./resources",
|
||||||
|
DatabasePath: "./tinyauth.db",
|
||||||
func NewTinyauthCmdConfiguration() *TinyauthCmdConfiguration {
|
Server: config.ServerConfig{
|
||||||
return &TinyauthCmdConfiguration{
|
Port: 3000,
|
||||||
Config: config.Config{
|
Address: "0.0.0.0",
|
||||||
LogLevel: "info",
|
},
|
||||||
|
Auth: config.AuthConfig{
|
||||||
|
SessionExpiry: 3600,
|
||||||
|
LoginTimeout: 300,
|
||||||
|
LoginMaxRetries: 3,
|
||||||
|
},
|
||||||
|
UI: config.UIConfig{
|
||||||
|
Title: "Tinyauth",
|
||||||
|
ForgotPasswordMessage: "You can change your password by changing the configuration.",
|
||||||
|
BackgroundImage: "/background.jpg",
|
||||||
|
},
|
||||||
|
Experimental: config.ExperimentalConfig{
|
||||||
|
ConfigFile: "",
|
||||||
},
|
},
|
||||||
// ConfigFile: "",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,8 +43,9 @@ func main() {
|
|||||||
tConfig := NewTinyauthCmdConfiguration()
|
tConfig := NewTinyauthCmdConfiguration()
|
||||||
|
|
||||||
loaders := []cli.ResourceLoader{
|
loaders := []cli.ResourceLoader{
|
||||||
&loaders.EnvLoader{},
|
&loaders.FileLoader{},
|
||||||
&loaders.FlagLoader{},
|
&loaders.FlagLoader{},
|
||||||
|
&loaders.EnvLoader{},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdTinyauth := &cli.Command{
|
cmdTinyauth := &cli.Command{
|
||||||
@@ -42,7 +54,7 @@ func main() {
|
|||||||
Configuration: tConfig,
|
Configuration: tConfig,
|
||||||
Resources: loaders,
|
Resources: loaders,
|
||||||
Run: func(_ []string) error {
|
Run: func(_ []string) error {
|
||||||
return runCmd(&tConfig.Config)
|
return runCmd(*tConfig)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +95,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runCmd(cfg *config.Config) error {
|
func runCmd(cfg config.Config) error {
|
||||||
logLevel, err := zerolog.ParseLevel(strings.ToLower(cfg.LogLevel))
|
logLevel, err := zerolog.ParseLevel(strings.ToLower(cfg.LogLevel))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -92,11 +104,15 @@ func runCmd(cfg *config.Config) error {
|
|||||||
zerolog.SetGlobalLevel(logLevel)
|
zerolog.SetGlobalLevel(logLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}).With().Caller().Logger()
|
log.Logger = log.With().Caller().Logger()
|
||||||
|
|
||||||
|
if !cfg.LogJSON {
|
||||||
|
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339})
|
||||||
|
}
|
||||||
|
|
||||||
log.Info().Str("version", config.Version).Msg("Starting tinyauth")
|
log.Info().Str("version", config.Version).Msg("Starting tinyauth")
|
||||||
|
|
||||||
app := bootstrap.NewBootstrapApp(*cfg)
|
app := bootstrap.NewBootstrapApp(cfg)
|
||||||
|
|
||||||
err = app.Setup()
|
err = app.Setup()
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ func verifyUserCmd() *cli.Command {
|
|||||||
ok := totp.Validate(tCfg.Totp, user.TotpSecret)
|
ok := totp.Validate(tCfg.Totp, user.TotpSecret)
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("TOTP code incorrect: %w", err)
|
return fmt.Errorf("TOTP code incorrect")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info().Msg("User verified")
|
log.Info().Msg("User verified")
|
||||||
88
config.example.yaml
Normal file
88
config.example.yaml
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# Tinyauth Example Configuration
|
||||||
|
|
||||||
|
# The base URL where Tinyauth is accessible
|
||||||
|
appUrl: "https://auth.example.com"
|
||||||
|
# Log level: trace, debug, info, warn, error
|
||||||
|
logLevel: "info"
|
||||||
|
# Directory for static resources
|
||||||
|
resourcesDir: "./resources"
|
||||||
|
# Path to SQLite database file
|
||||||
|
databasePath: "./tinyauth.db"
|
||||||
|
# Disable usage analytics
|
||||||
|
disableAnalytics: false
|
||||||
|
# Disable static resource serving
|
||||||
|
disableResources: false
|
||||||
|
# Disable UI warning messages
|
||||||
|
disableUIWarnings: false
|
||||||
|
# Enable JSON formatted logs
|
||||||
|
logJSON: false
|
||||||
|
|
||||||
|
# Server Configuration
|
||||||
|
server:
|
||||||
|
# Port to listen on
|
||||||
|
port: 3000
|
||||||
|
# Interface to bind to (0.0.0.0 for all interfaces)
|
||||||
|
address: "0.0.0.0"
|
||||||
|
# Unix socket path (optional, overrides port/address if set)
|
||||||
|
socketPath: ""
|
||||||
|
# Comma-separated list of trusted proxy IPs/CIDRs
|
||||||
|
trustedProxies: ""
|
||||||
|
|
||||||
|
# Authentication Configuration
|
||||||
|
auth:
|
||||||
|
# Format: username:bcrypt_hash (use bcrypt to generate hash)
|
||||||
|
users: "admin:$2a$10$example_bcrypt_hash_here"
|
||||||
|
# Path to external users file (optional)
|
||||||
|
usersFile: ""
|
||||||
|
# Enable secure cookies (requires HTTPS)
|
||||||
|
secureCookie: false
|
||||||
|
# Session expiry in seconds (3600 = 1 hour)
|
||||||
|
sessionExpiry: 3600
|
||||||
|
# Login timeout in seconds (300 = 5 minutes)
|
||||||
|
loginTimeout: 300
|
||||||
|
# Maximum login retries before lockout
|
||||||
|
loginMaxRetries: 3
|
||||||
|
|
||||||
|
# OAuth Configuration
|
||||||
|
oauth:
|
||||||
|
# Regex pattern for allowed email addresses (e.g., /@example\.com$/)
|
||||||
|
whitelist: ""
|
||||||
|
# Provider ID to auto-redirect to (skips login page)
|
||||||
|
autoRedirect: ""
|
||||||
|
# OAuth Provider Configuration (replace myprovider with your provider name)
|
||||||
|
providers:
|
||||||
|
myprovider:
|
||||||
|
clientId: "your_client_id_here"
|
||||||
|
clientSecret: "your_client_secret_here"
|
||||||
|
authUrl: "https://provider.example.com/oauth/authorize"
|
||||||
|
tokenUrl: "https://provider.example.com/oauth/token"
|
||||||
|
userInfoUrl: "https://provider.example.com/oauth/userinfo"
|
||||||
|
redirectUrl: "https://auth.example.com/api/oauth/callback/myprovider"
|
||||||
|
scopes: "openid email profile"
|
||||||
|
name: "My OAuth Provider"
|
||||||
|
# Allow insecure connections (self-signed certificates)
|
||||||
|
insecure: false
|
||||||
|
|
||||||
|
# UI Customization
|
||||||
|
ui:
|
||||||
|
# Custom title for login page
|
||||||
|
title: "Tinyauth"
|
||||||
|
# Message shown on forgot password page
|
||||||
|
forgotPasswordMessage: "Contact your administrator to reset your password"
|
||||||
|
# Background image URL for login page
|
||||||
|
backgroundImage: ""
|
||||||
|
|
||||||
|
# LDAP Configuration (optional)
|
||||||
|
ldap:
|
||||||
|
# LDAP server address
|
||||||
|
address: "ldap://ldap.example.com:389"
|
||||||
|
# DN for binding to LDAP server
|
||||||
|
bindDn: "cn=readonly,dc=example,dc=com"
|
||||||
|
# Password for bind DN
|
||||||
|
bindPassword: "your_bind_password"
|
||||||
|
# Base DN for user searches
|
||||||
|
baseDn: "dc=example,dc=com"
|
||||||
|
# Search filter (%s will be replaced with username)
|
||||||
|
searchFilter: "(&(uid=%s)(memberOf=cn=users,ou=groups,dc=example,dc=com))"
|
||||||
|
# Allow insecure LDAP connections
|
||||||
|
insecure: false
|
||||||
1
go.mod
1
go.mod
@@ -13,7 +13,6 @@ require (
|
|||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/mdp/qrterminal/v3 v3.2.1
|
github.com/mdp/qrterminal/v3 v3.2.1
|
||||||
github.com/rs/zerolog v1.34.0
|
github.com/rs/zerolog v1.34.0
|
||||||
github.com/stoewer/go-strcase v1.3.1
|
|
||||||
github.com/traefik/paerser v0.2.2
|
github.com/traefik/paerser v0.2.2
|
||||||
github.com/weppos/publicsuffix-go v0.50.1
|
github.com/weppos/publicsuffix-go v0.50.1
|
||||||
golang.org/x/crypto v0.46.0
|
golang.org/x/crypto v0.46.0
|
||||||
|
|||||||
2
go.sum
2
go.sum
@@ -260,8 +260,6 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
|
|||||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||||
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
|
|
||||||
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ func (app *BootstrapApp) heartbeat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
Timeout: time.Duration(10) * time.Second, // The server should never take more than 10 seconds to respond
|
Timeout: 30 * time.Second, // The server should never take more than 30 seconds to respond
|
||||||
}
|
}
|
||||||
|
|
||||||
heartbeatURL := config.ApiServer + "/v1/instances/heartbeat"
|
heartbeatURL := config.ApiServer + "/v1/instances/heartbeat"
|
||||||
|
|||||||
@@ -15,55 +15,61 @@ var RedirectCookieName = "tinyauth-redirect"
|
|||||||
// Main app config
|
// Main app config
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
AppURL string `description:"The base URL where the app is hosted."`
|
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
|
||||||
LogLevel string `description:"Log level (trace, debug, info, warn, error)."`
|
LogLevel string `description:"Log level (trace, debug, info, warn, error)." yaml:"logLevel"`
|
||||||
ResourcesDir string `description:"The directory where resources are stored."`
|
ResourcesDir string `description:"The directory where resources are stored." yaml:"resourcesDir"`
|
||||||
DatabasePath string `description:"The path to the database file."`
|
DatabasePath string `description:"The path to the database file." yaml:"databasePath"`
|
||||||
DisableAnalytics bool `description:"Disable analytics."`
|
DisableAnalytics bool `description:"Disable analytics." yaml:"disableAnalytics"`
|
||||||
DisableResources bool `description:"Disable resources server."`
|
DisableResources bool `description:"Disable resources server." yaml:"disableResources"`
|
||||||
DisableUIWarnings bool `description:"Disable UI warnings."`
|
DisableUIWarnings bool `description:"Disable UI warnings." yaml:"disableUIWarnings"`
|
||||||
Server ServerConfig
|
LogJSON bool `description:"Enable JSON formatted logs." yaml:"logJSON"`
|
||||||
Auth AuthConfig
|
Server ServerConfig `description:"Server configuration." yaml:"server"`
|
||||||
OAuth OAuthConfig
|
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
|
||||||
UI UIConfig
|
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
|
||||||
Ldap LdapConfig
|
UI UIConfig `description:"UI customization." yaml:"ui"`
|
||||||
|
Ldap LdapConfig `description:"LDAP configuration." yaml:"ldap"`
|
||||||
|
Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
Port int `description:"The port on which the server listens."`
|
Port int `description:"The port on which the server listens." yaml:"port"`
|
||||||
Address string `description:"The address on which the server listens."`
|
Address string `description:"The address on which the server listens." yaml:"address"`
|
||||||
SocketPath string `description:"The path to the Unix socket."`
|
SocketPath string `description:"The path to the Unix socket." yaml:"socketPath"`
|
||||||
TrustedProxies string `description:"Comma-separated list of trusted proxy addresses."`
|
TrustedProxies string `description:"Comma-separated list of trusted proxy addresses." yaml:"trustedProxies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type AuthConfig struct {
|
type AuthConfig struct {
|
||||||
Users string `description:"Comma-separated list of users (username:hashed_password)."`
|
Users string `description:"Comma-separated list of users (username:hashed_password)." yaml:"users"`
|
||||||
UsersFile string `description:"Path to the users file."`
|
UsersFile string `description:"Path to the users file." yaml:"usersFile"`
|
||||||
SecureCookie bool `description:"Enable secure cookies."`
|
SecureCookie bool `description:"Enable secure cookies." yaml:"secureCookie"`
|
||||||
SessionExpiry int `description:"Session expiry time in seconds."`
|
SessionExpiry int `description:"Session expiry time in seconds." yaml:"sessionExpiry"`
|
||||||
LoginTimeout int `description:"Login timeout in seconds."`
|
LoginTimeout int `description:"Login timeout in seconds." yaml:"loginTimeout"`
|
||||||
LoginMaxRetries int `description:"Maximum login retries."`
|
LoginMaxRetries int `description:"Maximum login retries." yaml:"loginMaxRetries"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OAuthConfig struct {
|
type OAuthConfig struct {
|
||||||
Whitelist string `description:"Comma-separated list of allowed OAuth domains."`
|
Whitelist string `description:"Comma-separated list of allowed OAuth domains." yaml:"whitelist"`
|
||||||
AutoRedirect string `description:"The OAuth provider to use for automatic redirection."`
|
AutoRedirect string `description:"The OAuth provider to use for automatic redirection." yaml:"autoRedirect"`
|
||||||
Providers map[string]OAuthServiceConfig
|
Providers map[string]OAuthServiceConfig `description:"OAuth providers configuration." yaml:"providers"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UIConfig struct {
|
type UIConfig struct {
|
||||||
Title string `description:"The title of the UI."`
|
Title string `description:"The title of the UI." yaml:"title"`
|
||||||
ForgotPasswordMessage string `description:"Message displayed on the forgot password page."`
|
ForgotPasswordMessage string `description:"Message displayed on the forgot password page." yaml:"forgotPasswordMessage"`
|
||||||
BackgroundImage string `description:"Path to the background image."`
|
BackgroundImage string `description:"Path to the background image." yaml:"backgroundImage"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LdapConfig struct {
|
type LdapConfig struct {
|
||||||
Address string `description:"LDAP server address."`
|
Address string `description:"LDAP server address." yaml:"address"`
|
||||||
BindDN string `description:"Bind DN for LDAP authentication."`
|
BindDN string `description:"Bind DN for LDAP authentication." yaml:"bindDn"`
|
||||||
BindPassword string `description:"Bind password for LDAP authentication."`
|
BindPassword string `description:"Bind password for LDAP authentication." yaml:"bindPassword"`
|
||||||
BaseDN string `description:"Base DN for LDAP searches."`
|
BaseDN string `description:"Base DN for LDAP searches." yaml:"baseDn"`
|
||||||
Insecure bool `description:"Allow insecure LDAP connections."`
|
Insecure bool `description:"Allow insecure LDAP connections." yaml:"insecure"`
|
||||||
SearchFilter string `description:"LDAP search filter."`
|
SearchFilter string `description:"LDAP search filter." yaml:"searchFilter"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExperimentalConfig struct {
|
||||||
|
ConfigFile string `description:"Path to config file." yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Config loader options
|
// Config loader options
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ func (generic *GenericOAuthService) Init() error {
|
|||||||
|
|
||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
Transport: transport,
|
Transport: transport,
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|||||||
@@ -50,7 +50,9 @@ func NewGithubOAuthService(config config.OAuthServiceConfig) *GithubOAuthService
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (github *GithubOAuthService) Init() error {
|
func (github *GithubOAuthService) Init() error {
|
||||||
httpClient := &http.Client{}
|
httpClient := &http.Client{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
||||||
github.context = ctx
|
github.context = ctx
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ func NewGoogleOAuthService(config config.OAuthServiceConfig) *GoogleOAuthService
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (google *GoogleOAuthService) Init() error {
|
func (google *GoogleOAuthService) Init() error {
|
||||||
httpClient := &http.Client{}
|
httpClient := &http.Client{
|
||||||
|
Timeout: 30 * time.Second,
|
||||||
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient)
|
||||||
google.context = ctx
|
google.context = ctx
|
||||||
|
|||||||
35
internal/utils/loaders/loader_file.go
Normal file
35
internal/utils/loaders/loader_file.go
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package loaders
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/traefik/paerser/cli"
|
||||||
|
"github.com/traefik/paerser/file"
|
||||||
|
"github.com/traefik/paerser/flag"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileLoader struct{}
|
||||||
|
|
||||||
|
func (f *FileLoader) Load(args []string, cmd *cli.Command) (bool, error) {
|
||||||
|
flags, err := flag.Parse(args, cmd.Configuration)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// I guess we are using traefik as the root name
|
||||||
|
configFileFlag := "traefik.experimental.configFile"
|
||||||
|
|
||||||
|
if _, ok := flags[configFileFlag]; !ok {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Warn().Msg("Using experimental file config loader, this feature is experimental and may change or be removed in future releases")
|
||||||
|
|
||||||
|
err = file.Decode(flags[configFileFlag], cmd.Configuration)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user