From 9117f1fc72fe0b6b69a358333e0f93aa166330e5 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 10 Jan 2024 10:49:23 -0600 Subject: [PATCH 1/6] chore: allow running fake idp with coderd dev --- coderd/coderdtest/oidctest/idp.go | 34 +++++++++++-- coderd/coderdtest/oidctest/testidp/main.go | 58 ++++++++++++++++++++++ codersdk/deployment.go | 9 ++-- 3 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 coderd/coderdtest/oidctest/testidp/main.go diff --git a/coderd/coderdtest/oidctest/idp.go b/coderd/coderdtest/oidctest/idp.go index bb758d60f5d0a..a4b48c9953ff7 100644 --- a/coderd/coderdtest/oidctest/idp.go +++ b/coderd/coderdtest/oidctest/idp.go @@ -78,9 +78,12 @@ type FakeIDP struct { // "Authorized Redirect URLs". This can be used to emulate that. hookValidRedirectURL func(redirectURL string) error hookUserInfo func(email string) (jwt.MapClaims, error) - hookMutateToken func(token map[string]interface{}) - fakeCoderd func(req *http.Request) (*http.Response, error) - hookOnRefresh func(email string) error + // defaultIDClaims is if a new client connects and we didn't preset + // some claims. + defaultIDClaims jwt.MapClaims + hookMutateToken func(token map[string]interface{}) + fakeCoderd func(req *http.Request) (*http.Response, error) + hookOnRefresh func(email string) error // Custom authentication for the client. This is useful if you want // to test something like PKI auth vs a client_secret. hookAuthenticateClient func(t testing.TB, req *http.Request) (url.Values, error) @@ -162,6 +165,12 @@ func WithStaticUserInfo(info jwt.MapClaims) func(*FakeIDP) { } } +func WithDefaultIDClaims(claims jwt.MapClaims) func(*FakeIDP) { + return func(f *FakeIDP) { + f.defaultIDClaims = claims + } +} + func WithDynamicUserInfo(userInfoFunc func(email string) (jwt.MapClaims, error)) func(*FakeIDP) { return func(f *FakeIDP) { f.hookUserInfo = userInfoFunc @@ -679,7 +688,7 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler { // Always invalidate the code after it is used. f.codeToStateMap.Delete(code) - idTokenClaims, ok := f.stateToIDTokenClaims.Load(stateStr) + idTokenClaims, ok := f.getClaims(f.stateToIDTokenClaims, stateStr) if !ok { t.Errorf("missing id token claims") http.Error(rw, "missing id token claims", http.StatusBadRequest) @@ -699,7 +708,7 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler { return } - idTokenClaims, ok := f.refreshIDTokenClaims.Load(refreshToken) + idTokenClaims, ok := f.getClaims(f.refreshIDTokenClaims, refreshToken) if !ok { t.Errorf("missing id token claims in refresh") http.Error(rw, "missing id token claims in refresh", http.StatusBadRequest) @@ -971,6 +980,10 @@ func (f *FakeIDP) ExternalAuthConfig(t testing.TB, id string, custom *ExternalAu return cfg } +func (f *FakeIDP) AppCredentials() (string, string) { + return f.clientID, f.clientSecret +} + // OIDCConfig returns the OIDC config to use for Coderd. func (f *FakeIDP) OIDCConfig(t testing.TB, scopes []string, opts ...func(cfg *coderd.OIDCConfig)) *coderd.OIDCConfig { t.Helper() @@ -1023,6 +1036,17 @@ func (f *FakeIDP) OIDCConfig(t testing.TB, scopes []string, opts ...func(cfg *co return cfg } +func (f *FakeIDP) getClaims(m *syncmap.Map[string, jwt.MapClaims], key string) (jwt.MapClaims, bool) { + v, ok := m.Load(key) + if !ok { + if f.defaultIDClaims != nil { + return f.defaultIDClaims, true + } + return nil, false + } + return v, true +} + func httpErrorCode(defaultCode int, err error) int { var stautsErr statusHookError status := defaultCode diff --git a/coderd/coderdtest/oidctest/testidp/main.go b/coderd/coderdtest/oidctest/testidp/main.go new file mode 100644 index 0000000000000..3de28ebe1ff9b --- /dev/null +++ b/coderd/coderdtest/oidctest/testidp/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "flag" + "log" + "os" + "os/signal" + "testing" + + "github.com/golang-jwt/jwt/v4" + + "github.com/coder/coder/v2/coderd/coderdtest/oidctest" +) + +func main() { + testing.Init() + _ = flag.Set("test.timeout", "0") + + flag.Parse() + + // This is just a way to run tests outside go test + testing.Main(func(pat, str string) (bool, error) { + return true, nil + }, []testing.InternalTest{ + { + Name: "Run Fake IDP", + F: RunIDP(), + }, + }, nil, nil) +} + +// RunIDP needs the testing.T because our oidctest package requires the +// testing.T. +func RunIDP() func(t *testing.T) { + return func(t *testing.T) { + idp := oidctest.NewFakeIDP(t, + oidctest.WithServing(), + oidctest.WithStaticUserInfo(jwt.MapClaims{}), + oidctest.WithDefaultIDClaims(jwt.MapClaims{}), + ) + id, sec := idp.AppCredentials() + prov := idp.WellknownConfig() + + log.Println("IDP Issuer URL", idp.IssuerURL()) + log.Println("Oauth Flags") + log.Printf(`--external-auth-providers='[{"type":"fake","client_id":"%s","client_secret":"%s","auth_url":"%s","token_url":"%s","validate_url":"%s","scopes":["openid","email","profile"]}]'`, + id, sec, prov.AuthURL, prov.TokenURL, prov.UserInfoURL, + ) + + log.Println("Press Ctrl+C to exit") + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt) + select { + case <-c: + log.Println("Closing") + } + } +} diff --git a/codersdk/deployment.go b/codersdk/deployment.go index c3e2db238e4ef..e0dcc4fe4ded2 100644 --- a/codersdk/deployment.go +++ b/codersdk/deployment.go @@ -1790,11 +1790,10 @@ Write out the current server config as YAML to stdout.`, // Env handling is done in cli.ReadGitAuthFromEnvironment Name: "External Auth Providers", Description: "External Authentication providers.", - // We need extra scrutiny to ensure this works, is documented, and - // tested before enabling. - YAML: "externalAuthProviders", - Value: &c.ExternalAuthConfigs, - Hidden: true, + YAML: "externalAuthProviders", + Flag: "external-auth-providers", + Value: &c.ExternalAuthConfigs, + Hidden: true, }, { Name: "Custom wgtunnel Host", From 27d1787640bff3f2a86b33e80b9d11a9a4bc2efa Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 10 Jan 2024 11:05:49 -0600 Subject: [PATCH 2/6] wording --- coderd/coderdtest/oidctest/testidp/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coderd/coderdtest/oidctest/testidp/main.go b/coderd/coderdtest/oidctest/testidp/main.go index 3de28ebe1ff9b..205660b3d2377 100644 --- a/coderd/coderdtest/oidctest/testidp/main.go +++ b/coderd/coderdtest/oidctest/testidp/main.go @@ -42,7 +42,7 @@ func RunIDP() func(t *testing.T) { prov := idp.WellknownConfig() log.Println("IDP Issuer URL", idp.IssuerURL()) - log.Println("Oauth Flags") + log.Println("Coderd Flags") log.Printf(`--external-auth-providers='[{"type":"fake","client_id":"%s","client_secret":"%s","auth_url":"%s","token_url":"%s","validate_url":"%s","scopes":["openid","email","profile"]}]'`, id, sec, prov.AuthURL, prov.TokenURL, prov.UserInfoURL, ) From 7cd28aeae0a737f704b2a564a45ce7a00970fbbb Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 10 Jan 2024 11:27:50 -0600 Subject: [PATCH 3/6] Linter --- {coderd/coderdtest/oidctest => cmd}/testidp/main.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) rename {coderd/coderdtest/oidctest => cmd}/testidp/main.go (95%) diff --git a/coderd/coderdtest/oidctest/testidp/main.go b/cmd/testidp/main.go similarity index 95% rename from coderd/coderdtest/oidctest/testidp/main.go rename to cmd/testidp/main.go index 205660b3d2377..af85908cf5621 100644 --- a/coderd/coderdtest/oidctest/testidp/main.go +++ b/cmd/testidp/main.go @@ -50,9 +50,10 @@ func RunIDP() func(t *testing.T) { log.Println("Press Ctrl+C to exit") c := make(chan os.Signal, 1) signal.Notify(c, os.Interrupt) - select { - case <-c: - log.Println("Closing") - } + + // Block until ctl+c + <-c + log.Println("Closing") + } } From 1a19b1cbcbd2e6361e536925c735ec9843b6810c Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 10 Jan 2024 11:33:41 -0600 Subject: [PATCH 4/6] Linter --- cmd/testidp/main.go | 1 - coderd/coderdtest/oidctest/idp.go | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cmd/testidp/main.go b/cmd/testidp/main.go index af85908cf5621..fd96d0b84a87e 100644 --- a/cmd/testidp/main.go +++ b/cmd/testidp/main.go @@ -54,6 +54,5 @@ func RunIDP() func(t *testing.T) { // Block until ctl+c <-c log.Println("Closing") - } } diff --git a/coderd/coderdtest/oidctest/idp.go b/coderd/coderdtest/oidctest/idp.go index a4b48c9953ff7..6b6936e3465e7 100644 --- a/coderd/coderdtest/oidctest/idp.go +++ b/coderd/coderdtest/oidctest/idp.go @@ -980,7 +980,7 @@ func (f *FakeIDP) ExternalAuthConfig(t testing.TB, id string, custom *ExternalAu return cfg } -func (f *FakeIDP) AppCredentials() (string, string) { +func (f *FakeIDP) AppCredentials() (clientID string, clientSecret string) { return f.clientID, f.clientSecret } From f23d4e7636dc485b5f98f72807eb32832841f956 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 10 Jan 2024 14:00:58 -0600 Subject: [PATCH 5/6] add short usage doc --- cmd/testidp/README.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 cmd/testidp/README.md diff --git a/cmd/testidp/README.md b/cmd/testidp/README.md new file mode 100644 index 0000000000000..880064c803f3b --- /dev/null +++ b/cmd/testidp/README.md @@ -0,0 +1,15 @@ +# How to use + +Start the idp service: +```bash +$ go run main.go +2024-01-10 16:48:01.415 [info] stdlib: 2024/01/10 10:48:01 IDP Issuer URL http://127.0.0.1:44517 +2024-01-10 16:48:01.415 [info] stdlib: 2024/01/10 10:48:01 Oauth Flags +2024-01-10 16:48:01.415 [info] stdlib: 2024/01/10 10:48:01 --external-auth-providers='[{"type":"fake","client_id":"f2df566b-a1c9-407a-8b75-480db45c6476","client_secret":"55aca4e3-7b94-44b6-9f45-ecb5e81c560d","auth_url":"http://127.0.0.1:44517/oauth2/authorize","token_url":"http://127.0.0.1:44517/oauth2/token","validate_url":"http://127.0.0.1:44517/oauth2/userinfo","scopes":["openid","email","profile"]}]' +2024-01-10 16:48:01.415 [info] stdlib: 2024/01/10 10:48:01 Press Ctrl+C to exit +``` + +Then use the flag into your coderd instance: +```bash +develop.sh -- --external-auth-providers='[{"type":"fake","client_id":"f2df566b-a1c9-407a-8b75-480db45c6476","client_secret":"55aca4e3-7b94-44b6-9f45-ecb5e81c560d","auth_url":"http://127.0.0.1:44517/oauth2/authorize","token_url":"http://127.0.0.1:44517/oauth2/token","validate_url":"http://127.0.0.1:44517/oauth2/userinfo","scopes":["openid","email","profile"]}]' +``` From eab1a1a278c385d77a936a070d0057f6a76621e4 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Thu, 11 Jan 2024 12:00:24 -0600 Subject: [PATCH 6/6] fmt --- cmd/testidp/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/testidp/README.md b/cmd/testidp/README.md index 880064c803f3b..2dac79af8602b 100644 --- a/cmd/testidp/README.md +++ b/cmd/testidp/README.md @@ -1,6 +1,7 @@ # How to use Start the idp service: + ```bash $ go run main.go 2024-01-10 16:48:01.415 [info] stdlib: 2024/01/10 10:48:01 IDP Issuer URL http://127.0.0.1:44517 @@ -10,6 +11,7 @@ $ go run main.go ``` Then use the flag into your coderd instance: + ```bash develop.sh -- --external-auth-providers='[{"type":"fake","client_id":"f2df566b-a1c9-407a-8b75-480db45c6476","client_secret":"55aca4e3-7b94-44b6-9f45-ecb5e81c560d","auth_url":"http://127.0.0.1:44517/oauth2/authorize","token_url":"http://127.0.0.1:44517/oauth2/token","validate_url":"http://127.0.0.1:44517/oauth2/userinfo","scopes":["openid","email","profile"]}]' ``` pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy