Skip to content
Snippets Groups Projects
Commit 0a876c75 authored by Rohith Jayawardene's avatar Rohith Jayawardene Committed by Rohith
Browse files

Proxy proto test (#214)

Proxy Protocol Unit Test
parent 1e41461b
No related branches found
No related tags found
No related merge requests found
......@@ -4,6 +4,7 @@ FIXES:
* fixed the parsing of slices for command line arguments (i.e. --cors-origins etc)
* fixed any accidental proxying on the /oauth or /debug URI
* removed all references to the underlining web framework in tests
* adding unit tests for proxy protocol and using the run() method [#PR214](https://github.com/gambol99/keycloak-proxy/pull/214)
FEATURES
* changed the routing engine from gin to echo
......
......@@ -16,9 +16,10 @@ limitations under the License.
package main
import (
"fmt"
"io/ioutil"
"net"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
......@@ -43,6 +44,7 @@ type fakeRequest struct {
NotSigned bool
OnResponse func(int, *resty.Request, *resty.Response)
Password string
ProxyProtocol string
ProxyRequest bool
RawToken string
Redirects bool
......@@ -65,7 +67,6 @@ type fakeProxy struct {
config *Config
idp *fakeAuthServer
proxy *oauthProxy
server *httptest.Server
cookies map[string]*http.Cookie
}
......@@ -82,22 +83,29 @@ func newFakeProxy(c *Config) *fakeProxy {
panic("failed to create fake proxy service, error: " + err.Error())
}
proxy.upstream = &fakeUpstreamService{}
service := httptest.NewServer(proxy.router)
c.RedirectionURL = service.URL
if err = proxy.Run(); err != nil {
panic("failed to create the proxy service, error: " + err.Error())
}
c.RedirectionURL = fmt.Sprintf("http://%s", proxy.listener.Addr().String())
// step: we need to update the client configs
if proxy.client, proxy.idp, proxy.idpClient, err = newOpenIDClient(c); err != nil {
panic("failed to recreate the openid client, error: " + err.Error())
}
return &fakeProxy{c, auth, proxy, service, make(map[string]*http.Cookie)}
return &fakeProxy{c, auth, proxy, make(map[string]*http.Cookie)}
}
func (f *fakeProxy) getServiceURL() string {
return fmt.Sprintf("http://%s", f.proxy.listener.Addr().String())
}
// RunTests performs a series of requests against a fake proxy service
func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
defer func() {
f.idp.Close()
f.server.Close()
f.proxy.server.Close()
}()
for i, c := range requests {
var upstream fakeUpstreamResponse
......@@ -110,6 +118,21 @@ func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
client := resty.New()
request := client.SetRedirectPolicy(resty.NoRedirectPolicy()).R()
if c.ProxyProtocol != "" {
client.SetTransport(&http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
conn, err := net.Dial("tcp", addr)
if err != nil {
return nil, err
}
header := fmt.Sprintf("PROXY TCP4 %s 10.0.0.1 1000 2000\r\n", c.ProxyProtocol)
conn.Write([]byte(header))
return conn, nil
},
})
}
// are we performing a oauth login beforehand
if c.HasLogin {
if err := f.performUserLogin(c.URI); err != nil {
......@@ -126,7 +149,7 @@ func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
request.SetResult(&upstream)
}
if c.ProxyRequest {
request.SetProxy(f.server.URL)
request.SetProxy(f.getServiceURL())
}
if c.BasicAuth {
request.SetBasicAuth(c.Username, c.Password)
......@@ -168,7 +191,7 @@ func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
var err error
switch c.URL {
case "":
resp, err = request.Execute(c.Method, f.server.URL+c.URI)
resp, err = request.Execute(c.Method, f.getServiceURL()+c.URI)
default:
resp, err = request.Execute(c.Method, c.URL)
}
......@@ -226,7 +249,7 @@ func (f *fakeProxy) RunTests(t *testing.T, requests []fakeRequest) {
}
func (f *fakeProxy) performUserLogin(uri string) error {
resp, err := makeTestCodeFlowLogin(f.server.URL + uri)
resp, err := makeTestCodeFlowLogin(f.getServiceURL() + uri)
if err != nil {
return err
}
......
......@@ -62,6 +62,10 @@ type oauthProxy struct {
store storage
// the prometheus handler
prometheusHandler http.Handler
// the default server
server *http.Server
// the default listener
listener net.Listener
}
func init() {
......@@ -284,19 +288,23 @@ func (r *oauthProxy) Run() error {
Addr: r.config.Listen,
Handler: r.router,
}
r.server = server
r.listener = listener
go func() {
log.Infof("keycloak proxy service starting on %s", r.config.Listen)
if err = server.Serve(listener); err != nil {
if err != http.ErrServerClosed {
log.WithFields(log.Fields{
"error": err.Error(),
}).Fatalf("failed to start the http service")
}
}
}()
// step: are we running http service as well?
if r.config.ListenHTTP != "" {
log.Infof("keycloak proxy service starting on %s", r.config.ListenHTTP)
log.Infof("keycloak proxy http service starting on %s", r.config.ListenHTTP)
httpListener, err := createHTTPListener(listenerConfig{
listen: r.config.ListenHTTP,
proxyProtocol: r.config.EnableProxyProtocol,
......
......@@ -171,6 +171,33 @@ func TestAuthorizationTemplate(t *testing.T) {
newFakeProxy(cfg).RunTests(t, requests)
}
func TestProxyProtocol(t *testing.T) {
c := newFakeKeycloakConfig()
c.EnableProxyProtocol = true
requests := []fakeRequest{
{
URI: fakeAuthAllURL + "/test",
HasToken: true,
ExpectedProxy: true,
ExpectedProxyHeaders: map[string]string{
"X-Forwarded-For": "127.0.0.1",
},
ExpectedCode: http.StatusOK,
},
{
URI: fakeAuthAllURL + "/test",
HasToken: true,
ProxyProtocol: "189.10.10.1",
ExpectedProxy: true,
ExpectedProxyHeaders: map[string]string{
"X-Forwarded-For": "189.10.10.1",
},
ExpectedCode: http.StatusOK,
},
}
newFakeProxy(c).RunTests(t, requests)
}
func newTestService() string {
_, _, u := newTestProxyService(nil)
return u
......@@ -226,7 +253,6 @@ func newFakeKeycloakConfig() *Config {
CookieRefreshName: "kc-state",
DiscoveryURL: "127.0.0.1:0",
Listen: "127.0.0.1:0",
ListenHTTP: "127.0.0.1:0",
EnableAuthorizationHeader: true,
EnableLoginHandler: true,
EncryptionKey: "AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j",
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment