Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
D
dex
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
dex
Commits
a41d93db
Commit
a41d93db
authored
Oct 21, 2017
by
Michael Stapelberg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement the “authproxy” connector (for Apache2 mod_auth etc.)
parent
f3c85e69
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
169 additions
and
12 deletions
+169
-12
authproxy.md
Documentation/authproxy.md
+88
-0
README.md
README.md
+1
-0
authproxy.go
connector/authproxy/authproxy.go
+56
-0
github.go
connector/github/github.go
+1
-1
gitlab.go
connector/gitlab/gitlab.go
+1
-1
ldap.go
connector/ldap/ldap.go
+1
-1
connectortest.go
connector/mock/connectortest.go
+2
-2
oidc.go
connector/oidc/oidc.go
+1
-1
oidc_test.go
connector/oidc/oidc_test.go
+4
-3
saml.go
connector/saml/saml.go
+1
-1
handlers.go
server/handlers.go
+6
-0
server.go
server/server.go
+7
-2
No files found.
Documentation/authproxy.md
0 → 100644
View file @
a41d93db
# External authentication
## Overview
The authproxy connector returns identities based on authentication which your
front-end web server performs.
The connector does not support refresh tokens or groups at this point.
## Configuration
The following is an example config file that can be used by the external
connector to authenticate a user.
```
yaml
connectors
:
-
type
:
authproxy
id
:
myBasicAuth
name
:
HTTP Basic Auth
```
The authproxy connector assumes that you configured your front-end web server
such that it performs authentication for the
`/dex/callback/myBasicAuth`
location and provides the result in the X-Remote-User HTTP header. The following
configuration will work for Apache 2.4.10+:
```
<Location /dex/callback/myBasicAuth>
AuthType Basic
AuthName "db.debian.org webPassword"
AuthBasicProvider file
AuthUserFile "/etc/apache2/debian-web-pw.htpasswd"
Require valid-user
# Defense in depth: clear the Authorization header so that
# Debian Web Passwords never even reach dex.
RequestHeader unset Authorization
# Requires Apache 2.4.10+
RequestHeader set X-Remote-User expr=%{REMOTE_USER}@debian.org
ProxyPass "http://localhost:5556/dex/callback/myBasicAuth"
ProxyPassReverse "http://localhost:5556/dex/callback/myBasicAuth"
</Location>
```
## Full Apache2 setup
After installing your Linux distribution’s Apache2 package, place the following
virtual host configuration in e.g.
`/etc/apache2/sites-available/sso.conf`
:
```
<VirtualHost sso.example.net>
ServerName sso.example.net
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Location /dex/>
ProxyPass "http://localhost:5556/dex/"
ProxyPassReverse "http://localhost:5556/dex/"
</Location>
<Location /dex/callback/myBasicAuth>
AuthType Basic
AuthName "db.debian.org webPassword"
AuthBasicProvider file
AuthUserFile "/etc/apache2/debian-web-pw.htpasswd"
Require valid-user
# Defense in depth: clear the Authorization header so that
# Debian Web Passwords never even reach dex.
RequestHeader unset Authorization
# Requires Apache 2.4.10+
RequestHeader set X-Remote-User expr=%{REMOTE_USER}@debian.org
ProxyPass "http://localhost:5556/dex/callback/myBasicAuth"
ProxyPassReverse "http://localhost:5556/dex/callback/myBasicAuth"
</Location>
</VirtualHost>
```
Then, enable it using
`a2ensite sso.conf`
, followed by a restart of Apache2.
\ No newline at end of file
README.md
View file @
a41d93db
...
...
@@ -67,6 +67,7 @@ More docs for running dex as a Kubernetes authenticator can be found [here](Docu
*
[
GitLab
](
Documentation/gitlab-connector.md
)
*
[
SAML 2.0
](
Documentation/saml-connector.md
)
*
[
OpenID Connect
](
Documentation/oidc-connector.md
)
(
includes
Google, Salesforce, Azure, etc.)
*
[
authproxy
](
Documentation/authproxy.md
)
(
Apache2
mod_auth, etc.)
*
Client libraries
*
[
Go
][
go-oidc
]
...
...
connector/authproxy/authproxy.go
0 → 100644
View file @
a41d93db
// Package authproxy implements a connector which relies on external
// authentication (e.g. mod_auth in Apache2) and returns an identity with the
// HTTP header X-Remote-User as verified email.
package
authproxy
import
(
"fmt"
"net/http"
"net/url"
"github.com/coreos/dex/connector"
"github.com/sirupsen/logrus"
)
// Config holds the configuration parameters for a connector which returns an
// identity with the HTTP header X-Remote-User as verified email.
type
Config
struct
{}
// Open returns an authentication strategy which requires no user interaction.
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
return
&
callback
{
logger
:
logger
,
pathSuffix
:
"/"
+
id
},
nil
}
// Callback is a connector which returns an identity with the HTTP header
// X-Remote-User as verified email.
type
callback
struct
{
logger
logrus
.
FieldLogger
pathSuffix
string
}
// LoginURL returns the URL to redirect the user to login with.
func
(
m
*
callback
)
LoginURL
(
s
connector
.
Scopes
,
callbackURL
,
state
string
)
(
string
,
error
)
{
u
,
err
:=
url
.
Parse
(
callbackURL
)
if
err
!=
nil
{
return
""
,
fmt
.
Errorf
(
"failed to parse callbackURL %q: %v"
,
callbackURL
,
err
)
}
u
.
Path
=
u
.
Path
+
m
.
pathSuffix
v
:=
u
.
Query
()
v
.
Set
(
"state"
,
state
)
u
.
RawQuery
=
v
.
Encode
()
return
u
.
String
(),
nil
}
// HandleCallback parses the request and returns the user's identity
func
(
m
*
callback
)
HandleCallback
(
s
connector
.
Scopes
,
r
*
http
.
Request
)
(
connector
.
Identity
,
error
)
{
remoteUser
:=
r
.
Header
.
Get
(
"X-Remote-User"
)
if
remoteUser
==
""
{
return
connector
.
Identity
{},
fmt
.
Errorf
(
"required HTTP header X-Remote-User is not set"
)
}
// TODO: add support for X-Remote-Group, see
// https://kubernetes.io/docs/admin/authentication/#authenticating-proxy
return
connector
.
Identity
{
Email
:
remoteUser
,
EmailVerified
:
true
,
},
nil
}
connector/github/github.go
View file @
a41d93db
...
...
@@ -63,7 +63,7 @@ type Org struct {
}
// Open returns a strategy for logging in through GitHub.
func
(
c
*
Config
)
Open
(
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
if
c
.
Org
!=
""
{
// Return error if both 'org' and 'orgs' fields are used.
...
...
connector/gitlab/gitlab.go
View file @
a41d93db
...
...
@@ -51,7 +51,7 @@ type gitlabGroup struct {
}
// Open returns a strategy for logging in through GitLab.
func
(
c
*
Config
)
Open
(
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
if
c
.
BaseURL
==
""
{
c
.
BaseURL
=
"https://www.gitlab.com"
}
...
...
connector/ldap/ldap.go
View file @
a41d93db
...
...
@@ -153,7 +153,7 @@ func parseScope(s string) (int, bool) {
}
// Open returns an authentication strategy using LDAP.
func
(
c
*
Config
)
Open
(
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
conn
,
err
:=
c
.
OpenConnector
(
logger
)
if
err
!=
nil
{
return
nil
,
err
...
...
connector/mock/connectortest.go
View file @
a41d93db
...
...
@@ -69,7 +69,7 @@ func (m *Callback) Refresh(ctx context.Context, s connector.Scopes, identity con
type
CallbackConfig
struct
{}
// Open returns an authentication strategy which requires no user interaction.
func
(
c
*
CallbackConfig
)
Open
(
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
func
(
c
*
CallbackConfig
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
return
NewCallbackConnector
(
logger
),
nil
}
...
...
@@ -81,7 +81,7 @@ type PasswordConfig struct {
}
// Open returns an authentication strategy which prompts for a predefined username and password.
func
(
c
*
PasswordConfig
)
Open
(
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
func
(
c
*
PasswordConfig
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
if
c
.
Username
==
""
{
return
nil
,
errors
.
New
(
"no username supplied"
)
}
...
...
connector/oidc/oidc.go
View file @
a41d93db
...
...
@@ -75,7 +75,7 @@ func registerBrokenAuthHeaderProvider(url string) {
// Open returns a connector which can be used to login users through an upstream
// OpenID Connect provider.
func
(
c
*
Config
)
Open
(
logger
logrus
.
FieldLogger
)
(
conn
connector
.
Connector
,
err
error
)
{
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
conn
connector
.
Connector
,
err
error
)
{
ctx
,
cancel
:=
context
.
WithCancel
(
context
.
Background
())
provider
,
err
:=
oidc
.
NewProvider
(
ctx
,
c
.
Issuer
)
...
...
connector/oidc/oidc_test.go
View file @
a41d93db
package
oidc
import
(
"github.com/coreos/dex/connector"
"github.com/sirupsen/logrus"
"net/url"
"os"
"reflect"
"testing"
"github.com/coreos/dex/connector"
"github.com/sirupsen/logrus"
)
func
TestKnownBrokenAuthHeaderProvider
(
t
*
testing
.
T
)
{
...
...
@@ -73,7 +74,7 @@ func TestOidcConnector_LoginURL(t *testing.T) {
HostedDomains
:
test
.
hostedDomains
,
}
conn
,
err
:=
config
.
Open
(
logger
)
conn
,
err
:=
config
.
Open
(
"oidc"
,
logger
)
if
err
!=
nil
{
t
.
Errorf
(
"failed to open connector: %v"
,
err
)
continue
...
...
connector/saml/saml.go
View file @
a41d93db
...
...
@@ -125,7 +125,7 @@ func (c certStore) Certificates() (roots []*x509.Certificate, err error) {
// Open validates the config and returns a connector. It does not actually
// validate connectivity with the provider.
func
(
c
*
Config
)
Open
(
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
func
(
c
*
Config
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
return
c
.
openConnector
(
logger
)
}
...
...
server/handlers.go
View file @
a41d93db
...
...
@@ -346,6 +346,12 @@ func (s *Server) handleConnectorCallback(w http.ResponseWriter, r *http.Request)
return
}
if
connID
:=
mux
.
Vars
(
r
)[
"connector"
];
connID
!=
""
&&
connID
!=
authReq
.
ConnectorID
{
s
.
logger
.
Errorf
(
"Connector mismatch: authentication started with id %q, but callback for id %q was triggered"
,
authReq
.
ConnectorID
,
connID
)
s
.
renderError
(
w
,
http
.
StatusInternalServerError
,
"Requested resource does not exist."
)
return
}
conn
,
err
:=
s
.
getConnector
(
authReq
.
ConnectorID
)
if
err
!=
nil
{
s
.
logger
.
Errorf
(
"Failed to get connector with id %q : %v"
,
authReq
.
ConnectorID
,
err
)
...
...
server/server.go
View file @
a41d93db
...
...
@@ -19,6 +19,7 @@ import (
"github.com/sirupsen/logrus"
"github.com/coreos/dex/connector"
"github.com/coreos/dex/connector/authproxy"
"github.com/coreos/dex/connector/github"
"github.com/coreos/dex/connector/gitlab"
"github.com/coreos/dex/connector/ldap"
...
...
@@ -240,6 +241,9 @@ func newServer(ctx context.Context, c Config, rotationStrategy rotationStrategy)
handleFunc
(
"/auth"
,
s
.
handleAuthorization
)
handleFunc
(
"/auth/{connector}"
,
s
.
handleConnectorLogin
)
handleFunc
(
"/callback"
,
s
.
handleConnectorCallback
)
// For easier connector-specific web server configuration, e.g. for the
// "authproxy" connector.
handleFunc
(
"/callback/{connector}"
,
s
.
handleConnectorCallback
)
handleFunc
(
"/approval"
,
s
.
handleApproval
)
handleFunc
(
"/healthz"
,
s
.
handleHealth
)
handlePrefix
(
"/static"
,
static
)
...
...
@@ -381,7 +385,7 @@ func (s *Server) startGarbageCollection(ctx context.Context, frequency time.Dura
// ConnectorConfig is a configuration that can open a connector.
type
ConnectorConfig
interface
{
Open
(
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
Open
(
id
string
,
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
}
// ConnectorsConfig variable provides an easy way to return a config struct
...
...
@@ -394,6 +398,7 @@ var ConnectorsConfig = map[string]func() ConnectorConfig{
"gitlab"
:
func
()
ConnectorConfig
{
return
new
(
gitlab
.
Config
)
},
"oidc"
:
func
()
ConnectorConfig
{
return
new
(
oidc
.
Config
)
},
"saml"
:
func
()
ConnectorConfig
{
return
new
(
saml
.
Config
)
},
"authproxy"
:
func
()
ConnectorConfig
{
return
new
(
authproxy
.
Config
)
},
// Keep around for backwards compatibility.
"samlExperimental"
:
func
()
ConnectorConfig
{
return
new
(
saml
.
Config
)
},
}
...
...
@@ -415,7 +420,7 @@ func openConnector(logger logrus.FieldLogger, conn storage.Connector) (connector
}
}
c
,
err
:=
connConfig
.
Open
(
logger
)
c
,
err
:=
connConfig
.
Open
(
conn
.
ID
,
logger
)
if
err
!=
nil
{
return
c
,
fmt
.
Errorf
(
"failed to create connector %s: %v"
,
conn
.
ID
,
err
)
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment