traefik_api_token_middleware

package module
v0.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2024 License: MIT Imports: 12 Imported by: 0

README

Traefik v3 middleware which allows for you to protect certain aspects of your site with an API token.

♾️ Traefik API Key & Token Middleware ♾️


This Traefik middleware allows you to secure certain routes behind a request header API token. Users who have not successfully authenticated will be greeted with a 403 Forbidden Error. Also displays information about each connection including IP address and URL that the user is trying to access.




Version Downloads Build Status Size Last Commit Contributors

Built with Material for MkDocs







Configuration

The following provides examples for usage scenarios.


Static File

If you are utilizing a Traefik Static File, review the following examples:


File (YAML)
## Static configuration
experimental:
  plugins:
    traefik-api-token-middleware:
      moduleName: "github.com/Aetherinox/traefik-api-token-middleware"
      version: "v0.1.4"

File (TOML)
## Static configuration
[experimental.plugins.traefik-api-token-middleware]
  moduleName = "github.com/Aetherinox/traefik-api-token-middleware"
  version = "v0.1.4"

CLI
## Static configuration
--experimental.plugins.traefik-api-token-middleware.modulename=github.com/Aetherinox/traefik-api-token-middleware
--experimental.plugins.traefik-api-token-middleware.version=v0.1.4

Dynamic File

If you are utilizing a Traefik Dynamic File, review the following examples:


File (YAML)
# Dynamic configuration
http:
  middlewares:
    api-token:
      plugin:
        traefik-api-token-middleware:
          authenticationHeader: true
          authenticationHeaderName: X-API-TOKEN
          authenticationErrorMsg: "Invalid token"
          bearerHeader: true
          bearerHeaderName: Authorization
          removeHeadersOnSuccess: true
          removeTokenNameOnFailure: false
          debugLogs: false
          timestampUnix: false
          permissiveMode: false
          regexDeny:
              - '\buseragent1\b'
          tokens:
            - your-api-token

File (TOML)
# Dynamic configuration
[http]
  [http.middlewares]
    [http.middlewares.api-token]
      [http.middlewares.api-token.plugin]
        [http.middlewares.api-token.plugin.traefik-api-token-middleware]
          authenticationHeader = true
          authenticationHeaderName = "X-API-TOKEN"
          authenticationErrorMsg = "Invalid token"
          bearerHeader = true
          bearerHeaderName = "Authorization"
          removeHeadersOnSuccess = true
          removeTokenNameOnFailure = false
          timestampUnix = false
          permissiveMode = false
          debugLogs = false
          tokens = ["your-api-token"]
          whitelistIPs = ["66.85.101.2", "10.10.0.7/32"]

Kubernetes Custom Resource Definition
# Dynamic configuration
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: api-token
spec:
  plugin:
    traefik-api-token-middleware:
      authenticationHeader: true
      authenticationHeaderName: X-API-TOKEN
      authenticationErrorMsg: "Invalid token"
      bearerHeader: true
      bearerHeaderName: Authorization
      removeHeadersOnSuccess: true
      removeTokenNameOnFailure: false
      debugLogs: false
      timestampUnix: false
      permissiveMode: false
      regexDeny:
          - '\buseragent1\b'
      tokens:
        - your-api-token



Parameters

This plugin accepts the following parameters:


Parameter Description Default Type Required
tokens List of API tokens [] []string ✔️ Required
authenticationHeader Pass token using Authentication Header true bool ⚠️ Note
authenticationHeaderName Authentication header name 'X-API-TOKEN' string ⭕ Optional
authenticationErrorMsg Error message to display on unsuccessful authentication 'Access Denied' string ⭕ Optional
bearerHeader Pass token using Authentication Header Bearer Key true bool ⚠️ Note
bearerHeaderName Authentication bearer header name 'Authorization' string ⭕ Optional
removeHeadersOnSuccess If true; remove header on successful authentication true bool ⭕ Optional
removeTokenNameOnFailure Don't display name of token in unsuccessful error message false bool ⭕ Optional
timestampUnix Display datetime in Unix timestamp instead of UnixDate false bool ⭕ Optional
whitelistIPs A list of IP blocks that will bypass the api-token check [] []string ⭕ Optional
regexDeny Blacklist list of useragents from accessing routes [] []string ⭕ Optional
permissiveMode Execute a dry-run, allows access even if a token is invalid false bool ⭕ Optional
debugLogs Shows debug logs in console false bool ⭕ Optional

  • ⚠️: Plugin requires that you enable either authenticationHeader OR bearerHeader. One of the two MUST be enabled.

authenticationErrorMsg

This setting changes the text at the beginning of an error message when an invalid token is specified.


authenticationErrorMsg:


{
  "message": "Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token",
  "status_code": 403,
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
  "ip": "XX.XX.XX.XX",
  "host": "sub.domain.lan",
  "uri": "/",
  "timestamp": "Fri Sep 27 03:24:27 UTC 2024"
}

authenticationErrorMsg: "You cannot access this API"

{
  "message": "You cannot access this API. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token",
  "status_code": 403,
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
  "ip": "XX.XX.XX.XX",
  "host": "sub.domain.lan",
  "uri": "/",
  "timestamp": "Fri Sep 27 03:24:27 UTC 2024"
}


removeTokenNameOnFailure

This setting changes how error messages are displayed to a user who doesn't provide a correct token. If enabled, it will keep the name of your token private.


removeTokenNameOnFailure: true

{
  "message": "Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token",
  "status_code": 403,
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
  "ip": "XX.XX.XX.XX",
  "host": "sub.domain.lan",
  "uri": "/",
  "timestamp": "1727432498"
}

removeTokenNameOnFailure: false

{
  "message": "Access Denied.",
  "status_code": 403,
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
  "ip": "XX.XX.XX.XX",
  "host": "sub.domain.lan",
  "uri": "/",
  "timestamp": "1727432498"
}


whitelistIPs

Allows you to specify a list of whitelisted IP addresses that will not have the API-token checked.


# Dynamic configuration
http:
  middlewares:
    api-token:
      plugin:
        traefik-api-token-middleware:
          authenticationHeader: true
          authenticationHeaderName: X-API-TOKEN
          authenticationErrorMsg: "Invalid token"
          bearerHeader: true
          bearerHeaderName: Authorization
          removeHeadersOnSuccess: true
          removeTokenNameOnFailure: false
          timestampUnix: false
          permissiveMode: false
          tokens:
            - your-api-token
          whitelistIPs:
            - "66.85.101.2"
            - "10.10.0.7/32"


timestampUnix

This setting changes how the date / time will be displayed in your API callback / output.


timestampUnix: true

{
  "message": "Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token",
  "status_code": 403,
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
  "ip": "XX.XX.XX.XX",
  "host": "sub.domain.lan",
  "uri": "/",
  "timestamp": "1727432498"
}

timestampUnix: false

{
  "message": "Access Denied. Provide a valid API Token header using either X-API-TOKEN: $token or Authorization: Bearer $token",
  "status_code": 403,
  "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0",
  "ip": "XX.XX.XX.XX",
  "host": "sub.domain.lan",
  "uri": "/",
  "timestamp": "Fri Sep 27 03:24:27 UTC 2024"
}


permissiveMode

Allows to execute a dry-run on a request. The request will pass successfully even if the API token is invalid. Used for testing.

# Dynamic configuration
http:
  middlewares:
    api-token:
      plugin:
        traefik-api-token-middleware:
          authenticationHeader: true
          authenticationHeaderName: X-API-TOKEN
          authenticationErrorMsg: "Invalid token"
          permissiveMode: true



Full Examples

A few extra examples have been provided.


http:
  middlewares:
    api-token:
      plugin:
        traefik-api-token-middleware:
          authenticationHeader: true
          authenticationHeaderName: X-API-TOKEN
          authenticationErrorMsg: "Invalid token"
          bearerHeader: true
          bearerHeaderName: Authorization
          removeHeadersOnSuccess: true
          removeTokenNameOnFailure: false
          timestampUnix: false
          permissiveMode: false
          tokens:
            - your-api-token

    routers:
        traefik-http:
            service: "traefik"
            rule: "Host(`yourdomain.com`)"
            entryPoints:
                - http
            middlewares:
                - https-redirect@file

        traefik-https:
            service: "traefik"
            rule: "Host(`yourdomain.com`)"
            entryPoints:
                - https
            middlewares:
                - api-token@file
            tls:
                certResolver: cloudflare
                domains:
                    - main: "yourdomain.com"
                      sans:
                          - "*.yourdomain.com"



Browser Plugins

If you do not want to specify an API token using conventional means (such as by using curl), you can utilize a front-end browser extension. This allows you to supply a modified request header with your specific API token which will grant you access to your desired location.


Firefox

If you are using Firefox, install the plugin(s) below. ( Pick One ):


Extension: Header Editor

With this extension, you can modify the request header and response header, cancel a request and redirect a request. Please do not write regular expressions that begin with (. *), (. *?), (. +), such regular expressions may cause problems with Firefox


Once you install the browser extension above, open the settings.



Create a new rule

  • Name: API Token
  • Rule Type: Modify request header
  • Match Type: Domain
    • Match Rules: subdomain.domain.com
    • Exclude Rule: none
  • Execute Type: normal
    • Header Name: x-api-token
    • Header Value: your-api-token


Once you have your modified header added to the browser extension, verify it by reading the section Verifying Modified Headers.



Extension: Modify Header Value

Modify Header Value can add, modify or remove an HTTP-request-header for all requests on a desired website or URL. This Firefox add-on is very useful if you are an App developer, website designer, or if you want to test a particular header for a request on a website.


Once you install the browser extension above, open the settings.



You need to add a new rule which injects your modified header into the specified domain.



Once you have your modified header added to the browser extension, verify it by reading the section Verifying Modified Headers.




Verifying Modified Headers

This section explains how you can verify that your modified request header is being received by your server.

Access the subdomain where you have applied an API-TOKEN. Once the page loads, open the Developer Console.

  • Firefox: SHIFT + CTRL + I
  • Chrome: SHIFT + CTRL + I
  • Safari: Option + ⌘ + C

A box should appear either on the right or bottom. Within the Console tab, ensure you have Errors, Warnings, Logs, Info, and Debug selected. They will have lines under them when enabled.



Next, refresh your browser's page.

  • Firefox: SHIFT + F5
  • Chrome: SHIFT + F5
  • Safari: OPTION + ⌘ + E


In the bottom box, you should see a list of actions, which display your domain name, a status code, and the number of milliseconds it took to perform the action.

01:00:25.139        GET https://sub.yourdomain.com                     [HTTP/2 403  1ms]

  • 403 status: API-TOKEN was not accepted.
  • 200 status: API-TOKEN was accepted. (along with being able to actually see your site)

Typically with a 403 status, you can click the box that contains the status code with your domain, which will expand a box and show you the headers that were passed to the site, including your API-TOKEN.



In the example above, we've passed BadToken which can be seen in the header response.




Local Install

Traefik comes with the ability to install this plugin locally without fetching it from Github.


Download a local copy of this plugin to your server within your Traefik installation folder.

git clone https://github.com/Aetherinox/traefik-api-token-middleware.git

If you are running Docker, you need to mount a new volume:


[!WARNING] The path to the plugin is case sensitive, do not change the casing of the folders, or the plugin will fail to load.


services:
    traefik:
        container_name: traefik
        image: traefik:latest
        restart: unless-stopped
        volumes:
            - ./traefik-api-token-middleware:/plugins-local/src/github.com/Aetherinox/traefik-api-token-middleware/

Static File

Open your Traefik Static File and change plugins to localPlugins.


File (YAML)
# Static configuration
experimental:
  localPlugins:
    traefik-api-token-middleware:
      moduleName: "github.com/Aetherinox/traefik-api-token-middleware"
      version: "v0.1.4"

File (TOML)
# Static configuration
[experimental.localPlugins.traefik-api-token-middleware]
  moduleName = "github.com/Aetherinox/traefik-api-token-middleware"
  version = "v0.1.4"

Dynamic File

For local installation, your dynamic file will contain the same contents as it would if you installed the plugin normally.


File (YAML)
# Dynamic configuration
http:
  middlewares:
    api-token:
      plugin:
        traefik-api-token-middleware:
          authenticationHeader: true
          authenticationHeaderName: X-API-TOKEN
          authenticationErrorMsg: "Invalid token"
          bearerHeader: true
          bearerHeaderName: Authorization
          removeHeadersOnSuccess: true
          removeTokenNameOnFailure: false
          timestampUnix: false
          tokens:
            - your-api-token

File (TOML)
# Dynamic configuration
[http]
  [http.middlewares]
    [http.middlewares.api-token]
      [http.middlewares.api-token.plugin]
        [http.middlewares.api-token.plugin.traefik-api-token-middleware]
          authenticationHeader = true
          authenticationHeaderName = "X-API-TOKEN"
          authenticationErrorMsg = "Invalid token"
          bearerHeader = true
          bearerHeaderName = "Authorization"
          removeHeadersOnSuccess = true
          removeTokenNameOnFailure = false
          timestampUnix = false
          tokens = ["your-api-token"]



Contributors ✨

We are always looking for contributors. If you feel that you can provide something useful to Gistr, then we'd love to review your suggestion. Before submitting your contribution, please review the following resources:


Want to help but can't write code?


Alt


The following people have helped get this project going:




Documentation

Index

Constants

This section is empty.

Variables

View Source
var BBlack = "\033[1;30m"
View Source
var BBlue = "\033[1;34m"
View Source
var BCyan = "\033[1;36m"
View Source
var BGreen = "\033[1;32m"
View Source
var BPurple = "\033[1;35m"
View Source
var BRed = "\033[1;31m"
View Source
var BWhite = "\033[1;37m"
View Source
var BYellow = "\033[1;33m"
View Source
var Blue = "\033[34m"
View Source
var BlueL = "\033[94m"
View Source
var Cyan = "\033[36m"
View Source
var Gray = "\033[37m"
View Source
var GrayD = "\033[90m"
View Source
var Green = "\033[32m"
View Source
var GreenL = "\033[92m"
View Source
var Magenta = "\033[35m"
View Source
var Orange = "\033[33m"
View Source
var PurpleL = "\033[95m"
View Source
var Red = "\033[31m"
View Source
var RedL = "\033[91m"
View Source
var Reset = "\033[0m"
View Source
var White = "\033[97m"
View Source
var Yellow = "\033[93m"

Functions

func New

func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error)

Types

type Config

type Config struct {
	AuthenticationHeader     bool     `json:"authenticationHeader,omitempty"`
	AuthenticationHeaderName string   `json:"authenticationHeaderName,omitempty"`
	AuthenticationErrorMsg   string   `json:"authenticationErrorMsg,omitempty"`
	BearerHeader             bool     `json:"bearerHeader,omitempty"`
	BearerHeaderName         string   `json:"bearerHeaderName,omitempty"`
	PermissiveMode           bool     `json:"permissiveMode,omitempty"`
	RemoveHeadersOnSuccess   bool     `json:"removeHeadersOnSuccess,omitempty"`
	RemoveTokenNameOnFailure bool     `json:"removeTokenNameOnError,omitempty"`
	TimestampUnix            bool     `json:"timestampUnix,omitempty"`
	DebugLogs                bool     `json:"debugLogs,omitempty"`
	InternalErrorRoute       string   `json:"internalErrorRoute,omitempty"`
	Tokens                   []string `json:"tokens,omitempty"`
	WhitelistIPs             []string `yaml:"whitelistIPs,omitempty"`
	RegexAllow               []string `json:"regexAllow,omitempty"`
	RegexDeny                []string `json:"regexDeny,omitempty"`
}

func CreateConfig

func CreateConfig() *Config

type KeyAuth

type KeyAuth struct {
	// contains filtered or unexported fields
}

func (*KeyAuth) ServeHTTP

func (ka *KeyAuth) ServeHTTP(rw http.ResponseWriter, req *http.Request)

type Response

type Response struct {
	Message    string `json:"message"`
	StatusCode int    `json:"status_code"`
	Timestamp  string `json:"timestamp"`
	UserAgent  string `json:"user-agent"`
	RemoteAddr string `json:"ip"`
	Host       string `json:"host"`
	RequestURI string `json:"uri"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL