Skip to content

Instantly share code, notes, and snippets.

@liggitt
Last active May 10, 2021 16:10
Show Gist options
  • Save liggitt/3faccd9d95291a85b4ba to your computer and use it in GitHub Desktop.
Save liggitt/3faccd9d95291a85b4ba to your computer and use it in GitHub Desktop.
/*
Generate a config like this:
openshift start master --write-config=requestheader --master=https://127.0.0.1:8443 --etcd-dir=requestheader/etcd
Update requestheader/master-config.yaml:
identityProviders:
- challenge: true
login: true
name: header
provider:
apiVersion: v1
challengeURL: "http://127.0.0.1:1234/oauth/authorize?${query}"
loginURL: "http://127.0.0.1:1234/oauth/authorize?${query}"
kind: RequestHeaderIdentityProvider
headers:
- RemoteUser
Start openshift:
openshift start master --config=requestheader/master-config.yaml
Start the proxy:
go run proxy.go 127.0.0.1:1234 https://127.0.0.1:8443
*/
package main
import (
"crypto/tls"
"fmt"
"io"
"net/http"
"net/url"
"os"
)
func main() {
args := os.Args[1:]
if len(args) != 2 {
fmt.Println("Usage: go run proxy.go listenhost:port http://backendhost:port")
os.Exit(1)
}
// Set up an auth proxy
proxyTransport := &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
}
proxyAddr := args[0]
backendURL, err := url.Parse(args[1])
if err != nil || backendURL.Scheme == "" || backendURL.Host == "" {
fmt.Println("invalid backend %q: %v", args[1], err)
os.Exit(1)
}
fmt.Println("Starting server. Any username is accepted with the password 'secret'. Press ctrl+c to stop...")
server := &http.Server{Addr: proxyAddr, Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.URL.String())
// Decide whether to challenge
username, password, _ := r.BasicAuth()
if username == "" || password != "secret" {
fmt.Println("Challenging")
w.Header().Set("WWW-Authenticate", `Basic realm="Protected Area"`)
w.WriteHeader(401)
return
}
// Swap the scheme and host to the master, keeping path and params the same
proxyURL := r.URL
proxyURL.Scheme = backendURL.Scheme
proxyURL.Host = backendURL.Host
// Build a request, copying the original method, body, and headers, overriding the remote user headers
proxyRequest, _ := http.NewRequest(r.Method, proxyURL.String(), r.Body)
proxyRequest.Header = r.Header
proxyRequest.Header.Set("RemoteUser", username)
// Round trip to the back end
response, err := proxyTransport.RoundTrip(r)
if err != nil {
fmt.Printf("Unexpected error: %v\n", err)
return
}
defer response.Body.Close()
// Copy response back to originator
for k, v := range response.Header {
w.Header()[k] = v
}
w.WriteHeader(response.StatusCode)
if _, err := io.Copy(w, response.Body); err != nil {
fmt.Printf("Unexpected error: %v\n", err)
return
}
})}
fmt.Println(server.ListenAndServe())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment