Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dex
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
hdacloud
dex
Commits
76b9eb1d
Commit
76b9eb1d
authored
8 years ago
by
rithu john
Browse files
Options
Downloads
Patches
Plain Diff
connector/github: add support for github enterprise.
parent
943253fe
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
Documentation/github-connector.md
+33
-0
33 additions, 0 deletions
Documentation/github-connector.md
connector/github/github.go
+92
-6
92 additions, 6 deletions
connector/github/github.go
with
125 additions
and
6 deletions
Documentation/github-connector.md
+
33
−
0
View file @
76b9eb1d
...
...
@@ -31,4 +31,37 @@ connectors:
org
:
my-oranization
```
## GitHub Enterprise
Users can use their GitHub Enterprise account to login to dex. The following configuration can be used to enable a GitHub Enterprise connector on dex:
```
yaml
connectors
:
-
type
:
github
# Required field for connector id.
id
:
github
# Required field for connector name.
name
:
GitHub
config
:
# Required fields. Dex must be pre-registered with GitHub Enterprise
# to get the following values.
# Credentials can be string literals or pulled from the environment.
clientID
:
$GITHUB_CLIENT_ID
clientSecret
:
$GITHUB_CLIENT_SECRET
redirectURI
:
http://127.0.0.1:5556/dex/callback
# Optional organization to pull teams from, communicate through the
# "groups" scope.
#
# NOTE: This is an EXPERIMENTAL config option and will likely change.
org
:
my-oranization
# Required ONLY for GitHub Enterprise.
# This is the Hostname of the GitHub Enterprise account listed on the
# management console. Ensure this domain is routable on your network.
hostName
:
git.example.com
# ONLY for GitHub Enterprise. Optional field.
# Used to support self-signed or untrusted CA root certificates.
rootCA
:
/etc/dex/ca.crt
```
[
github-oauth2
]:
https://github.com/settings/applications/new
This diff is collapsed.
Click to expand it.
connector/github/github.go
+
92
−
6
View file @
76b9eb1d
...
...
@@ -3,13 +3,18 @@ package github
import
(
"context"
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net"
"net/http"
"regexp"
"strconv"
"strings"
"time"
"golang.org/x/oauth2"
"golang.org/x/oauth2/github"
...
...
@@ -19,7 +24,7 @@ import (
)
const
(
base
URL
=
"https://api.github.com"
api
URL
=
"https://api.github.com"
scopeEmail
=
"user:email"
scopeOrgs
=
"read:org"
)
...
...
@@ -30,17 +35,45 @@ type Config struct {
ClientSecret
string
`json:"clientSecret"`
RedirectURI
string
`json:"redirectURI"`
Org
string
`json:"org"`
HostName
string
`json:"hostName"`
RootCA
string
`json:"rootCA"`
}
// Open returns a strategy for logging in through GitHub.
func
(
c
*
Config
)
Open
(
logger
logrus
.
FieldLogger
)
(
connector
.
Connector
,
error
)
{
return
&
githubConnector
{
g
:=
githubConnector
{
redirectURI
:
c
.
RedirectURI
,
org
:
c
.
Org
,
clientID
:
c
.
ClientID
,
clientSecret
:
c
.
ClientSecret
,
apiURL
:
apiURL
,
logger
:
logger
,
},
nil
}
if
c
.
HostName
!=
""
{
// ensure this is a hostname and not a URL or path.
if
strings
.
Contains
(
c
.
HostName
,
"/"
)
{
return
nil
,
errors
.
New
(
"invalid hostname: hostname cannot contain `/`"
)
}
g
.
hostName
=
c
.
HostName
g
.
apiURL
=
"https://"
+
c
.
HostName
+
"/api/v3"
}
if
c
.
RootCA
!=
""
{
if
c
.
HostName
==
""
{
return
nil
,
errors
.
New
(
"invalid connector config: Host name field required for a root certificate file"
)
}
g
.
rootCA
=
c
.
RootCA
var
err
error
if
g
.
httpClient
,
err
=
newHTTPClient
(
g
.
rootCA
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create HTTP client: %v"
,
err
)
}
}
return
&
g
,
nil
}
type
connectorData
struct
{
...
...
@@ -59,6 +92,14 @@ type githubConnector struct {
clientID
string
clientSecret
string
logger
logrus
.
FieldLogger
// apiURL defaults to "https://api.github.com"
apiURL
string
// hostName of the GitHub enterprise account.
hostName
string
// Used to support untrusted/self-signed CA certs.
rootCA
string
// HTTP Client that trusts the custom delcared rootCA cert.
httpClient
*
http
.
Client
}
func
(
c
*
githubConnector
)
oauth2Config
(
scopes
connector
.
Scopes
)
*
oauth2
.
Config
{
...
...
@@ -68,10 +109,21 @@ func (c *githubConnector) oauth2Config(scopes connector.Scopes) *oauth2.Config {
}
else
{
githubScopes
=
[]
string
{
scopeEmail
}
}
endpoint
:=
github
.
Endpoint
// case when it is a GitHub Enterprise account.
if
c
.
hostName
!=
""
{
endpoint
=
oauth2
.
Endpoint
{
AuthURL
:
"https://"
+
c
.
hostName
+
"/login/oauth/authorize"
,
TokenURL
:
"https://"
+
c
.
hostName
+
"/login/oauth/access_token"
,
}
}
return
&
oauth2
.
Config
{
ClientID
:
c
.
clientID
,
ClientSecret
:
c
.
clientSecret
,
Endpoint
:
github
.
E
ndpoint
,
Endpoint
:
e
ndpoint
,
Scopes
:
githubScopes
,
}
}
...
...
@@ -80,6 +132,7 @@ func (c *githubConnector) LoginURL(scopes connector.Scopes, callbackURL, state s
if
c
.
redirectURI
!=
callbackURL
{
return
""
,
fmt
.
Errorf
(
"expected callback URL did not match the URL in the config"
)
}
return
c
.
oauth2Config
(
scopes
)
.
AuthCodeURL
(
state
),
nil
}
...
...
@@ -95,6 +148,34 @@ func (e *oauth2Error) Error() string {
return
e
.
error
+
": "
+
e
.
errorDescription
}
// newHTTPClient returns a new HTTP client that trusts the custom delcared rootCA cert.
func
newHTTPClient
(
rootCA
string
)
(
*
http
.
Client
,
error
)
{
tlsConfig
:=
tls
.
Config
{
RootCAs
:
x509
.
NewCertPool
()}
rootCABytes
,
err
:=
ioutil
.
ReadFile
(
rootCA
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to read root-ca: %v"
,
err
)
}
if
!
tlsConfig
.
RootCAs
.
AppendCertsFromPEM
(
rootCABytes
)
{
return
nil
,
fmt
.
Errorf
(
"no certs found in root CA file %q"
,
rootCA
)
}
return
&
http
.
Client
{
Transport
:
&
http
.
Transport
{
TLSClientConfig
:
&
tlsConfig
,
Proxy
:
http
.
ProxyFromEnvironment
,
DialContext
:
(
&
net
.
Dialer
{
Timeout
:
30
*
time
.
Second
,
KeepAlive
:
30
*
time
.
Second
,
DualStack
:
true
,
})
.
DialContext
,
MaxIdleConns
:
100
,
IdleConnTimeout
:
90
*
time
.
Second
,
TLSHandshakeTimeout
:
10
*
time
.
Second
,
ExpectContinueTimeout
:
1
*
time
.
Second
,
},
},
nil
}
func
(
c
*
githubConnector
)
HandleCallback
(
s
connector
.
Scopes
,
r
*
http
.
Request
)
(
identity
connector
.
Identity
,
err
error
)
{
q
:=
r
.
URL
.
Query
()
if
errType
:=
q
.
Get
(
"error"
);
errType
!=
""
{
...
...
@@ -102,7 +183,12 @@ func (c *githubConnector) HandleCallback(s connector.Scopes, r *http.Request) (i
}
oauth2Config
:=
c
.
oauth2Config
(
s
)
ctx
:=
r
.
Context
()
// GitHub Enterprise account
if
c
.
httpClient
!=
nil
{
ctx
=
context
.
WithValue
(
r
.
Context
(),
oauth2
.
HTTPClient
,
c
.
httpClient
)
}
token
,
err
:=
oauth2Config
.
Exchange
(
ctx
,
q
.
Get
(
"code"
))
if
err
!=
nil
{
...
...
@@ -192,7 +278,7 @@ type user struct {
// a bearer token as part of the request.
func
(
c
*
githubConnector
)
user
(
ctx
context
.
Context
,
client
*
http
.
Client
)
(
user
,
error
)
{
var
u
user
req
,
err
:=
http
.
NewRequest
(
"GET"
,
base
URL
+
"/user"
,
nil
)
req
,
err
:=
http
.
NewRequest
(
"GET"
,
c
.
api
URL
+
"/user"
,
nil
)
if
err
!=
nil
{
return
u
,
fmt
.
Errorf
(
"github: new req: %v"
,
err
)
}
...
...
@@ -228,7 +314,7 @@ func (c *githubConnector) teams(ctx context.Context, client *http.Client, org st
// https://developer.github.com/v3/#pagination
reNext
:=
regexp
.
MustCompile
(
"<(.*)>; rel=
\"
next
\"
"
)
reLast
:=
regexp
.
MustCompile
(
"<(.*)>; rel=
\"
last
\"
"
)
apiURL
:=
base
URL
+
"/user/teams"
apiURL
:=
c
.
api
URL
+
"/user/teams"
for
{
req
,
err
:=
http
.
NewRequest
(
"GET"
,
apiURL
,
nil
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment