Skip to content
Snippets Groups Projects
Commit 36215832 authored by Rohith's avatar Rohith
Browse files

Merge pull request #24 from gambol99/cors_config

- cleaning up the cors options
parents 15d55b51 c48d52cd
No related branches found
No related tags found
No related merge requests found
......@@ -40,7 +40,7 @@ func newDefaultConfig() *Config {
TagData: make(map[string]string, 0),
ClaimsMatch: make(map[string]string, 0),
Header: make(map[string]string, 0),
CORSConfig: &CORS{
CORS: &CORS{
Origins: []string{},
Methods: []string{},
Headers: []string{},
......@@ -203,6 +203,24 @@ func readOptions(cx *cli.Context, config *Config) (err error) {
if cx.IsSet("hostname") {
config.Hostnames = cx.StringSlice("hostname")
}
if cx.IsSet("cors-origins") {
config.CORS.Origins = cx.StringSlice("cors-origins")
}
if cx.IsSet("cors-methods") {
config.CORS.Methods = cx.StringSlice("cors-methods")
}
if cx.IsSet("cors-headers") {
config.CORS.Headers = cx.StringSlice("cors-headers")
}
if cx.IsSet("cors-exposed-headers") {
config.CORS.ExposedHeaders = cx.StringSlice("cors-exposed-headers")
}
if cx.IsSet("cors-max-age") {
config.CORS.MaxAge = cx.Duration("cors-max-age")
}
if cx.IsSet("cors-credentials") {
config.CORS.Credentials = cx.BoolT("cors-credentials")
}
if cx.IsSet("tag") {
config.TagData, err = decodeKeyPairs(cx.StringSlice("tag"))
if err != nil {
......@@ -221,18 +239,7 @@ func readOptions(cx *cli.Context, config *Config) (err error) {
return err
}
}
if cx.IsSet("cors-origins") {
config.CORSConfig.Origins = cx.StringSlice("cors-origins")
}
if cx.IsSet("cors-methods") {
config.CORSConfig.Methods = cx.StringSlice("cors-methods")
}
if cx.IsSet("cors-headers") {
config.CORSConfig.Headers = cx.StringSlice("cors-headers")
}
if cx.IsSet("cors-max-age") {
config.CORSConfig.MaxAge = cx.Duration("cors-max-age")
}
if cx.IsSet("resource") {
for _, x := range cx.StringSlice("resource") {
resource, err := decodeResource(x)
......@@ -355,18 +362,26 @@ func getOptions() []cli.Flag {
Name: "cors-origins",
Usage: "a set of origins to add to the CORS access control (Access-Control-Allow-Origin)",
},
cli.StringSliceFlag{
Name: "cors-methods",
Usage: "the method permitted in the access control (Access-Control-Allow-Methods)",
},
cli.StringSliceFlag{
Name: "cors-headers",
Usage: "a set of headers to add to the CORS access control (Access-Control-Allow-Headers)",
},
cli.StringSliceFlag{
Name: "cors-methods",
Usage: "the method permitted in the access control (Access-Control-Allow-Methods)",
Name: "cors-exposes-headers",
Usage: "set the expose cors headers access control (Access-Control-Expose-Headers)",
},
cli.DurationFlag{
Name: "cors-max-age",
Usage: "the max age applied to cors headers (Access-Control-Max-Age)",
},
cli.BoolFlag{
Name: "cors-credentials",
Usage: "the credentials access control header (Access-Control-Allow-Credentials)",
},
cli.BoolFlag{
Name: "skip-token-verification",
Usage: "testing purposes ONLY, the option allows you to bypass the token verification, expiration and roles are still enforced",
......
......@@ -53,3 +53,19 @@ resources:
roles:
- openvpn:vpn-user
- openvpn:prod-vpn
# set the cross origin resource sharing headers
cors:
# an array of origins (Access-Control-Allow-Origin)
origins: []
# an array of headers to apply (Access-Control-Allow-Headers)
headers: []
# an array of expose headers (Access-Control-Expose-Headers)
exposed-headers: []
# an array of methods (Access-Control-Allow-Methods)
methods: []
# the credentials flag (Access-Control-Allow-Credentials)
credentials: true|false
# the max age (Access-Control-Max-Age)
max-age: 1h
......@@ -22,7 +22,7 @@ import (
const (
prog = "keycloak-proxy"
version = "v1.0.0-rc1"
version = "v1.0.0-rc2"
author = "Rohith"
email = "gambol99@gmail.com"
description = "is a proxy using the keycloak service for auth and authorization"
......@@ -67,7 +67,7 @@ type Resource struct {
Roles []string `json:"roles" yaml:"roles"`
}
// CORS controls
// CORS access controls
type CORS struct {
// Origins is a list of origins permitted
Origins []string `json:"origins" yaml:"origins"`
......@@ -75,6 +75,10 @@ type CORS struct {
Methods []string `json:"methods" yaml:"methods"`
// Headers is a set of cors headers
Headers []string `json:"headers" yaml:"headers"`
// ExposedHeaders are the exposed header fields
ExposedHeaders []string `json:"exposed-headers" yaml:"exposed-headers"`
// Credentials set the creds flag
Credentials bool `json:"credentials" yaml:"credentials"`
// MaxAge is the age for CORS
MaxAge time.Duration `json:"max-age" yaml:"max-age"`
}
......@@ -116,7 +120,7 @@ type Config struct {
// TagData is passed to the templates
TagData map[string]string `json:"TagData" yaml:"TagData"`
// CORS permits adding headers to the /oauth handlers
CORSConfig *CORS `json:"cors" yaml:"cors"`
CORS *CORS `json:"cors" yaml:"cors"`
// Header permits adding customs headers across the board
Header map[string]string `json:"headers" yaml:"headers"`
// Scopes is a list of scope we should request
......
......@@ -16,7 +16,6 @@ limitations under the License.
package main
import (
"fmt"
"net/http"
"path"
"regexp"
......@@ -452,9 +451,6 @@ func (r *KeycloakProxy) oauthAuthorizationHandler(cx *gin.Context) {
return
}
// step: add the cors headers
r.corsAccessHeaders(cx)
// step: get the redirection url
r.redirectToURL(redirectionURL, cx)
}
......@@ -564,9 +560,6 @@ func (r *KeycloakProxy) oauthCallbackHandler(cx *gin.Context) {
}
}
// step: add the cors headers
r.corsAccessHeaders(cx)
r.redirectToURL(state, cx)
}
......@@ -576,21 +569,3 @@ func (r *KeycloakProxy) oauthCallbackHandler(cx *gin.Context) {
func (r *KeycloakProxy) healthHandler(cx *gin.Context) {
cx.String(http.StatusOK, "OK")
}
// corsAccessHeaders adds the cors access controls to the oauth responses
func (r *KeycloakProxy) corsAccessHeaders(cx *gin.Context) {
cors := r.config.CORSConfig
if len(cors.Origins) > 0 {
cx.Writer.Header().Set("Access-Control-Allow-Origin", strings.Join(cors.Origins, ","))
}
if len(cors.Methods) > 0 {
cx.Writer.Header().Set("Access-Control-Allow-Methods", strings.Join(cors.Methods, ","))
}
if len(cors.Headers) > 0 {
cx.Writer.Header().Set("Access-Control-Allow-Headers", strings.Join(cors.Headers, ","))
}
if cors.MaxAge > 0 {
cx.Writer.Header().Set("Access-Control-Max-Age",
fmt.Sprintf("%d", int(cors.MaxAge.Seconds())))
}
}
......@@ -29,6 +29,7 @@ import (
log "github.com/Sirupsen/logrus"
"github.com/gin-gonic/gin"
"strings"
)
// KeycloakProxy is the server component
......@@ -193,7 +194,7 @@ func (r *KeycloakProxy) Run() error {
// redirectToURL redirects the user and aborts the context
func (r KeycloakProxy) redirectToURL(url string, cx *gin.Context) {
// step: add the cors headers
r.corsAccessHeaders(cx)
r.injectCORSHeaders(cx)
cx.Redirect(http.StatusTemporaryRedirect, url)
cx.Abort()
......@@ -227,6 +228,29 @@ func (r KeycloakProxy) redirectToAuthorization(cx *gin.Context) {
r.redirectToURL(authorizationURL+authQuery, cx)
}
// injectCORSHeaders adds the cors access controls to the oauth responses
func (r *KeycloakProxy) injectCORSHeaders(cx *gin.Context) {
c := r.config.CORS
if len(c.Origins) > 0 {
cx.Writer.Header().Set("Access-Control-Allow-Origin", strings.Join(c.Origins, ","))
}
if len(c.Methods) > 0 {
cx.Writer.Header().Set("Access-Control-Allow-Methods", strings.Join(c.Methods, ","))
}
if len(c.Headers) > 0 {
cx.Writer.Header().Set("Access-Control-Allow-Headers", strings.Join(c.Headers, ","))
}
if len(c.ExposedHeaders) > 0 {
cx.Writer.Header().Set("Access-Control-Expose-Headers", strings.Join(c.ExposedHeaders, ","))
}
if c.Credentials {
cx.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
}
if c.MaxAge > 0 {
cx.Writer.Header().Set("Access-Control-Max-Age", fmt.Sprintf("%d", int(c.MaxAge.Seconds())))
}
}
// tryUpdateConnection attempt to upgrade the connection to a http pdy stream
func (r *KeycloakProxy) tryUpdateConnection(cx *gin.Context) error {
// step: dial the endpoint
......
......@@ -94,7 +94,7 @@ func newFakeKeycloakProxy(t *testing.T) *KeycloakProxy {
Roles: []string{},
},
},
CORSConfig: &CORS{},
CORS: &CORS{},
},
proxy: new(fakeReverseProxy),
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment