Skip to content

Commit b16d19e

Browse files
committed
Echo Router (louketo#199)
- shifting over to the echo rather than gin web framework - adding the extra dependencies - dropped the cors middleware and using the default middles from echo router - completely removing gin tonic - adding the Renderer implementation - loading the templates for the custom pages - hooking in the drop for the proxy middleware - updating the readme to reflect the changes - updating the CHANGELOG to reflect the changes - updating the authors file - adding the extra test for api errors and drop refresh cookie - updated the golang version to v1.8 - shifting most of the checks into a common testing method makeFakeRequests() - fixed the cli parsing for slices, was incorrectly setting the reflected value - adding a quick check for the forwarding proxy - changed the option log-requests to --enable-logging - changed the option --json-format to --enable-json-logging - ensure nothing in /oauth is passed to the proxy forwarder. Echo doesnt not run middleware if no route is found, so was have to hack this slightly to get it to work - removed unrequired elements from the testing code - fixed the newTestToken; need to copy the map - updated the authors file - added test coverage for token refreshing - cleaned up some of the code around tests - fixed up the checks for the callback endpoint - update the kubernetes example files to deployments - fixed up the unit tests for the custom claims - added 'any|ANY' to the resource definition and expanded the tests
1 parent 4c755fb commit b16d19e

File tree

199 files changed

+13734
-11395
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

199 files changed

+13734
-11395
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ tests/db.bolt
99
test.sock
1010
tests/redis.conf
1111
tests/*.csr
12+
*.orig
13+
debug
1214

1315
*.iml
1416
config.yml

.travis.yml

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ services:
99
- docker
1010
language: go
1111
go:
12-
- 1.7
1312
- 1.8
1413
install:
1514
- go get github.com/tools/godep

AUTHORS

+2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
Allan Degnan <[email protected]>
22
Ben Marvell <[email protected]>
33
Chris Nesbitt-Smith <[email protected]>
4+
Jiten Bhagat <[email protected]>
45
johanneslanger <[email protected]>
6+
57
Rémi Vion <[email protected]>
68
79
Rohith Jayawardene <[email protected]>

CHANGELOG.md

+21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,24 @@
1+
#### **2.1.0**
2+
3+
FIXES:
4+
* fixed the parsing of slices for command line arguments (i.e. --cors-origins etc)
5+
* fixed any accidental proxying on the /oauth or /debug URI
6+
* removed all references to the underlining web framework in tests
7+
8+
FEATURES
9+
* changed the routing engine from gin to echo
10+
* we now normalize all inbound URI before applying the protection middleware
11+
* the order of the resources are no longer important, the framework will handle the routing
12+
* improved the overall spec of the proxy by removing URL inspection and prefix checking
13+
* removed the CORS implementation and using the default echo middles, which is more compliant
14+
15+
BREAKING CHANGES:
16+
* the proxy no longer uses prefixes for resources, if you wish to use wildcard urls you need
17+
to specify it, i.e. --resource=/ becomes --resource=/* or =admin/ becomes =admin/* or /admin*;
18+
a full set of routing details can bt found at https://echo.labstack.com/guide/routing
19+
* removed the --enable-cors-global option, CORS is now handled the default echo middleware
20+
* changed option from log-requests -> enable-logging
21+
* changed option from json-format -> enable-json-logging
122

223
#### **2.0.5 (unreleased)**
324

Godeps/Godeps.json

+58-22
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ NAME=keycloak-proxy
22
AUTHOR=gambol99
33
AUTHOR_EMAIL[email protected]
44
REGISTRY=quay.io
5-
GOVERSION ?= 1.7.3
5+
GOVERSION ?= 1.8.0
66
SUDO=
77
ROOT_DIR=${PWD}
88
HARDWARE=$(shell uname -m)

README.md

+31-20
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@
2424
Keycloak-proxy is a proxy service which at the risk of stating the obvious integrates with the [Keycloak](https://github.com/keycloak/keycloak) authentication service. Although technically the service has no dependency on Keycloak itself and would quite happily work with any OpenID provider. The service supports both access tokens in browser cookie or bearer tokens.
2525

2626
```shell
27-
[jest@starfury keycloak-proxy]$ bin/keycloak-proxy help
27+
[jest@starfury keycloak-proxy]$ bin/keycloak-proxy --help
2828
NAME:
2929
keycloak-proxy - is a proxy using the keycloak service for auth and authorization
3030

3131
USAGE:
3232
keycloak-proxy [options]
3333

3434
VERSION:
35-
v2.0.2 (git+sha: 260d2c8-dirty)
35+
v2.1.0 (git+sha: f74c713)
3636

3737
AUTHOR:
3838
@@ -47,14 +47,15 @@ GLOBAL OPTIONS:
4747
--discovery-url value discovery url to retrieve the openid configuration [$PROXY_DISCOVERY_URL]
4848
--client-id value client id used to authenticate to the oauth service [$PROXY_CLIENT_ID]
4949
--client-secret value client secret used to authenticate to the oauth service [$PROXY_CLIENT_SECRET]
50-
--redirection-url value redirection url for the oauth callback url [$PROXY_REDIRECTION_URL]
50+
--redirection-url value redirection url for the oauth callback url, defaults to host header is absent [$PROXY_REDIRECTION_URL]
5151
--revocation-url value url for the revocation endpoint to revoke refresh token [$PROXY_REVOCATION_URL]
5252
--skip-openid-provider-tls-verify skip the verification of any TLS communication with the openid provider (default: false)
5353
--scopes value list of scopes requested when authenticating the user
5454
--upstream-url value url for the upstream endpoint you wish to proxy [$PROXY_UPSTREAM_URL]
5555
--resources value list of resources 'uri=/admin|methods=GET,PUT|roles=role1,role2'
5656
--headers value custom headers to the upstream request, key=value
57-
--enable-cors-global inject the CORs headers into all responses (default: false) [$PROXY_ENABLE_CORS_GLOBAL]
57+
--enable-logging enable http logging of the requests (default: false)
58+
--enable-json-logging switch on json logging rather than text (default: false)
5859
--enable-forwarding enables the forwarding proxy mode, signing outbound request (default: false)
5960
--enable-security-filter enables the security filter handler (default: false)
6061
--enable-refresh-tokens nables the handling of the refresh tokens (default: false) [$PROXY_ENABLE_SECURITY_FILTER]
@@ -68,6 +69,7 @@ GLOBAL OPTIONS:
6869
--filter-frame-deny enable to the frame deny header (default: false)
6970
--content-security-policy value specify the content security policy
7071
--localhost-metrics enforces the metrics page can only been requested from 127.0.0.1 (default: false)
72+
--access-token-duration value fallback cookie duration for the access token when using refresh tokens (default: 720h0m0s)
7173
--cookie-domain value domain the access cookie is available to, defaults host header
7274
--cookie-access-name value name of the cookie use to hold the access token (default: "kc-access")
7375
--cookie-refresh-name value name of the cookie used to hold the encrypted refresh token (default: "kc-state")
@@ -89,9 +91,7 @@ GLOBAL OPTIONS:
8991
--cors-max-age value max age applied to cors headers (Access-Control-Max-Age) (default: 0s)
9092
--hostnames value list of hostnames the service will respond to
9193
--store-url value url for the storage subsystem, e.g redis://127.0.0.1:6379, file:///etc/tokens.file
92-
--encryption-key value encryption key used to encrpytion the session state
93-
--log-requests enable http logging of the requests (default: false)
94-
--json-format switch on json logging rather than text (default: false)
94+
--encryption-key value encryption key used to encryption the session state [$PROXY_ENCRYPTION_KEY]
9595
--no-redirects do not have back redirects when no authentication is present, 401 them (default: false)
9696
--skip-token-verification TESTING ONLY; bypass token verification, only expiration and roles enforced (default: false)
9797
--upstream-keepalives enables or disables the keepalive connections for upstream endpoint (default: false)
@@ -122,7 +122,7 @@ Docker image is available at [https://quay.io/repository/gambol99/keycloak-proxy
122122
Configuration can come from a yaml/json file and or the command line options (note, command options have a higher priority and will override or merge any options referenced in a config file)
123123
124124
```YAML
125-
# is the url for retrieve the openid configuration - normally the <server>/auth/realm/<realm_name>
125+
# is the url for retrieve the OpenID configuration - normally the <server>/auth/realm/<realm_name>
126126
discovery-url: https://keycloak.example.com/auth/realms/<REALM_NAME>
127127
# the client id for the 'client' application
128128
client-id: <CLIENT_ID>
@@ -158,7 +158,7 @@ resources:
158158
- openvpn:vpn-user
159159
- openvpn:prod-vpn
160160
- test
161-
- uri: /admin
161+
- uri: /admin/*
162162
methods:
163163
- GET
164164
roles:
@@ -188,13 +188,13 @@ redirection-url: http://127.0.0.1:3000
188188
encryption_key: AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j
189189
upstream-url: http://127.0.0.1:80
190190
resources:
191-
- uri: /admin
191+
- uri: /admin*
192192
methods:
193193
- GET
194194
roles:
195195
- client:test1
196196
- client:test2
197-
- uri: /backend
197+
- uri: /backend*
198198
roles:
199199
- client:test1
200200
```
@@ -211,19 +211,30 @@ bin/keycloak-proxy \
211211
--enable-refresh-token=true \
212212
--encryption-key=AgXa7xRcoClDEU0ZDSH4X0XhL5Qy2Z2j \
213213
--upstream-url=http://127.0.0.1:80 \
214-
--resources="uri=/admin|methods=GET|roles=test1,test2" \
215-
--resources="uri=/backend|roles=test1"
214+
--resources="uri=/admin*|methods=GET|roles=test1,test2" \
215+
--resources="uri=/backend*|roles=test1"
216216
```
217217
218+
#### **HTTP Routing**
219+
220+
By default all requests will be proxyed on to the upstream, if you wish to ensure all requests are authentication you can use
221+
222+
```shell
223+
--resource=uri=/* # note, by default unless specified the methods is assumed to be 'any|ANY'
224+
```
225+
226+
Note the HTTP routing rules following the guidelines from [echo](https://echo.labstack.com/guide/routing). Its also worth nothing the ordering of the resource do not matter, the router will handle that for you.
227+
218228
#### **Google OAuth**
229+
219230
Although the role extensions do require a Keycloak IDP or at the very least a IDP that produces a token which contains roles, there's nothing stopping you from using it against any OpenID providers, such as Google. Go to the Google Developers Console and create a new application *(via "Enable and Manage APIs -> Credentials)*. Once you've created the application, take the client id, secret and make sure you've added the callback url to the application scope *(using the default this would be http://127.0.0.1:3000/oauth/callback)*
220231
221232
``` shell
222233
bin/keycloak-proxy \
223234
--discovery-url=https://accounts.google.com/.well-known/openid-configuration \
224235
--client-id=<CLIENT_ID> \
225236
--client-secret=<CLIENT_SECRET> \
226-
--resources="uri=/" \
237+
--resources="uri=/*" \
227238
--verbose=true
228239
```
229240
@@ -403,13 +414,13 @@ By default the proxy will immediately redirect you for authentication and hand b
403414
404415
#### **White-listed URL's**
405416
406-
Depending on how the application url's are laid out, you might want protect the root / url but have exceptions on a list of paths, i.e. /health etc. Although you should probably fix this by fixing up the paths, you can add excepts to the protected resources. (Note: it's an array, so the order is important)
417+
Depending on how the application url's are laid out, you might want protect the root / url but have exceptions on a list of paths, i.e. /health etc. Although you should probably fix this by fixing up the paths, you can add excepts to the protected resources.
407418
408419
```YAML
409420
resources:
410421
- url: /some_white_listed_url
411422
white-listed: true
412-
- url: /
423+
- url: /*
413424
methods:
414425
- GET
415426
roles:
@@ -421,7 +432,7 @@ Or on the command line
421432
422433
```shell
423434
--resources "uri=/some_white_listed_url|white-listed=true"
424-
--resources "uri=/" # requires authentication on the rest
435+
--resources "uri=/*" # requires authentication on the rest
425436
--resources "uri=/admin|roles=admin,superuser|methods=POST,DELETE
426437
```
427438
@@ -445,7 +456,7 @@ A /oauth/logout?redirect=url is provided as a helper to logout the users. Aside
445456
446457
#### **Cross Origin Resource Sharing (CORS)**
447458
448-
You can add CORS header via the --cors-[method] command line or configuration options. By default this will inject CORS header into all response from the /oauth/* and any authentication required redirects, though you can enable these globally for all responses via the --enable-cors-global option.
459+
You can add CORS header via the --cors-[method] command line or configuration options.
449460
450461
* Access-Control-Allow-Origin
451462
* Access-Control-Allow-Methods
@@ -479,8 +490,8 @@ You can control the upstream endpoint via the --upstream-url option. Both http a
479490
480491
#### **Endpoints**
481492
482-
* **/oauth/authorize** is authentication endpoint which will generate the openid redirect to the provider
483-
* **/oauth/callback** is provider openid callback endpoint
493+
* **/oauth/authorize** is authentication endpoint which will generate the OpenID redirect to the provider
494+
* **/oauth/callback** is provider OpenID callback endpoint
484495
* **/oauth/expired** is a helper endpoint to check if a access token has expired, 200 for ok and, 401 for no token and 401 for expired
485496
* **/oauth/health** is the health checking endpoint for the proxy, you can also grab version from headers
486497
* **/oauth/login** provides a relay endpoint to login via grant_type=password i.e. POST /oauth/login form values are username=USERNAME&password=PASSWORD (must be enabled)

cli.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,7 @@ func parseCLIOptions(cx *cli.Context, config *Config) (err error) {
169169
case reflect.String:
170170
reflect.ValueOf(config).Elem().FieldByName(field.Name).SetString(cx.String(name))
171171
case reflect.Slice:
172-
for _, x := range cx.StringSlice(name) {
173-
reflect.Append(reflect.ValueOf(config).Elem().FieldByName(field.Name), reflect.ValueOf(x))
174-
}
172+
reflect.ValueOf(config).Elem().FieldByName(field.Name).Set(reflect.ValueOf(cx.StringSlice(name)))
175173
case reflect.Int64:
176174
switch field.Type.String() {
177175
case "time.Duration":

cli_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,15 @@ package main
1818
import (
1919
"testing"
2020

21+
"github.com/stretchr/testify/assert"
2122
"github.com/urfave/cli"
2223
)
2324

25+
func TestNewOauthProxyApp(t *testing.T) {
26+
a := newOauthProxyApp()
27+
assert.NotNil(t, a)
28+
}
29+
2430
func TestGetCLIOptions(t *testing.T) {
2531
if flags := getCommandLineOptions(); flags == nil {
2632
t.Error("we should have received some flags options")

0 commit comments

Comments
 (0)