Skip to content
This repository has been archived by the owner on Apr 29, 2024. It is now read-only.

Commit

Permalink
Initial checking
Browse files Browse the repository at this point in the history
  • Loading branch information
pvliesdonk committed Dec 14, 2022
1 parent 4682a97 commit 9d0248d
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 121 deletions.
10 changes: 5 additions & 5 deletions .traefik.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
displayName: Demo Plugin
displayName: mTLS forward
type: middleware
iconPath: .assets/icon.png

import: github.com/traefik/plugindemo
import: https://github.com/pvliesdonk/traefik_mtls_forward

summary: '[Demo] Add Request Header'
summary: 'Forward mTLS client certificate as SSL_CLIENT_CERT and CERT_CHAIN_# headers for use with Wildfly/Undertow services like Keycloak.'

testData:
Headers:
X-Demo: test
X-URL: '{{URL}}'
sslClientCert: SSL_CLIENT_CERT
sslCertChainPrefix: CERT_CHAIN
66 changes: 0 additions & 66 deletions demo.go

This file was deleted.

49 changes: 0 additions & 49 deletions demo_test.go

This file was deleted.

2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/traefik/plugindemo
module github.com/pvliesdonk/traefik_mtls_forward

go 1.19
73 changes: 73 additions & 0 deletions mtlsforward.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Package mtlsforward implements a middleware for
// Traefik Proxy that forwards mTLS certificates inside
// HTTP headers.
package mtlsforward

import (
"context"
"encoding/pem"
"fmt"
"net/http"
"net/url"
"strconv"
)

// Config handles configuration of the sslClientCert (e.g. SSL_CLIENT_CERT) and sslCertChainPrefix (e.g. SSL_CERT_CHAIN) headers.
type Config struct {
Headers map[string]string
}

// CreateConfig creates the default plugin configuration.
func CreateConfig() *Config {
return &Config{
Headers: make(map[string]string),
}
}

// New created a new plugin.
func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error) {
_, ok := config.Headers["sslClientCert"]
if !ok {
return nil, fmt.Errorf("configuration option 'sslClientCert' not set")
}
_, ok = config.Headers["sslCertChainPrefix"]
if !ok {
return nil, fmt.Errorf("configuration option 'sslCertChainPrefix' not set")
}

return &mTLSForward{
headers: config.Headers,
next: next,
name: name,
}, nil
}

type mTLSForward struct {
headers map[string]string
next http.Handler
name string
}

func (m mTLSForward) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
// are we using mTLS?
if request.TLS != nil && len(request.TLS.PeerCertificates) > 0 {
for i, cert := range request.TLS.PeerCertificates {
fmt.Println("Found certificate with subject", cert.Subject, "issued by", cert.Issuer)
certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
if i == 0 {
// client cert
fmt.Println(string(certPEM))
request.Header.Set(m.headers["sslClientCert"], url.QueryEscape(string(certPEM)))
} else {
// part of chain
headerName := m.headers["sslCertChainPrefix"] + "_" + strconv.Itoa(i-1)
fmt.Println(string(certPEM))
request.Header.Set(headerName, url.QueryEscape(string(certPEM)))
}
}
}
fmt.Println("Ready for next plugin")

// call to next plugin
m.next.ServeHTTP(writer, request)
}

0 comments on commit 9d0248d

Please sign in to comment.