Skip to content
This repository has been archived by the owner on Jul 25, 2023. It is now read-only.

Commit

Permalink
adding authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
Maliheh committed May 21, 2019
1 parent c3b7762 commit 6e06324
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 41 deletions.
35 changes: 31 additions & 4 deletions internal/devproxy/dev_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,27 @@ type UpstreamConfig struct {
HeaderOverrides map[string]string
TLSSkipVerify bool
SkipRequestSigning bool
User string
Groups string
Email string
}

// RouteConfig maps to the yaml config fields,
// * "from" - the domain that will be used to access the service
// * "to" - the cname of the proxied service (this tells sso proxy where to proxy requests that come in on the from field)
type RouteConfig struct {
From string `yaml:"from"`
To string `yaml:"to"`
Type string `yaml:"type"`
Options *OptionsConfig `yaml:"options"`
From string `yaml:"from"`
To string `yaml:"to"`
Type string `yaml:"type"`
Options *OptionsConfig `yaml:"options"`
UserInfo *UserInfo `yaml:"user_info"`
}

//UserInfo is going to be injected into the header
type UserInfo struct {
User string `yaml:"user"`
Groups string `yaml:"groups"`
Email string `yaml:"email"`
}

// OptionsConfig maps to the yaml config fields:
Expand Down Expand Up @@ -177,6 +188,10 @@ func loadServiceConfigs(raw []byte, cluster, scheme string, configVars map[strin
if err != nil {
return nil, err
}
err = parseUserInfoConfig(proxy)
if err != nil {
return nil, err
}
}

for _, proxy := range configs {
Expand Down Expand Up @@ -353,6 +368,18 @@ func parseOptionsConfig(proxy *UpstreamConfig) error {
return nil
}

func parseUserInfoConfig(proxy *UpstreamConfig) error {
if proxy.RouteConfig.UserInfo == nil {
return nil
}

proxy.User = proxy.RouteConfig.UserInfo.User
proxy.Groups = proxy.RouteConfig.UserInfo.Groups
proxy.Email = proxy.RouteConfig.UserInfo.Email

return nil
}

func cleanWhiteSpace(s string) string {
// This trims all white space from a service name and collapses all remaining space to `_`
return space.ReplaceAllString(strings.TrimSpace(s), "_") //
Expand Down
36 changes: 24 additions & 12 deletions internal/devproxy/devproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,30 @@ const HMACSignatureHeader = "Gap-Signature"

// SignatureHeaders are the headers that are valid in the request.
var SignatureHeaders = []string{
"Content-Length",
"Content-Md5",
"Content-Type",
"Date",
"Authorization",
"X-Forwarded-User",
"X-Forwarded-Email",
"X-Forwarded-Groups",
"X-Forwarded-Access-Token",
"Cookie",
}

const statusInvalidHost = 421

// DevProxy stores all the information associated with proxying the request.
type DevProxy struct {
// redirectURL *url.URL // the url to receive requests at
skipAuthPreflight bool
templates *template.Template
mux map[string]*route
regexRoutes []*route
requestSigner *RequestSigner
publicCertsJSON []byte
user string
groups string
email string
}

type route struct {
Expand All @@ -61,6 +68,7 @@ type StateParameter struct {
type UpstreamProxy struct {
name string
handler http.Handler
auth hmacauth.HmacAuth
requestSigner *RequestSigner
}

Expand Down Expand Up @@ -104,9 +112,10 @@ func newUpstreamTransport(insecureSkipVerify bool) *upstreamTransport {

// ServeHTTP calls the upstream's ServeHTTP function.
func (u *UpstreamProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {

if u.auth != nil {
u.auth.SignRequest(r)
}
if u.requestSigner != nil {

u.requestSigner.Sign(r)
}

Expand Down Expand Up @@ -157,6 +166,7 @@ func NewReverseProxy(to *url.URL, config *UpstreamConfig) *httputil.ReverseProxy
dir(req)
req.Host = to.Host
}

return proxy
}

Expand Down Expand Up @@ -194,6 +204,7 @@ func NewReverseProxyHandler(reverseProxy *httputil.ReverseProxy, opts *Options,
upstreamProxy := &UpstreamProxy{
name: config.Service,
handler: reverseProxy,
auth: config.HMACAuth,
requestSigner: signer,
}

Expand Down Expand Up @@ -274,10 +285,8 @@ func NewDevProxy(opts *Options, optFuncs ...func(*DevProxy) error) (*DevProxy, e

p := &DevProxy{
// these fields make up the routing mechanism
mux: make(map[string]*route),
regexRoutes: make([]*route, 0),

// redirectURL: &url.URL{Path: "/oauth2/callback"},
mux: make(map[string]*route),
regexRoutes: make([]*route, 0),
templates: getTemplates(),
requestSigner: requestSigner,
publicCertsJSON: certsAsStr,
Expand All @@ -289,8 +298,10 @@ func NewDevProxy(opts *Options, optFuncs ...func(*DevProxy) error) (*DevProxy, e
return nil, err
}
}

for _, upstreamConfig := range opts.upstreamConfigs {
p.user = upstreamConfig.User
p.email = upstreamConfig.Email
p.groups = upstreamConfig.Groups
switch route := upstreamConfig.Route.(type) {
case *SimpleRoute:
reverseProxy := NewReverseProxy(route.ToURL, upstreamConfig)
Expand Down Expand Up @@ -419,6 +430,7 @@ func (p *DevProxy) UnknownHost(rw http.ResponseWriter, req *http.Request) {

// Handle constructs a route from the given host string and matches it to the provided http.Handler and UpstreamConfig
func (p *DevProxy) Handle(host string, handler http.Handler, tags []string, upstreamConfig *UpstreamConfig) {

tags = append(tags, "route:simple")
p.mux[host] = &route{handler: handler, upstreamConfig: upstreamConfig, tags: tags}
}
Expand All @@ -430,9 +442,9 @@ func (p *DevProxy) HandleRegex(regex *regexp.Regexp, handler http.Handler, tags
}

func (p *DevProxy) setProxyHeaders(rw http.ResponseWriter, req *http.Request) (err error) {
req.Header.Set("X-Forwarded-User", req.Header.Get("User"))
req.Header.Set("X-Forwarded-Email", req.Header.Get("Email"))
req.Header.Set("X-Forwarded-Groups", req.Header.Get("groups"))
req.Header.Set("X-Forwarded-User", p.user)
req.Header.Set("X-Forwarded-Email", p.email)
req.Header.Set("X-Forwarded-Groups", p.groups)
// req.Header.set("X-Forwarded-Access-Token", "")
return nil
}
Expand Down
32 changes: 11 additions & 21 deletions internal/devproxy/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,17 @@ import (
// TCPWriteTimeout - http server tcp write timeout
// TCPReadTimeout - http server tcp read timeout
type Options struct {
Port int `envconfig:"PORT" default:"4180"`

UpstreamConfigsFile string `envconfig:"UPSTREAM_CONFIGS"`
Cluster string `envconfig:"CLUSTER"`
Scheme string `envconfig:"SCHEME" default:"https"`

Host string `envconfig:"HOST"`

Port int `envconfig:"PORT" default:"4180"`
UpstreamConfigsFile string `envconfig:"UPSTREAM_CONFIGS"`
Scheme string `envconfig:"SCHEME" default:"https"`
Host string `envconfig:"HOST"`
DefaultUpstreamTimeout time.Duration `envconfig:"DEFAULT_UPSTREAM_TIMEOUT" default:"10s"`

TCPWriteTimeout time.Duration `envconfig:"TCP_WRITE_TIMEOUT" default:"30s"`
TCPReadTimeout time.Duration `envconfig:"TCP_READ_TIMEOUT" default:"30s"`

RequestLogging bool `envconfig:"REQUEST_LOGGING" default:"true"`

RequestSigningKey string `envconfig:"REQUEST_SIGNATURE_KEY"`

TCPWriteTimeout time.Duration `envconfig:"TCP_WRITE_TIMEOUT" default:"30s"`
TCPReadTimeout time.Duration `envconfig:"TCP_READ_TIMEOUT" default:"30s"`
RequestLogging bool `envconfig:"REQUEST_LOGGING" default:"true"`
RequestSigningKey string `envconfig:"REQUEST_SIGNATURE_KEY"`
// This is an override for supplying template vars at test time
testTemplateVars map[string]string

// internal values that are set after config validation
upstreamConfigs []*UpstreamConfig
}
Expand All @@ -62,11 +53,10 @@ func parseURL(toParse string, urltype string, msgs []string) (*url.URL, []string
// Validate validates options
func (o *Options) Validate() error {
msgs := make([]string, 0)
if o.Cluster == "" {
msgs = append(msgs, "missing setting: cluster")
}

if o.UpstreamConfigsFile == "" {
msgs = append(msgs, "missing setting: upstream-configs")
o.UpstreamConfigsFile = "internal/devproxy/testdata/upstream_configs.yml"
}

if o.UpstreamConfigsFile != "" {
Expand All @@ -80,7 +70,7 @@ func (o *Options) Validate() error {
templateVars = o.testTemplateVars
}

o.upstreamConfigs, err = loadServiceConfigs(rawBytes, o.Cluster, o.Scheme, templateVars)
o.upstreamConfigs, err = loadServiceConfigs(rawBytes, "default", o.Scheme, templateVars)
if err != nil {
msgs = append(msgs, fmt.Sprintf("error parsing upstream configs file %s", err))
}
Expand Down
1 change: 1 addition & 0 deletions internal/devproxy/request_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ var signedHeaders = []string{
"X-Forwarded-User",
"X-Forwarded-Email",
"X-Forwarded-Groups",
"Cookie",
}

// Name of the header used to transmit the signature computed for the request.
Expand Down
5 changes: 3 additions & 2 deletions internal/devproxy/testdata/.env
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
export PORT=4888
export UPSTREAM_CONFIGS=/path/to/upstream_configs.yml
export SCHEME=http
export HOST=http://localhost/
export UPSTREAM_CONFIGS=/path/to/upstream_configs.yml
export CLUSTER=sso-dev
export DEFAULT_UPSTREAM_TIMEOUT=10s
export TCP_WRITE_TIMEOUT=30s
export TCP_READ_TIMEOUT=30s
export REQUEST_LOGGING=true
export REQUEST_SIGNATURE_KEY=$(cat /path/to/devproxy/testdata/private_key.pem)
export REQUEST_SIGNATURE_KEY=$(cat /path/to/private_key.pem)
export DEV_CONFIG_DEVSHIM_SIGNING_KEY="sha256:shared-secret-value"
7 changes: 5 additions & 2 deletions internal/devproxy/testdata/upstream_configs.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
- service: dev-shim
- service: devshim
default:
from: http://localhost:4888
to: http://localhost:4810
options:
skip_request_signing: false

user_info:
user: testUser
groups: team
email: [email protected]

0 comments on commit 6e06324

Please sign in to comment.