From 26651a2c1ab1d40863d0c52fbf0f10550e9713f1 Mon Sep 17 00:00:00 2001 From: Mark Wolfe Date: Sun, 15 Oct 2017 23:02:01 +1100 Subject: [PATCH] refactor(Providers) Move providers into their own tree. --- .travis.yml | 4 +- Makefile | 4 +- cmd/saml2aws/commands/exec.go | 2 +- cmd/saml2aws/commands/login.go | 5 +- cmd/saml2aws/commands/login_test.go | 5 +- helper/credentials/saml.go | 4 +- input.go | 25 +-------- input_test.go | 4 +- pkg/creds/creds.go | 24 +++++++++ pkg/creds/creds_test.go | 52 +++++++++++++++++++ adfs.go => pkg/provider/adfs/adfs.go | 15 +++--- adfs2.go => pkg/provider/adfs2/adfs2.go | 14 +++-- .../provider/jumpcloud/jumpcloud.go | 15 +++--- .../provider/keycloak/keycloak.go | 15 +++--- okta.go => pkg/provider/okta/okta.go | 13 ++--- pingfed.go => pkg/provider/pingfed/pingfed.go | 15 +++--- {shell => pkg/shell}/env.go | 0 {shell => pkg/shell}/env_test.go | 0 {shell => pkg/shell}/shell.go | 0 {shell => pkg/shell}/shell_test.go | 0 {shell => pkg/shell}/shell_windows.go | 0 saml2aws.go | 26 +++++++--- 22 files changed, 160 insertions(+), 82 deletions(-) create mode 100644 pkg/creds/creds.go create mode 100644 pkg/creds/creds_test.go rename adfs.go => pkg/provider/adfs/adfs.go (90%) rename adfs2.go => pkg/provider/adfs2/adfs2.go (83%) rename jumpcloud.go => pkg/provider/jumpcloud/jumpcloud.go (92%) rename keycloak.go => pkg/provider/keycloak/keycloak.go (91%) rename okta.go => pkg/provider/okta/okta.go (97%) rename pingfed.go => pkg/provider/pingfed/pingfed.go (94%) rename {shell => pkg/shell}/env.go (100%) rename {shell => pkg/shell}/env_test.go (100%) rename {shell => pkg/shell}/shell.go (100%) rename {shell => pkg/shell}/shell_test.go (100%) rename {shell => pkg/shell}/shell_windows.go (100%) diff --git a/.travis.yml b/.travis.yml index 3c8a13ac7..a4e5b0421 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ language: go go: - - 1.8 + - 1.9 # - tip -go_import_path: github.com/versent/unicreds +go_import_path: github.com/versent/saml2aws install: - echo noop diff --git a/Makefile b/Makefile index 4aeb822ef..24c7c8c0e 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ compile: deps -osarch="windows/amd64" \ -osarch="windows/i386" \ -output "build/{{.Dir}}_$(VERSION)_{{.OS}}_{{.Arch}}/$(NAME)" \ - $(shell glide novendor) + $(shell ./glide novendor) install: go install ./cmd/saml2aws @@ -52,7 +52,7 @@ release: @github-release "v$(VERSION)" dist/* --commit "$(git rev-parse HEAD)" --github-repository versent/$(NAME) test: deps - go test -cover -v $(shell glide novendor) + go test -cover -v $(shell ./glide novendor) clean: rm ./glide diff --git a/cmd/saml2aws/commands/exec.go b/cmd/saml2aws/commands/exec.go index b61a1b039..82df5fd29 100644 --- a/cmd/saml2aws/commands/exec.go +++ b/cmd/saml2aws/commands/exec.go @@ -10,7 +10,7 @@ import ( "github.com/aws/aws-sdk-go/service/sts" "github.com/pkg/errors" "github.com/versent/saml2aws" - "github.com/versent/saml2aws/shell" + "github.com/versent/saml2aws/pkg/shell" ) // Exec execute the supplied command after seeding the environment diff --git a/cmd/saml2aws/commands/login.go b/cmd/saml2aws/commands/login.go index 978f8b4fd..8899fe706 100644 --- a/cmd/saml2aws/commands/login.go +++ b/cmd/saml2aws/commands/login.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" "github.com/versent/saml2aws" "github.com/versent/saml2aws/helper/credentials" + "github.com/versent/saml2aws/pkg/creds" ) // LoginFlags login specific command flags @@ -47,7 +48,7 @@ func Login(loginFlags *LoginFlags) error { // fmt.Println("LookupCredentials", hostname) - loginDetails := &saml2aws.LoginDetails{ + loginDetails := &creds.LoginDetails{ Hostname: hostname, Username: username, } @@ -160,7 +161,7 @@ func Login(loginFlags *LoginFlags) error { return nil } -func resolveLoginDetails(loginDetails *saml2aws.LoginDetails, loginFlags *LoginFlags) error { +func resolveLoginDetails(loginDetails *creds.LoginDetails, loginFlags *LoginFlags) error { // fmt.Printf("loginFlags %+v\n", loginFlags) diff --git a/cmd/saml2aws/commands/login_test.go b/cmd/saml2aws/commands/login_test.go index 7edf4f3a2..72cb30e05 100644 --- a/cmd/saml2aws/commands/login_test.go +++ b/cmd/saml2aws/commands/login_test.go @@ -5,18 +5,19 @@ import ( "github.com/stretchr/testify/assert" "github.com/versent/saml2aws" + "github.com/versent/saml2aws/pkg/creds" ) func TestResolveLoginDetailsWithFlags(t *testing.T) { loginFlags := &LoginFlags{Hostname: "id.example.com", Username: "wolfeidau", Password: "testtestlol", SkipPrompt: true} - loginDetails := &saml2aws.LoginDetails{Hostname: "id.example.com", Username: ""} + loginDetails := &creds.LoginDetails{Hostname: "id.example.com", Username: ""} err := resolveLoginDetails(loginDetails, loginFlags) assert.Empty(t, err) - assert.Equal(t, loginDetails, &saml2aws.LoginDetails{Username: "wolfeidau", Password: "testtestlol", Hostname: "id.example.com"}) + assert.Equal(t, loginDetails, &creds.LoginDetails{Username: "wolfeidau", Password: "testtestlol", Hostname: "id.example.com"}) } func TestResolveRoleSingleEntry(t *testing.T) { diff --git a/helper/credentials/saml.go b/helper/credentials/saml.go index 10bb53e22..4d802adef 100644 --- a/helper/credentials/saml.go +++ b/helper/credentials/saml.go @@ -3,11 +3,11 @@ package credentials import ( "fmt" - "github.com/versent/saml2aws" + "github.com/versent/saml2aws/pkg/creds" ) // LookupCredentials lookup an existing set of credentials and validate it. -func LookupCredentials(loginDetails *saml2aws.LoginDetails) error { +func LookupCredentials(loginDetails *creds.LoginDetails) error { username, password, err := CurrentHelper.Get(fmt.Sprintf("https://%s", loginDetails.Hostname)) if err != nil { diff --git a/input.go b/input.go index 8d392e638..c29a4aa50 100644 --- a/input.go +++ b/input.go @@ -7,33 +7,12 @@ import ( "strconv" "strings" - "github.com/pkg/errors" "github.com/segmentio/go-prompt" + "github.com/versent/saml2aws/pkg/creds" ) -// LoginDetails used to authenticate to ADFS -type LoginDetails struct { - Username string - Password string - Hostname string -} - -// Validate validate the login details -func (ld *LoginDetails) Validate() error { - if ld.Hostname == "" { - return errors.New("Missing hostname") - } - if ld.Username == "" { - return errors.New("Missing username") - } - if ld.Password == "" { - return errors.New("Missing password") - } - return nil -} - // PromptForLoginDetails prompt the user to present their username, password and hostname -func PromptForLoginDetails(loginDetails *LoginDetails) error { +func PromptForLoginDetails(loginDetails *creds.LoginDetails) error { loginDetails.Hostname = promptFor("Hostname [%s]", loginDetails.Hostname) diff --git a/input_test.go b/input_test.go index ee8283d1f..50a03628b 100644 --- a/input_test.go +++ b/input_test.go @@ -2,6 +2,8 @@ package saml2aws import ( "testing" + + "github.com/versent/saml2aws/pkg/creds" ) func TestLoginDetails_Validate(t *testing.T) { @@ -23,7 +25,7 @@ func TestLoginDetails_Validate(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ld := &LoginDetails{ + ld := &creds.LoginDetails{ Username: tt.fields.Username, Password: tt.fields.Password, Hostname: tt.fields.Hostname, diff --git a/pkg/creds/creds.go b/pkg/creds/creds.go new file mode 100644 index 000000000..08519c33a --- /dev/null +++ b/pkg/creds/creds.go @@ -0,0 +1,24 @@ +package creds + +import "errors" + +// LoginDetails used to authenticate +type LoginDetails struct { + Username string + Password string + Hostname string +} + +// Validate validate the login details +func (ld *LoginDetails) Validate() error { + if ld.Hostname == "" { + return errors.New("Empty hostname") + } + if ld.Username == "" { + return errors.New("Empty username") + } + if ld.Password == "" { + return errors.New("Empty password") + } + return nil +} diff --git a/pkg/creds/creds_test.go b/pkg/creds/creds_test.go new file mode 100644 index 000000000..7b053e24b --- /dev/null +++ b/pkg/creds/creds_test.go @@ -0,0 +1,52 @@ +package creds + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestValidateEmptyLoginDetails(t *testing.T) { + + ld := &LoginDetails{} + + err := ld.Validate() + + require.Error(t, err) +} +func TestValidateEmptyHostnameLoginDetails(t *testing.T) { + + ld := &LoginDetails{Username: "test", Password: "test"} + + err := ld.Validate() + + require.Error(t, err) + +} + +func TestValidateEmptyUsernameLoginDetails(t *testing.T) { + + ld := &LoginDetails{Hostname: "test", Password: "test"} + + err := ld.Validate() + + require.Error(t, err) + +} +func TestValidateEmptyPasswordLoginDetails(t *testing.T) { + + ld := &LoginDetails{Hostname: "test", Username: "test"} + + err := ld.Validate() + + require.Error(t, err) +} + +func TestValidateLoginDetails(t *testing.T) { + + ld := &LoginDetails{Hostname: "test", Username: "test", Password: "test"} + + err := ld.Validate() + + require.Nil(t, err) +} diff --git a/adfs.go b/pkg/provider/adfs/adfs.go similarity index 90% rename from adfs.go rename to pkg/provider/adfs/adfs.go index be49755c7..7dbbdac1d 100644 --- a/adfs.go +++ b/pkg/provider/adfs/adfs.go @@ -1,4 +1,4 @@ -package saml2aws +package adfs import ( "bytes" @@ -13,17 +13,18 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/pkg/errors" + "github.com/versent/saml2aws/pkg/creds" "golang.org/x/net/publicsuffix" ) -// ADFSClient wrapper around ADFS enabling authentication and retrieval of assertions -type ADFSClient struct { +// Client wrapper around ADFS enabling authentication and retrieval of assertions +type Client struct { client *http.Client } // NewADFSClient create a new ADFS client -func NewADFSClient(skipVerify bool) (*ADFSClient, error) { +func NewADFSClient(skipVerify bool) (*Client, error) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify, Renegotiation: tls.RenegotiateFreelyAsClient}, @@ -40,13 +41,13 @@ func NewADFSClient(skipVerify bool) (*ADFSClient, error) { client := &http.Client{Transport: tr, Jar: jar} - return &ADFSClient{ + return &Client{ client: client, }, nil } // Authenticate authenticate to ADFS and return the data from the body of the SAML assertion. -func (ac *ADFSClient) Authenticate(loginDetails *LoginDetails) (string, error) { +func (ac *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) { var authSubmitURL string var samlAssertion string authForm := url.Values{} @@ -122,7 +123,7 @@ func (ac *ADFSClient) Authenticate(loginDetails *LoginDetails) (string, error) { return samlAssertion, nil } -func updateFormData(authForm url.Values, s *goquery.Selection, user *LoginDetails) { +func updateFormData(authForm url.Values, s *goquery.Selection, user *creds.LoginDetails) { name, ok := s.Attr("name") // log.Printf("name = %s ok = %v", name, ok) if !ok { diff --git a/adfs2.go b/pkg/provider/adfs2/adfs2.go similarity index 83% rename from adfs2.go rename to pkg/provider/adfs2/adfs2.go index 0b316624f..764043fdc 100644 --- a/adfs2.go +++ b/pkg/provider/adfs2/adfs2.go @@ -1,4 +1,4 @@ -package saml2aws +package adfs2 import ( "bytes" @@ -14,14 +14,17 @@ import ( "github.com/Azure/go-ntlmssp" "github.com/PuerkitoBio/goquery" "github.com/pkg/errors" + "github.com/versent/saml2aws/pkg/creds" ) -type ADFS2Client struct { +// Client client for adfs2 +type Client struct { transport http.RoundTripper jar http.CookieJar } -func NewADFS2Client(skipVerify bool) (*ADFS2Client, error) { +// NewADFS2Client new adfs2 client with ntlmssp configured +func NewADFS2Client(skipVerify bool) (*Client, error) { transport := &ntlmssp.Negotiator{ RoundTripper: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify, Renegotiation: tls.RenegotiateFreelyAsClient}, @@ -35,13 +38,14 @@ func NewADFS2Client(skipVerify bool) (*ADFS2Client, error) { return nil, err } - return &ADFS2Client{ + return &Client{ transport: transport, jar: jar, }, nil } -func (ac *ADFS2Client) Authenticate(loginDetails *LoginDetails) (string, error) { +// Authenticate authenticate the user using the supplied login details +func (ac *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) { var samlAssertion string client := http.Client{ Transport: ac.transport, diff --git a/jumpcloud.go b/pkg/provider/jumpcloud/jumpcloud.go similarity index 92% rename from jumpcloud.go rename to pkg/provider/jumpcloud/jumpcloud.go index dd7646cd4..f307acebe 100644 --- a/jumpcloud.go +++ b/pkg/provider/jumpcloud/jumpcloud.go @@ -1,4 +1,4 @@ -package saml2aws +package jumpcloud import ( "bytes" @@ -14,17 +14,18 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/pkg/errors" "github.com/segmentio/go-prompt" + "github.com/versent/saml2aws/pkg/creds" "golang.org/x/net/publicsuffix" ) -// JumpCloudClient is a wrapper representing a JumpCloud SAML client -type JumpCloudClient struct { +// Client is a wrapper representing a JumpCloud SAML client +type Client struct { client *http.Client } // NewJumpCloudClient creates a new JumpCloud client -func NewJumpCloudClient(skipVerify bool) (*JumpCloudClient, error) { +func NewJumpCloudClient(skipVerify bool) (*Client, error) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify}, } @@ -40,13 +41,13 @@ func NewJumpCloudClient(skipVerify bool) (*JumpCloudClient, error) { client := &http.Client{Transport: tr, Jar: jar} - return &JumpCloudClient{ + return &Client{ client: client, }, nil } // Authenticate logs into JumpCloud and returns a SAML response -func (jc *JumpCloudClient) Authenticate(loginDetails *LoginDetails) (string, error) { +func (jc *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) { var authSubmitURL string var samlAssertion string mfaRequired := false @@ -159,7 +160,7 @@ func (jc *JumpCloudClient) Authenticate(loginDetails *LoginDetails) (string, err return samlAssertion, nil } -func updateJumpCloudForm(authForm url.Values, s *goquery.Selection, user *LoginDetails) { +func updateJumpCloudForm(authForm url.Values, s *goquery.Selection, user *creds.LoginDetails) { name, ok := s.Attr("name") if !ok { return diff --git a/keycloak.go b/pkg/provider/keycloak/keycloak.go similarity index 91% rename from keycloak.go rename to pkg/provider/keycloak/keycloak.go index 3d72eeee1..c50fa26fe 100644 --- a/keycloak.go +++ b/pkg/provider/keycloak/keycloak.go @@ -1,4 +1,4 @@ -package saml2aws +package keycloak import ( "bytes" @@ -12,19 +12,20 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/pkg/errors" + "github.com/versent/saml2aws/pkg/creds" "fmt" "golang.org/x/net/publicsuffix" ) -// KeyCloakClient wrapper around KeyCloak. -type KeyCloakClient struct { +// Client wrapper around KeyCloak. +type Client struct { client *http.Client } // NewKeyCloakClient create a new KeyCloakClient -func NewKeyCloakClient(skipVerify bool) (*KeyCloakClient, error) { +func NewKeyCloakClient(skipVerify bool) (*Client, error) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify}, @@ -42,13 +43,13 @@ func NewKeyCloakClient(skipVerify bool) (*KeyCloakClient, error) { client := &http.Client{Transport: tr, Jar: jar} - return &KeyCloakClient{ + return &Client{ client: client, }, nil } // Authenticate logs into KeyCloak and returns a SAML response -func (kc *KeyCloakClient) Authenticate(loginDetails *LoginDetails) (string, error) { +func (kc *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) { var authSubmitURL string var samlAssertion string authForm := url.Values{} @@ -130,7 +131,7 @@ func (kc *KeyCloakClient) Authenticate(loginDetails *LoginDetails) (string, erro return samlAssertion, nil } -func updateKeyCloakFormData(authForm url.Values, s *goquery.Selection, user *LoginDetails) { +func updateKeyCloakFormData(authForm url.Values, s *goquery.Selection, user *creds.LoginDetails) { name, ok := s.Attr("name") // log.Printf("name = %s ok = %v", name, ok) if !ok { diff --git a/okta.go b/pkg/provider/okta/okta.go similarity index 97% rename from okta.go rename to pkg/provider/okta/okta.go index 0a378e2a8..d030b9557 100644 --- a/okta.go +++ b/pkg/provider/okta/okta.go @@ -1,4 +1,4 @@ -package saml2aws +package okta import ( "bytes" @@ -16,14 +16,15 @@ import ( "github.com/pkg/errors" prompt "github.com/segmentio/go-prompt" "github.com/tidwall/gjson" + "github.com/versent/saml2aws/pkg/creds" "encoding/json" "golang.org/x/net/publicsuffix" ) -// OktaClient is a wrapper representing a Okta SAML client -type OktaClient struct { +// Client is a wrapper representing a Okta SAML client +type Client struct { client *http.Client } @@ -39,7 +40,7 @@ type VerifyRequest struct { } // NewOktaClient creates a new Okta client -func NewOktaClient(skipVerify bool) (*OktaClient, error) { +func NewOktaClient(skipVerify bool) (*Client, error) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify}, } @@ -55,13 +56,13 @@ func NewOktaClient(skipVerify bool) (*OktaClient, error) { client := &http.Client{Transport: tr, Jar: jar} - return &OktaClient{ + return &Client{ client: client, }, nil } // Authenticate logs into Okta and returns a SAML response -func (oc *OktaClient) Authenticate(loginDetails *LoginDetails) (string, error) { +func (oc *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) { var samlAssertion string oktaEntryURL := fmt.Sprintf("https://%s", loginDetails.Hostname) diff --git a/pingfed.go b/pkg/provider/pingfed/pingfed.go similarity index 94% rename from pingfed.go rename to pkg/provider/pingfed/pingfed.go index 98981754d..5152df8b0 100644 --- a/pingfed.go +++ b/pkg/provider/pingfed/pingfed.go @@ -1,4 +1,4 @@ -package saml2aws +package pingfed import ( "crypto/tls" @@ -11,12 +11,13 @@ import ( "github.com/PuerkitoBio/goquery" "github.com/pkg/errors" prompt "github.com/segmentio/go-prompt" + "github.com/versent/saml2aws/pkg/creds" "golang.org/x/net/publicsuffix" ) -// PingFedClient wrapper around PingFed + PingId enabling authentication and retrieval of assertions -type PingFedClient struct { +// Client wrapper around PingFed + PingId enabling authentication and retrieval of assertions +type Client struct { client *http.Client authSubmitURL string samlAssertion string @@ -24,7 +25,7 @@ type PingFedClient struct { } // NewPingFedClient create a new PingFed client -func NewPingFedClient(skipVerify bool) (*PingFedClient, error) { +func NewPingFedClient(skipVerify bool) (*Client, error) { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: skipVerify}, @@ -45,14 +46,14 @@ func NewPingFedClient(skipVerify bool) (*PingFedClient, error) { return errors.New("Redirect") } - return &PingFedClient{ + return &Client{ client: client, mfaRequired: false, }, nil } // Authenticate Authenticate to PingFed and return the data from the body of the SAML assertion. -func (ac *PingFedClient) Authenticate(loginDetails *LoginDetails) (string, error) { +func (ac *Client) Authenticate(loginDetails *creds.LoginDetails) (string, error) { authForm := url.Values{} @@ -210,7 +211,7 @@ func (ac *PingFedClient) Authenticate(loginDetails *LoginDetails) (string, error return ac.samlAssertion, nil } -func updateLoginFormData(authForm url.Values, s *goquery.Selection, user *LoginDetails) { +func updateLoginFormData(authForm url.Values, s *goquery.Selection, user *creds.LoginDetails) { name, ok := s.Attr("name") // log.Printf("name = %s ok = %v", name, ok) if !ok { diff --git a/shell/env.go b/pkg/shell/env.go similarity index 100% rename from shell/env.go rename to pkg/shell/env.go diff --git a/shell/env_test.go b/pkg/shell/env_test.go similarity index 100% rename from shell/env_test.go rename to pkg/shell/env_test.go diff --git a/shell/shell.go b/pkg/shell/shell.go similarity index 100% rename from shell/shell.go rename to pkg/shell/shell.go diff --git a/shell/shell_test.go b/pkg/shell/shell_test.go similarity index 100% rename from shell/shell_test.go rename to pkg/shell/shell_test.go diff --git a/shell/shell_windows.go b/pkg/shell/shell_windows.go similarity index 100% rename from shell/shell_windows.go rename to pkg/shell/shell_windows.go diff --git a/saml2aws.go b/saml2aws.go index 7aa02166d..ee1793034 100644 --- a/saml2aws.go +++ b/saml2aws.go @@ -1,6 +1,16 @@ package saml2aws -import "fmt" +import ( + "fmt" + + "github.com/versent/saml2aws/pkg/creds" + "github.com/versent/saml2aws/pkg/provider/adfs" + "github.com/versent/saml2aws/pkg/provider/adfs2" + "github.com/versent/saml2aws/pkg/provider/jumpcloud" + "github.com/versent/saml2aws/pkg/provider/keycloak" + "github.com/versent/saml2aws/pkg/provider/okta" + "github.com/versent/saml2aws/pkg/provider/pingfed" +) // Provider the SAML provider type Provider int @@ -14,7 +24,7 @@ const ( // SAMLClient client interface type SAMLClient interface { - Authenticate(loginDetails *LoginDetails) (string, error) + Authenticate(loginDetails *creds.LoginDetails) (string, error) } // SAMLOptions options for the new SAML client @@ -27,17 +37,17 @@ type SAMLOptions struct { func NewSAMLClient(opts *SAMLOptions) (SAMLClient, error) { switch opts.Provider { case "ADFS": - return NewADFSClient(opts.SkipVerify) + return adfs.NewADFSClient(opts.SkipVerify) case "ADFS2": - return NewADFS2Client(opts.SkipVerify) + return adfs2.NewADFS2Client(opts.SkipVerify) case "Ping": - return NewPingFedClient(opts.SkipVerify) + return pingfed.NewPingFedClient(opts.SkipVerify) case "JumpCloud": - return NewJumpCloudClient(opts.SkipVerify) + return jumpcloud.NewJumpCloudClient(opts.SkipVerify) case "Okta": - return NewOktaClient(opts.SkipVerify) + return okta.NewOktaClient(opts.SkipVerify) case "KeyCloak": - return NewKeyCloakClient(opts.SkipVerify) + return keycloak.NewKeyCloakClient(opts.SkipVerify) default: return nil, fmt.Errorf("Invalid provider: %v", opts.Provider) }