Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redis: Unify config #365

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions auth_server/authn/data/oidc_auth.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
<body>
<div id="panel">
<p>
<a id="login-with-oidc" href="{{.AuthEndpoint}}?response_type=code&scope={{.Scope}}&client_id={{.ClientId}}&redirect_uri={{.RedirectURI}}">
<a id="login-with-oidc" href="{{.AuthEndpoint}}?response_type=code&scope={{.Scope}}&client_id={{.ClientId}}{{.AuthParameter}}&redirect_uri={{.RedirectURI}}">
Login with OIDC Provider
</a>
</p>
</div>
</body>
</html>
</html>
40 changes: 16 additions & 24 deletions auth_server/authn/github_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ import (
"errors"
"fmt"
"html/template"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
"time"

"github.com/cesanta/glog"
"github.com/go-redis/redis"

"github.com/cesanta/docker_auth/auth_server/api"
)
Expand Down Expand Up @@ -57,30 +56,25 @@ type ParentGitHubTeam struct {
}

type GitHubAuthConfig struct {
Organization string `yaml:"organization,omitempty"`
ClientId string `yaml:"client_id,omitempty"`
ClientSecret string `yaml:"client_secret,omitempty"`
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
TokenDB string `yaml:"token_db,omitempty"`
GCSTokenDB *GitHubGCSStoreConfig `yaml:"gcs_token_db,omitempty"`
RedisTokenDB *GitHubRedisStoreConfig `yaml:"redis_token_db,omitempty"`
HTTPTimeout time.Duration `yaml:"http_timeout,omitempty"`
RevalidateAfter time.Duration `yaml:"revalidate_after,omitempty"`
GithubWebUri string `yaml:"github_web_uri,omitempty"`
GithubApiUri string `yaml:"github_api_uri,omitempty"`
RegistryUrl string `yaml:"registry_url,omitempty"`
Organization string `yaml:"organization,omitempty"`
ClientId string `yaml:"client_id,omitempty"`
ClientSecret string `yaml:"client_secret,omitempty"`
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
TokenDB string `yaml:"token_db,omitempty"`
GCSTokenDB *GitHubGCSStoreConfig `yaml:"gcs_token_db,omitempty"`
RedisTokenDB *RedisStoreConfig `yaml:"redis_token_db,omitempty"`
HTTPTimeout time.Duration `yaml:"http_timeout,omitempty"`
RevalidateAfter time.Duration `yaml:"revalidate_after,omitempty"`
GithubWebUri string `yaml:"github_web_uri,omitempty"`
GithubApiUri string `yaml:"github_api_uri,omitempty"`
RegistryUrl string `yaml:"registry_url,omitempty"`
}

type GitHubGCSStoreConfig struct {
Bucket string `yaml:"bucket,omitempty"`
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
}

type GitHubRedisStoreConfig struct {
ClientOptions *redis.Options `yaml:"redis_options,omitempty"`
ClusterOptions *redis.ClusterOptions `yaml:"redis_cluster_options,omitempty"`
}

type GitHubAuthRequest struct {
Action string `json:"action,omitempty"`
Code string `json:"code,omitempty"`
Expand Down Expand Up @@ -128,7 +122,6 @@ func execGHExperimentalApiRequest(url string, token string) (*http.Response, err
}

// removeSubstringsFromString removes all occurences of stringsToStrip from sourceStr
//
func removeSubstringsFromString(sourceStr string, stringsToStrip []string) string {
theNewString := sourceStr
for _, i := range stringsToStrip {
Expand All @@ -140,7 +133,6 @@ func removeSubstringsFromString(sourceStr string, stringsToStrip []string) strin
// parseLinkHeader parses the HTTP headers from the Github API response
//
// https://developer.github.com/v3/guides/traversing-with-pagination/
//
func parseLinkHeader(linkLines []string) (linkHeader, error) {
var lH linkHeader
// URL in link is enclosed in < >
Expand Down Expand Up @@ -265,7 +257,7 @@ func (gha *GitHubAuth) doGitHubAuthCreateToken(rw http.ResponseWriter, code stri
http.Error(rw, fmt.Sprintf("Error talking to GitHub auth backend: %s", err), http.StatusServiceUnavailable)
return
}
codeResp, _ := ioutil.ReadAll(resp.Body)
codeResp, _ := io.ReadAll(resp.Body)
resp.Body.Close()
glog.V(2).Infof("Code to token resp: %s", strings.Replace(string(codeResp), "\n", " ", -1))

Expand Down Expand Up @@ -327,7 +319,7 @@ func (gha *GitHubAuth) validateAccessToken(token string) (user string, err error
err = fmt.Errorf("could not verify token %s: %s", token, err)
return
}
body, _ := ioutil.ReadAll(resp.Body)
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()

var ti GitHubTokenUser
Expand Down Expand Up @@ -396,7 +388,7 @@ func (gha *GitHubAuth) fetchTeams(token string) ([]string, error) {
}

respHeaders := resp.Header
body, _ := ioutil.ReadAll(resp.Body)
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()

err = json.Unmarshal(body, &pagedTeams)
Expand Down
47 changes: 19 additions & 28 deletions auth_server/authn/gitlab_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ import (
"errors"
"fmt"
"html/template"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
"time"

"github.com/cesanta/glog"
"github.com/go-redis/redis"

"github.com/cesanta/docker_auth/auth_server/api"
)
Expand Down Expand Up @@ -57,20 +56,20 @@ type ParentGitlabTeam struct {
}

type GitlabAuthConfig struct {
Organization string `yaml:"organization,omitempty"`
ClientId string `yaml:"client_id,omitempty"`
ClientSecret string `yaml:"client_secret,omitempty"`
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
TokenDB string `yaml:"token_db,omitempty"`
GCSTokenDB *GitlabGCSStoreConfig `yaml:"gcs_token_db,omitempty"`
RedisTokenDB *GitlabRedisStoreConfig `yaml:"redis_token_db,omitempty"`
HTTPTimeout time.Duration `yaml:"http_timeout,omitempty"`
RevalidateAfter time.Duration `yaml:"revalidate_after,omitempty"`
GitlabWebUri string `yaml:"gitlab_web_uri,omitempty"`
GitlabApiUri string `yaml:"gitlab_api_uri,omitempty"`
RegistryUrl string `yaml:"registry_url,omitempty"`
GrantType string `yaml:"grant_type,omitempty"`
RedirectUri string `yaml:"redirect_uri,omitempty"`
Organization string `yaml:"organization,omitempty"`
ClientId string `yaml:"client_id,omitempty"`
ClientSecret string `yaml:"client_secret,omitempty"`
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
TokenDB string `yaml:"token_db,omitempty"`
GCSTokenDB *GitlabGCSStoreConfig `yaml:"gcs_token_db,omitempty"`
RedisTokenDB *RedisStoreConfig `yaml:"redis_token_db,omitempty"`
HTTPTimeout time.Duration `yaml:"http_timeout,omitempty"`
RevalidateAfter time.Duration `yaml:"revalidate_after,omitempty"`
GitlabWebUri string `yaml:"gitlab_web_uri,omitempty"`
GitlabApiUri string `yaml:"gitlab_api_uri,omitempty"`
RegistryUrl string `yaml:"registry_url,omitempty"`
GrantType string `yaml:"grant_type,omitempty"`
RedirectUri string `yaml:"redirect_uri,omitempty"`
}

type CodeToGitlabTokenResponse struct {
Expand All @@ -90,11 +89,6 @@ type GitlabGCSStoreConfig struct {
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
}

type GitlabRedisStoreConfig struct {
ClientOptions *redis.Options `yaml:"redis_options,omitempty"`
ClusterOptions *redis.ClusterOptions `yaml:"redis_cluster_options,omitempty"`
}

type GitlabAuthRequest struct {
Action string `json:"action,omitempty"`
Code string `json:"code,omitempty"`
Expand All @@ -114,7 +108,6 @@ type GitlabAuth struct {
tmplResult *template.Template
}


func NewGitlabAuth(c *GitlabAuthConfig) (*GitlabAuth, error) {
var db TokenDB
var err error
Expand All @@ -125,7 +118,7 @@ func NewGitlabAuth(c *GitlabAuthConfig) (*GitlabAuth, error) {
db, err = NewGCSTokenDB(c.GCSTokenDB.Bucket, c.GCSTokenDB.ClientSecretFile)
dbName = "GCS: " + c.GCSTokenDB.Bucket
case c.RedisTokenDB != nil:
db, err = NewRedisGitlabTokenDB(c.RedisTokenDB)
db, err = NewRedisTokenDB(c.RedisTokenDB)
dbName = db.(*redisTokenDB).String()
default:
db, err = NewTokenDB(c.TokenDB)
Expand Down Expand Up @@ -215,7 +208,7 @@ func (glab *GitlabAuth) doGitlabAuthCreateToken(rw http.ResponseWriter, code str
http.Error(rw, fmt.Sprintf("Error talking to GitLab auth backend: %s", err), http.StatusServiceUnavailable)
return
}
codeResp, _ := ioutil.ReadAll(resp.Body)
codeResp, _ := io.ReadAll(resp.Body)
resp.Body.Close()
glog.V(2).Infof("Code to token resp: %s", strings.Replace(string(codeResp), "\n", " ", -1))

Expand All @@ -240,7 +233,6 @@ func (glab *GitlabAuth) doGitlabAuthCreateToken(rw http.ResponseWriter, code str

glog.Infof("New GitLab auth token for %s", user)


v := &TokenDBValue{
TokenType: c2t.TokenType,
AccessToken: c2t.AccessToken,
Expand All @@ -257,7 +249,7 @@ func (glab *GitlabAuth) doGitlabAuthCreateToken(rw http.ResponseWriter, code str

func (glab *GitlabAuth) validateGitlabAccessToken(token string) (user string, err error) {
glog.Infof("Gitlab API: Fetching user info")
req, err := http.NewRequest("GET", fmt.Sprintf("%s/user", glab.getGitlabApiUri()),nil)
req, err := http.NewRequest("GET", fmt.Sprintf("%s/user", glab.getGitlabApiUri()), nil)

if err != nil {
err = fmt.Errorf("could not create request to get information for token %s: %s", token, err)
Expand All @@ -271,7 +263,7 @@ func (glab *GitlabAuth) validateGitlabAccessToken(token string) (user string, er
err = fmt.Errorf("could not verify token %s: %s", token, err)
return
}
body, _ := ioutil.ReadAll(resp.Body)
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()
var ti GitlabTokenUser
err = json.Unmarshal(body, &ti)
Expand Down Expand Up @@ -312,7 +304,6 @@ func (glab *GitlabAuth) checkGitlabOrganization(token, user string) (err error)
return fmt.Errorf("Unknown status for membership of organization %s: %s", glab.config.Organization, resp.Status)
}


func (glab *GitlabAuth) validateGitlabServerToken(user string) (*TokenDBValue, error) {
v, err := glab.db.GetValue(user)
if err != nil || v == nil {
Expand Down
12 changes: 6 additions & 6 deletions auth_server/authn/google_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"errors"
"fmt"
"html/template"
"io/ioutil"
"io"
"net/http"
"net/url"
"strings"
Expand Down Expand Up @@ -146,7 +146,7 @@ func (ga *GoogleAuth) DoGoogleAuth(rw http.ResponseWriter, req *http.Request) {
ga.doGoogleAuthPage(rw, req)
return
}
gauthRequest, _ := ioutil.ReadAll(req.Body)
gauthRequest, _ := io.ReadAll(req.Body)
glog.V(2).Infof("gauth request: %s", string(gauthRequest))
var gar GoogleAuthRequest
err := json.Unmarshal(gauthRequest, &gar)
Expand Down Expand Up @@ -187,7 +187,7 @@ func (ga *GoogleAuth) doGoogleAuthCreateToken(rw http.ResponseWriter, code strin
http.Error(rw, fmt.Sprintf("Error talking to Google auth backend: %s", err), http.StatusServiceUnavailable)
return
}
codeResp, _ := ioutil.ReadAll(resp.Body)
codeResp, _ := io.ReadAll(resp.Body)
resp.Body.Close()
glog.V(2).Infof("Code to token resp: %s", strings.Replace(string(codeResp), "\n", " ", -1))

Expand Down Expand Up @@ -246,7 +246,7 @@ func (ga *GoogleAuth) getIDTokenInfo(token string) (*GoogleTokenInfo, error) {
if err != nil {
return nil, fmt.Errorf("could not verify token %s: %s", token, err)
}
body, _ := ioutil.ReadAll(resp.Body)
body, _ := io.ReadAll(resp.Body)
resp.Body.Close()

var ti GoogleTokenInfo
Expand Down Expand Up @@ -301,7 +301,7 @@ func (ga *GoogleAuth) refreshAccessToken(refreshToken string) (rtr RefreshTokenR
err = fmt.Errorf("Error talking to Google auth backend: %s", err)
return
}
respStr, _ := ioutil.ReadAll(resp.Body)
respStr, _ := io.ReadAll(resp.Body)
glog.V(2).Infof("Refresh token resp: %s", strings.Replace(string(respStr), "\n", " ", -1))

err = json.Unmarshal(respStr, &rtr)
Expand All @@ -318,7 +318,7 @@ func (ga *GoogleAuth) validateAccessToken(toktype, token string) (user string, e
if err != nil {
return
}
respStr, _ := ioutil.ReadAll(resp.Body)
respStr, _ := io.ReadAll(resp.Body)
glog.V(2).Infof("Access token validation rrsponse: %s", strings.Replace(string(respStr), "\n", " ", -1))
var pr ProfileResponse
err = json.Unmarshal(respStr, &pr)
Expand Down
48 changes: 36 additions & 12 deletions auth_server/authn/oidc_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"errors"
"fmt"
"html/template"
"io/ioutil"
"io"
"net/http"
"strings"
"time"
Expand All @@ -48,7 +48,9 @@ type OIDCAuthConfig struct {
ClientSecret string `yaml:"client_secret,omitempty"`
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
// path where the tokendb should be stored within the container
TokenDB string `yaml:"token_db,omitempty"`
TokenDB string `yaml:"token_db,omitempty"`
RedisTokenDB *RedisStoreConfig `yaml:"redis_token_db,omitempty"`
GCSTokenDB *OidcGCSStoreConfig `yaml:"gcs_token_db,omitempty"`
// --- optional ---
HTTPTimeout int `yaml:"http_timeout,omitempty"`
// the URL of the docker registry. Used to generate a full docker login command after authentication
Expand All @@ -61,6 +63,13 @@ type OIDCAuthConfig struct {
LabelsClaims []string `yaml:"labels_claims,omitempty"`
// --- optional ---
Scopes []string `yaml:"scopes,omitempty"`
// --- optional --- // if google add &access_type=offline&prompt=consent
AuthParameter string `yaml:"auth_parameter,omitempty"`
}

type OidcGCSStoreConfig struct {
Bucket string `yaml:"bucket,omitempty"`
ClientSecretFile string `yaml:"client_secret_file,omitempty"`
}

// OIDCRefreshTokenResponse is sent by OIDC provider in response to the grant_type=refresh_token request.
Expand Down Expand Up @@ -92,11 +101,26 @@ type OIDCAuth struct {
Creates everything necessary for OIDC auth.
*/
func NewOIDCAuth(c *OIDCAuthConfig) (*OIDCAuth, error) {
db, err := NewTokenDB(c.TokenDB)

var db TokenDB
var err error
dbName := c.TokenDB

switch {
case c.GCSTokenDB != nil:
db, err = NewGCSTokenDB(c.GCSTokenDB.Bucket, c.GCSTokenDB.ClientSecretFile)
dbName = "GCS: " + c.GCSTokenDB.Bucket
case c.RedisTokenDB != nil:
db, err = NewRedisTokenDB(c.RedisTokenDB)
dbName = db.(*redisTokenDB).String()
default:
db, err = NewTokenDB(c.TokenDB)
}

if err != nil {
return nil, err
}
glog.Infof("OIDC auth token DB at %s", c.TokenDB)
glog.Infof("OIDC auth token DB at %s", dbName)
ctx := context.Background()
oidcAuth, _ := static.ReadFile("data/oidc_auth.tmpl")
oidcAuthResult, _ := static.ReadFile("data/oidc_auth_result.tmpl")
Expand Down Expand Up @@ -145,12 +169,13 @@ Executes tmpl for the OIDC login page.
*/
func (ga *OIDCAuth) doOIDCAuthPage(rw http.ResponseWriter) {
if err := ga.tmpl.Execute(rw, struct {
AuthEndpoint, RedirectURI, ClientId, Scope string
AuthEndpoint, RedirectURI, ClientId, Scope, AuthParameter string
}{
AuthEndpoint: ga.provider.Endpoint().AuthURL,
RedirectURI: ga.oauth.RedirectURL,
ClientId: ga.oauth.ClientID,
Scope: strings.Join(ga.config.Scopes, " "),
AuthEndpoint: ga.provider.Endpoint().AuthURL,
RedirectURI: ga.oauth.RedirectURL,
ClientId: ga.oauth.ClientID,
Scope: strings.Join(ga.config.Scopes, " "),
AuthParameter: ga.config.AuthParameter,
}); err != nil {
http.Error(rw, fmt.Sprintf("Template error: %s", err), http.StatusInternalServerError)
}
Expand Down Expand Up @@ -203,8 +228,7 @@ func (ga *OIDCAuth) doOIDCAuthCreateToken(rw http.ResponseWriter, code string) {
http.Error(rw, fmt.Sprintf("No %q claim in ID token", ga.config.UserClaim), http.StatusInternalServerError)
return
}

glog.V(2).Infof("New OIDC auth token for %s (Current time: %s, expiration time: %s)", username, time.Now().String(), tok.Expiry.String())
glog.V(2).Infof("New OIDC auth token for %s (Current time: %s, expiration time: %s) - refreshtoken: %s", username, time.Now().String(), tok.Expiry.String(), tok.RefreshToken)

dbVal := &TokenDBValue{
TokenType: tok.TokenType,
Expand Down Expand Up @@ -257,7 +281,7 @@ func (ga *OIDCAuth) refreshAccessToken(refreshToken string) (rtr OIDCRefreshToke
err = fmt.Errorf("error talking to OIDC auth backend: %s", err)
return
}
respStr, _ := ioutil.ReadAll(resp.Body)
respStr, _ := io.ReadAll(resp.Body)
glog.V(2).Infof("Refresh token resp: %s", strings.Replace(string(respStr), "\n", " ", -1))

err = json.Unmarshal(respStr, &rtr)
Expand Down
Loading