Browse Source

Sonar code smells and Unauthorized processing

[CLOUDTRUST-2654] Fix Sonar code smells
[CLOUDTRUST-2695] Change Unauthorized processing
master
sispeo 6 years ago
committed by GitHub
parent
commit
78647a0794
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .gitignore
  2. 65
      Gopkg.lock
  3. 3
      Gopkg.toml
  4. 2
      Jenkinsfile
  5. 21
      api/account.go
  6. 17
      api/authentication_management.go
  7. 3
      api/credentials.go
  8. 24
      api/keycloak_client.go
  9. 3
      api/realm.go
  10. 27
      errormessages.go
  11. 6
      integration/integration_test.go
  12. 9
      model_toolbox.go
  13. 25
      model_toolbox_test.go
  14. 7
      toolbox/issuer.go
  15. 21
      toolbox/issuer_test.go
  16. 8
      toolbox/logger.go
  17. 3
      toolbox/mock_test.go
  18. 7
      toolbox/oidc_connect.go
  19. 20
      toolbox/oidc_connect_test.go
  20. 2
      toolbox/oidc_verifier_test.go

2
.gitignore

@ -6,6 +6,7 @@
# Test binary, build with `go test -c` # Test binary, build with `go test -c`
*.test *.test
mock/
# Output of the go coverage tool, specifically when used with LiteIDE # Output of the go coverage tool, specifically when used with LiteIDE
*.out *.out
@ -19,3 +20,4 @@ vendor/*
bin/* bin/*
**/debug **/debug
**/.coverprofile **/.coverprofile
mock/

65
Gopkg.lock

@ -2,16 +2,12 @@
[[projects]] [[projects]]
branch = "master" digest = "1:fcbbb02d897902b3460476fcc6723f21a1674c0b6bd4a5579de11d53983d3d70"
digest = "1:840df8ec522c8d8d5f2f6fe0cf507e2370dcd5137bc119c1a280211e0cae2b9a"
name = "github.com/cloudtrust/common-service" name = "github.com/cloudtrust/common-service"
packages = [ packages = ["errors"]
".",
"errors",
"log",
]
pruneopts = "" pruneopts = ""
revision = "641630ce2eb40df09540f688a885ef450ea10d6b" revision = "0dac96e146315562f548272f90e3f0ccf9ea7ddb"
version = "v2.2.0"
[[projects]] [[projects]]
digest = "1:bb7f91ab4d1c44a3bb2651c613463c134165bda0282fca891a63b88d1b501997" digest = "1:bb7f91ab4d1c44a3bb2651c613463c134165bda0282fca891a63b88d1b501997"
@ -38,17 +34,17 @@
version = "v2.0.0" version = "v2.0.0"
[[projects]] [[projects]]
digest = "1:48e65aaf8ce34ffb3e8d56daa9417826db162afbc2040705db331e9a2e9eebe3" digest = "1:324437ddda77526fea02c29a2208ef1260e7a96ff0202965143215941564c400"
name = "github.com/go-kit/kit" name = "github.com/go-kit/kit"
packages = [ packages = [
"endpoint", "endpoint",
"log", "log",
"log/level", "transport",
"transport/http", "transport/http",
] ]
pruneopts = "" pruneopts = ""
revision = "12210fb6ace19e0496167bb3e667dcd91fa9f69b" revision = "cc938d52e0cdf4c811ab203f428fcd06f9d9a148"
version = "v0.8.0" version = "v0.10.0"
[[projects]] [[projects]]
digest = "1:aa9a6ccd5fd7d29804a27cb0666bc4ac5eb4b73439b7edd54f4b377e5ef8bb47" digest = "1:aa9a6ccd5fd7d29804a27cb0666bc4ac5eb4b73439b7edd54f4b377e5ef8bb47"
@ -59,12 +55,20 @@
version = "v0.5.0" version = "v0.5.0"
[[projects]] [[projects]]
digest = "1:686f864c452288f97bb25a51da037cdad321b40e17a803aa7645f848c729874e" digest = "1:03f8f40437ef8b7a1c7aed0ab000474245559153639ee44d6d43ec8eb9e24eda"
name = "github.com/golang/mock"
packages = ["gomock"]
pruneopts = ""
revision = "3a35fb6e3e18b9dbfee291262260dee7372d2a92"
version = "v1.4.3"
[[projects]]
digest = "1:02c7a8570f619bdb5620e8f6a16407455c8e63433d8a9e829f618813dc7f89a5"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
packages = ["proto"] packages = ["proto"]
pruneopts = "" pruneopts = ""
revision = "6c66de79d66478d166c7ea05f5d2ccaf016fbd6b" revision = "d04d7b157bb510b1e0c10132224b616ac0e26b17"
version = "v1.4.1" version = "v1.4.2"
[[projects]] [[projects]]
digest = "1:fbab76ba211c99fcd45a481a32530efc229f3510fd94889f361dcaf13ff05fe0" digest = "1:fbab76ba211c99fcd45a481a32530efc229f3510fd94889f361dcaf13ff05fe0"
@ -110,16 +114,16 @@
version = "v1.0.5" version = "v1.0.5"
[[projects]] [[projects]]
digest = "1:cc4eb6813da8d08694e557fcafae8fcc24f47f61a0717f952da130ca9a486dfc" digest = "1:9cc06d7468e429919ead45fc408b26838b4dfb12075f9756685ac6eae867b1a3"
name = "github.com/stretchr/testify" name = "github.com/stretchr/testify"
packages = ["assert"] packages = ["assert"]
pruneopts = "" pruneopts = ""
revision = "3ebf1ddaeb260c4b1ae502a01c7844fa8c1fa0e9" revision = "004e3cb72213e5e727e4e08f668ee6c8f27e5d32"
version = "v1.5.1" version = "v1.6.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:90f8aa620559abef3e8222064705e420dcb3498085b20782d128e5fa477b3a89" digest = "1:90e0a5569023a45d6f5ba62cf7b250b89a4310107e42c45b76481f518bb09cc7"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = [ packages = [
"ed25519", "ed25519",
@ -127,11 +131,11 @@
"pbkdf2", "pbkdf2",
] ]
pruneopts = "" pruneopts = ""
revision = "06a226fb4e3765ef3f48aa2852b401bc7b98e981" revision = "279210d13fedf5be6d476bad5df6a015042bb905"
[[projects]] [[projects]]
branch = "master" branch = "master"
digest = "1:ea84836e35d7a66c9b8944796295912509c80c921244bc4e098c5417219895f2" digest = "1:7254fd3f1a6e5ae98ab721ce6f3f09a79a59d3a1426e045fabc2548101e37333"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = [ packages = [
"context", "context",
@ -140,7 +144,7 @@
"publicsuffix", "publicsuffix",
] ]
pruneopts = "" pruneopts = ""
revision = "7e3656a0809f6f95abd88ac65313578f80b00df2" revision = "627f9648deb96c27737b83199d44bb5c1010cbcf"
[[projects]] [[projects]]
branch = "master" branch = "master"
@ -195,7 +199,7 @@
version = "v1.6.6" version = "v1.6.6"
[[projects]] [[projects]]
digest = "1:3f5031bb27e860d92d43004a88db1143b1c393c0430f68e562f1efd7e8d186ec" digest = "1:7579d802036911f3a087652830860739fcd8a03967ad5a3531e190aefe647f9d"
name = "google.golang.org/protobuf" name = "google.golang.org/protobuf"
packages = [ packages = [
"encoding/prototext", "encoding/prototext",
@ -227,8 +231,8 @@
"runtime/protoimpl", "runtime/protoimpl",
] ]
pruneopts = "" pruneopts = ""
revision = "8b0d71ac935315b10385aaaf30175de0c74bbba6" revision = "5c3dd7024aed895adfe053f26b5a479e991cbca9"
version = "v1.22.0" version = "v1.24.0"
[[projects]] [[projects]]
digest = "1:95fa5eae3b22887e8aea55ad4f93bc1374d586f7dd3504cf0010845ccc0a95a8" digest = "1:95fa5eae3b22887e8aea55ad4f93bc1374d586f7dd3504cf0010845ccc0a95a8"
@ -266,23 +270,22 @@
version = "v2.5.1" version = "v2.5.1"
[[projects]] [[projects]]
digest = "1:2efc9662a6a1ff28c65c84fc2f9030f13d3afecdb2ecad445f3b0c80e75fc281" branch = "v3"
name = "gopkg.in/yaml.v2" digest = "1:4eec9bf48dd37d5c72af308fb8609bb61ed7c18dc2677848ff1da45edb1dbbfd"
name = "gopkg.in/yaml.v3"
packages = ["."] packages = ["."]
pruneopts = "" pruneopts = ""
revision = "53403b58ad1b561927d19068c655246f2db79d48" revision = "e3079894b1e86c57cd48ff0d67dfd45de276d131"
version = "v2.2.8"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"
analyzer-version = 1 analyzer-version = 1
input-imports = [ input-imports = [
"github.com/cloudtrust/common-service",
"github.com/cloudtrust/common-service/errors", "github.com/cloudtrust/common-service/errors",
"github.com/cloudtrust/common-service/log",
"github.com/coreos/go-oidc", "github.com/coreos/go-oidc",
"github.com/gbrlsnchs/jwt", "github.com/gbrlsnchs/jwt",
"github.com/go-kit/kit/transport/http", "github.com/go-kit/kit/transport/http",
"github.com/golang/mock/gomock",
"github.com/gorilla/mux", "github.com/gorilla/mux",
"github.com/pkg/errors", "github.com/pkg/errors",
"github.com/spf13/pflag", "github.com/spf13/pflag",

3
Gopkg.toml

@ -22,7 +22,7 @@
[[constraint]] [[constraint]]
name = "github.com/cloudtrust/common-service" name = "github.com/cloudtrust/common-service"
branch = "master" version = "v2.2.0"
[[constraint]] [[constraint]]
name = "github.com/pkg/errors" name = "github.com/pkg/errors"
@ -32,7 +32,6 @@
name = "gopkg.in/h2non/gentleman.v2" name = "gopkg.in/h2non/gentleman.v2"
version = "2.0.0" version = "2.0.0"
[[constraint]] [[constraint]]
name = "github.com/gbrlsnchs/jwt" name = "github.com/gbrlsnchs/jwt"
version = "2.0.0" version = "2.0.0"

2
Jenkinsfile

@ -31,6 +31,8 @@ pipeline {
dep ensure dep ensure
go generate ./...
go test -coverprofile=coverage.out -json ./... | tee report.json go test -coverprofile=coverage.out -json ./... | tee report.json
go tool cover -func=coverage.out go tool cover -func=coverage.out
bash -c \"go vet ./... > >(cat) 2> >(tee govet.out)\" || true bash -c \"go vet ./... > >(cat) 2> >(tee govet.out)\" || true

21
api/account.go

@ -19,39 +19,44 @@ const (
accountMoveAfterPath = accountCredentialIDPath + "/moveAfter/:previousCredentialID" accountMoveAfterPath = accountCredentialIDPath + "/moveAfter/:previousCredentialID"
) )
var (
hdrAcceptJSON = headers.Set("Accept", "application/json")
hdrContentTypeTextPlain = headers.Set("Content-Type", "text/plain")
)
// GetCredentials returns the list of credentials of the user // GetCredentials returns the list of credentials of the user
func (c *AccountClient) GetCredentials(accessToken string, realmName string) ([]keycloak.CredentialRepresentation, error) { func (c *AccountClient) GetCredentials(accessToken string, realmName string) ([]keycloak.CredentialRepresentation, error) {
var resp = []keycloak.CredentialRepresentation{} var resp = []keycloak.CredentialRepresentation{}
var err = c.client.get(accessToken, &resp, url.Path(accountCredentialsPath), url.Param("realm", realmName), headers.Set("Accept", "application/json")) var err = c.client.get(accessToken, &resp, url.Path(accountCredentialsPath), url.Param("realm", realmName), hdrAcceptJSON)
return resp, err return resp, err
} }
// GetCredentialRegistrators returns list of credentials types available for the user // GetCredentialRegistrators returns list of credentials types available for the user
func (c *AccountClient) GetCredentialRegistrators(accessToken string, realmName string) ([]string, error) { func (c *AccountClient) GetCredentialRegistrators(accessToken string, realmName string) ([]string, error) {
var resp = []string{} var resp = []string{}
var err = c.client.get(accessToken, &resp, url.Path(accountCredentialsRegistratorsPath), url.Param("realm", realmName), headers.Set("Accept", "application/json")) var err = c.client.get(accessToken, &resp, url.Path(accountCredentialsRegistratorsPath), url.Param("realm", realmName), hdrAcceptJSON)
return resp, err return resp, err
} }
// UpdateLabelCredential updates the label of credential // UpdateLabelCredential updates the label of credential
func (c *AccountClient) UpdateLabelCredential(accessToken string, realmName string, credentialID string, label string) error { func (c *AccountClient) UpdateLabelCredential(accessToken string, realmName string, credentialID string, label string) error {
return c.client.put(accessToken, url.Path(accountCredentialLabelPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), body.String(label), headers.Set("Accept", "application/json"), headers.Set("Content-Type", "text/plain")) return c.client.put(accessToken, url.Path(accountCredentialLabelPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), body.String(label), hdrAcceptJSON, hdrContentTypeTextPlain)
} }
// DeleteCredential deletes the credential // DeleteCredential deletes the credential
func (c *AccountClient) DeleteCredential(accessToken string, realmName string, credentialID string) error { func (c *AccountClient) DeleteCredential(accessToken string, realmName string, credentialID string) error {
return c.client.delete(accessToken, url.Path(accountCredentialIDPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), headers.Set("Accept", "application/json")) return c.client.delete(accessToken, url.Path(accountCredentialIDPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), hdrAcceptJSON)
} }
// MoveToFirst moves the credential at the top of the list // MoveToFirst moves the credential at the top of the list
func (c *AccountClient) MoveToFirst(accessToken string, realmName string, credentialID string) error { func (c *AccountClient) MoveToFirst(accessToken string, realmName string, credentialID string) error {
_, err := c.client.post(accessToken, nil, url.Path(accountMoveFirstPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), headers.Set("Accept", "application/json")) _, err := c.client.post(accessToken, nil, url.Path(accountMoveFirstPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), hdrAcceptJSON)
return err return err
} }
// MoveAfter moves the credential after the specified one into the list // MoveAfter moves the credential after the specified one into the list
func (c *AccountClient) MoveAfter(accessToken string, realmName string, credentialID string, previousCredentialID string) error { func (c *AccountClient) MoveAfter(accessToken string, realmName string, credentialID string, previousCredentialID string) error {
_, err := c.client.post(accessToken, nil, url.Path(accountMoveAfterPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), url.Param("previousCredentialID", previousCredentialID), headers.Set("Accept", "application/json")) _, err := c.client.post(accessToken, nil, url.Path(accountMoveAfterPath), url.Param("realm", realmName), url.Param("credentialID", credentialID), url.Param("previousCredentialID", previousCredentialID), hdrAcceptJSON)
return err return err
} }
@ -65,7 +70,7 @@ func (c *AccountClient) UpdatePassword(accessToken, realm, currentPassword, newP
// GetAccount provides the user's information // GetAccount provides the user's information
func (c *AccountClient) GetAccount(accessToken string, realm string) (keycloak.UserRepresentation, error) { func (c *AccountClient) GetAccount(accessToken string, realm string) (keycloak.UserRepresentation, error) {
var resp = keycloak.UserRepresentation{} var resp = keycloak.UserRepresentation{}
var err = c.client.get(accessToken, &resp, url.Path(accountExtensionAPIPath), url.Param("realm", realm), headers.Set("Accept", "application/json")) var err = c.client.get(accessToken, &resp, url.Path(accountExtensionAPIPath), url.Param("realm", realm), hdrAcceptJSON)
return resp, err return resp, err
} }
@ -77,7 +82,7 @@ func (c *AccountClient) UpdateAccount(accessToken string, realm string, user key
// DeleteAccount delete current user // DeleteAccount delete current user
func (c *AccountClient) DeleteAccount(accessToken string, realmName string) error { func (c *AccountClient) DeleteAccount(accessToken string, realmName string) error {
return c.client.delete(accessToken, url.Path(accountExtensionAPIPath), url.Param("realm", realmName), headers.Set("Accept", "application/json")) return c.client.delete(accessToken, url.Path(accountExtensionAPIPath), url.Param("realm", realmName), hdrAcceptJSON)
} }
// ExecuteActionsEmail send an email with required actions to the user // ExecuteActionsEmail send an email with required actions to the user

17
api/authentication_management.go

@ -8,6 +8,9 @@ import (
const ( const (
authenticationManagementPath = "/auth/admin/realms/:realm/authentication" authenticationManagementPath = "/auth/admin/realms/:realm/authentication"
authenticationConfigPath = authenticationManagementPath + "/config/:id"
authenticationRequiredActionsPath = authenticationManagementPath + "/required-actions"
authenticationRequiredActionPath = authenticationRequiredActionsPath + "/:alias"
) )
// GetAuthenticatorProviders returns a list of authenticator providers. // GetAuthenticatorProviders returns a list of authenticator providers.
@ -34,18 +37,18 @@ func (c *Client) GetAuthenticatorProviderConfig(accessToken string, realmName, p
// GetAuthenticatorConfig returns the authenticator configuration. // GetAuthenticatorConfig returns the authenticator configuration.
func (c *Client) GetAuthenticatorConfig(accessToken string, realmName, configID string) (keycloak.AuthenticatorConfigRepresentation, error) { func (c *Client) GetAuthenticatorConfig(accessToken string, realmName, configID string) (keycloak.AuthenticatorConfigRepresentation, error) {
var resp = keycloak.AuthenticatorConfigRepresentation{} var resp = keycloak.AuthenticatorConfigRepresentation{}
var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID)) var err = c.get(accessToken, &resp, url.Path(authenticationConfigPath), url.Param("realm", realmName), url.Param("id", configID))
return resp, err return resp, err
} }
// UpdateAuthenticatorConfig updates the authenticator configuration. // UpdateAuthenticatorConfig updates the authenticator configuration.
func (c *Client) UpdateAuthenticatorConfig(accessToken string, realmName, configID string, config keycloak.AuthenticatorConfigRepresentation) error { func (c *Client) UpdateAuthenticatorConfig(accessToken string, realmName, configID string, config keycloak.AuthenticatorConfigRepresentation) error {
return c.put(accessToken, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID), body.JSON(config)) return c.put(accessToken, url.Path(authenticationConfigPath), url.Param("realm", realmName), url.Param("id", configID), body.JSON(config))
} }
// DeleteAuthenticatorConfig deletes the authenticator configuration. // DeleteAuthenticatorConfig deletes the authenticator configuration.
func (c *Client) DeleteAuthenticatorConfig(accessToken string, realmName, configID string) error { func (c *Client) DeleteAuthenticatorConfig(accessToken string, realmName, configID string) error {
return c.delete(accessToken, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID)) return c.delete(accessToken, url.Path(authenticationConfigPath), url.Param("realm", realmName), url.Param("id", configID))
} }
// CreateAuthenticationExecution add new authentication execution // CreateAuthenticationExecution add new authentication execution
@ -167,25 +170,25 @@ func (c *Client) RegisterRequiredAction(accessToken string, realmName, providerI
// GetRequiredActions returns a list of required actions. // GetRequiredActions returns a list of required actions.
func (c *Client) GetRequiredActions(accessToken string, realmName string) ([]keycloak.RequiredActionProviderRepresentation, error) { func (c *Client) GetRequiredActions(accessToken string, realmName string) ([]keycloak.RequiredActionProviderRepresentation, error) {
var resp = []keycloak.RequiredActionProviderRepresentation{} var resp = []keycloak.RequiredActionProviderRepresentation{}
var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/required-actions"), url.Param("realm", realmName)) var err = c.get(accessToken, &resp, url.Path(authenticationRequiredActionsPath), url.Param("realm", realmName))
return resp, err return resp, err
} }
// GetRequiredAction returns the required action for the alias. // GetRequiredAction returns the required action for the alias.
func (c *Client) GetRequiredAction(accessToken string, realmName, actionAlias string) (keycloak.RequiredActionProviderRepresentation, error) { func (c *Client) GetRequiredAction(accessToken string, realmName, actionAlias string) (keycloak.RequiredActionProviderRepresentation, error) {
var resp = keycloak.RequiredActionProviderRepresentation{} var resp = keycloak.RequiredActionProviderRepresentation{}
var err = c.get(accessToken, &resp, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias)) var err = c.get(accessToken, &resp, url.Path(authenticationRequiredActionPath), url.Param("realm", realmName), url.Param("alias", actionAlias))
return resp, err return resp, err
} }
// UpdateRequiredAction updates the required action. // UpdateRequiredAction updates the required action.
func (c *Client) UpdateRequiredAction(accessToken string, realmName, actionAlias string, action keycloak.RequiredActionProviderRepresentation) error { func (c *Client) UpdateRequiredAction(accessToken string, realmName, actionAlias string, action keycloak.RequiredActionProviderRepresentation) error {
return c.put(accessToken, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias), body.JSON(action)) return c.put(accessToken, url.Path(authenticationRequiredActionPath), url.Param("realm", realmName), url.Param("alias", actionAlias), body.JSON(action))
} }
// DeleteRequiredAction deletes the required action. // DeleteRequiredAction deletes the required action.
func (c *Client) DeleteRequiredAction(accessToken string, realmName, actionAlias string) error { func (c *Client) DeleteRequiredAction(accessToken string, realmName, actionAlias string) error {
return c.delete(accessToken, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias)) return c.delete(accessToken, url.Path(authenticationRequiredActionPath), url.Param("realm", realmName), url.Param("alias", actionAlias))
} }
// GetUnregisteredRequiredActions returns a list of unregistered required actions. // GetUnregisteredRequiredActions returns a list of unregistered required actions.

3
api/credentials.go

@ -3,7 +3,6 @@ package api
import ( import (
"github.com/cloudtrust/keycloak-client" "github.com/cloudtrust/keycloak-client"
"gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/headers"
"gopkg.in/h2non/gentleman.v2/plugins/url" "gopkg.in/h2non/gentleman.v2/plugins/url"
) )
@ -39,7 +38,7 @@ func (c *Client) GetCredentialTypes(accessToken string, realmName string) ([]str
// UpdateLabelCredential updates the label of credential // UpdateLabelCredential updates the label of credential
func (c *Client) UpdateLabelCredential(accessToken string, realmName string, userID string, credentialID string, label string) error { func (c *Client) UpdateLabelCredential(accessToken string, realmName string, userID string, credentialID string, label string) error {
return c.put(accessToken, url.Path(labelPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("credentialID", credentialID), body.String(label), headers.Set("Accept", "application/json"), headers.Set("Content-Type", "text/plain")) return c.put(accessToken, url.Path(labelPath), url.Param("realm", realmName), url.Param("id", userID), url.Param("credentialID", credentialID), body.String(label), hdrAcceptJSON, hdrContentTypeTextPlain)
} }
// DeleteCredential deletes the credential // DeleteCredential deletes the credential

24
api/keycloak_client.go

@ -35,11 +35,11 @@ type AccountClient struct {
} }
// New returns a keycloak client. // New returns a keycloak client.
func New(config keycloak.Config) (*Client, error) { func New(config keycloak.Config, keyContextIssuerDomain interface{}) (*Client, error) {
var issuerMgr toolbox.IssuerManager var issuerMgr toolbox.IssuerManager
{ {
var err error var err error
issuerMgr, err = toolbox.NewIssuerManager(config) issuerMgr, err = toolbox.NewIssuerManager(config, keyContextIssuerDomain)
if err != nil { if err != nil {
return nil, errors.Wrap(err, keycloak.MsgErrCannotParse+"."+keycloak.TokenProviderURL) return nil, errors.Wrap(err, keycloak.MsgErrCannotParse+"."+keycloak.TokenProviderURL)
} }
@ -159,10 +159,7 @@ func (c *Client) get(accessToken string, data interface{}, plugins ...plugin.Plu
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
return keycloak.HTTPError{ return keycloak.ClientDetailedError{HTTPStatus: http.StatusUnauthorized, Message: string(resp.Bytes())}
HTTPStatus: resp.StatusCode,
Message: string(resp.Bytes()),
}
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return treatErrorStatus(resp) return treatErrorStatus(resp)
case resp.StatusCode >= 200: case resp.StatusCode >= 200:
@ -201,10 +198,7 @@ func (c *Client) post(accessToken string, data interface{}, plugins ...plugin.Pl
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
return "", keycloak.HTTPError{ return "", keycloak.ClientDetailedError{HTTPStatus: http.StatusUnauthorized, Message: string(resp.Bytes())}
HTTPStatus: resp.StatusCode,
Message: string(resp.Bytes()),
}
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return "", treatErrorStatus(resp) return "", treatErrorStatus(resp)
case resp.StatusCode >= 200: case resp.StatusCode >= 200:
@ -245,10 +239,7 @@ func (c *Client) delete(accessToken string, plugins ...plugin.Plugin) error {
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
return keycloak.HTTPError{ return keycloak.ClientDetailedError{HTTPStatus: http.StatusUnauthorized, Message: string(resp.Bytes())}
HTTPStatus: resp.StatusCode,
Message: string(resp.Bytes()),
}
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return treatErrorStatus(resp) return treatErrorStatus(resp)
case resp.StatusCode >= 200: case resp.StatusCode >= 200:
@ -282,10 +273,7 @@ func (c *Client) put(accessToken string, plugins ...plugin.Plugin) error {
switch { switch {
case resp.StatusCode == http.StatusUnauthorized: case resp.StatusCode == http.StatusUnauthorized:
return keycloak.HTTPError{ return keycloak.ClientDetailedError{HTTPStatus: http.StatusUnauthorized, Message: string(resp.Bytes())}
HTTPStatus: resp.StatusCode,
Message: string(resp.Bytes()),
}
case resp.StatusCode >= 400: case resp.StatusCode >= 400:
return treatErrorStatus(resp) return treatErrorStatus(resp)
case resp.StatusCode >= 200: case resp.StatusCode >= 200:

3
api/realm.go

@ -3,7 +3,6 @@ package api
import ( import (
"github.com/cloudtrust/keycloak-client" "github.com/cloudtrust/keycloak-client"
"gopkg.in/h2non/gentleman.v2/plugins/body" "gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/headers"
"gopkg.in/h2non/gentleman.v2/plugins/url" "gopkg.in/h2non/gentleman.v2/plugins/url"
) )
@ -56,6 +55,6 @@ func (c *Client) ExportRealm(accessToken string, realmName string) (keycloak.Rea
// GetRealmCredentialRegistrators returns list of credentials types available for the realm // GetRealmCredentialRegistrators returns list of credentials types available for the realm
func (c *Client) GetRealmCredentialRegistrators(accessToken string, realmName string) ([]string, error) { func (c *Client) GetRealmCredentialRegistrators(accessToken string, realmName string) ([]string, error) {
var resp = []string{} var resp = []string{}
var err = c.get(accessToken, &resp, url.Path(realmCredentialRegistrators), url.Param("realm", realmName), headers.Set("Accept", "application/json")) var err = c.get(accessToken, &resp, url.Path(realmCredentialRegistrators), url.Param("realm", realmName), hdrAcceptJSON)
return resp, err return resp, err
} }

27
errormessages.go

@ -1,6 +1,8 @@
package keycloak package keycloak
import "strconv" import (
"fmt"
)
// Constants for error management // Constants for error management
const ( const (
@ -35,5 +37,26 @@ type HTTPError struct {
} }
func (e HTTPError) Error() string { func (e HTTPError) Error() string {
return strconv.Itoa(e.HTTPStatus) + ":" + e.Message return fmt.Sprintf("%d:%s", e.HTTPStatus, e.Message)
}
// ClientDetailedError struct
type ClientDetailedError struct {
HTTPStatus int
Message string
}
// Error implements error
func (e ClientDetailedError) Error() string {
return fmt.Sprintf("%d:%s", e.HTTPStatus, e.Message)
}
// Status implements common-service/errors/DetailedError
func (e ClientDetailedError) Status() int {
return e.HTTPStatus
}
// ErrorMessage implements common-service/errors/DetailedError
func (e ClientDetailedError) ErrorMessage() string {
return e.Message
} }

6
integration/integration_test.go

@ -12,15 +12,19 @@ import (
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
type keyContext int
const ( const (
tstRealm = "__internal" tstRealm = "__internal"
reqRealm = "master" reqRealm = "master"
user = "version" user = "version"
keyContextIssuerDomain keyContext = iota
) )
func main() { func main() {
var conf = getKeycloakConfig() var conf = getKeycloakConfig()
var client, err = api.New(*conf) var client, err = api.New(*conf, keyContextIssuerDomain)
if err != nil { if err != nil {
log.Fatalf("could not create keycloak client: %v", err) log.Fatalf("could not create keycloak client: %v", err)
} }

9
model_toolbox.go

@ -155,6 +155,15 @@ func (a Attributes) reformatDate(value *string, dateLayouts []string) *string {
return &res return &res
} }
// Merge current attributes with others (Values from others replace those with the same key in current attributes)
func (a Attributes) Merge(others *Attributes) {
if others != nil {
for key, attribute := range *others {
a[key] = attribute
}
}
}
// GetAttribute returns an attribute given its key // GetAttribute returns an attribute given its key
func (u *UserRepresentation) GetAttribute(key AttributeKey) []string { func (u *UserRepresentation) GetAttribute(key AttributeKey) []string {
if u.Attributes != nil { if u.Attributes != nil {

25
model_toolbox_test.go

@ -102,3 +102,28 @@ func TestUserRepresentationAttributes(t *testing.T) {
assert.True(t, *res) assert.True(t, *res)
}) })
} }
func TestMergeAttributes(t *testing.T) {
var (
currentAttributes = make(Attributes)
newAttributes = make(Attributes)
keyOne = AttributeKey("one")
keyTwo = AttributeKey("two")
keyThree = AttributeKey("three")
)
currentAttributes.SetString(keyOne, "abc")
currentAttributes.SetString(keyThree, "zyx")
currentAttributes.Merge(nil)
assert.Len(t, currentAttributes, 2)
newAttributes.SetString(keyTwo, "def")
newAttributes.SetString(keyThree, "ghi")
currentAttributes.Merge(&newAttributes)
assert.Len(t, currentAttributes, 3)
assert.Equal(t, "abc", *currentAttributes.GetString(keyOne))
assert.Equal(t, "def", *currentAttributes.GetString(keyTwo))
assert.Equal(t, "ghi", *currentAttributes.GetString(keyThree))
}

7
toolbox/issuer.go

@ -8,7 +8,6 @@ import (
"strings" "strings"
"time" "time"
cs "github.com/cloudtrust/common-service"
"github.com/cloudtrust/keycloak-client" "github.com/cloudtrust/keycloak-client"
) )
@ -19,6 +18,7 @@ type IssuerManager interface {
type issuerManager struct { type issuerManager struct {
domainToIssuer map[string]OidcVerifierProvider domainToIssuer map[string]OidcVerifierProvider
keyContextIssuerDomain interface{}
} }
func getProtocolAndDomain(URL string) string { func getProtocolAndDomain(URL string) string {
@ -32,7 +32,7 @@ func getProtocolAndDomain(URL string) string {
} }
// NewIssuerManager creates a new URLProvider // NewIssuerManager creates a new URLProvider
func NewIssuerManager(config keycloak.Config) (IssuerManager, error) { func NewIssuerManager(config keycloak.Config, keyContextIssuerDomain interface{}) (IssuerManager, error) {
URLs := config.AddrTokenProvider URLs := config.AddrTokenProvider
// Use default values when clients are not initializing these values // Use default values when clients are not initializing these values
cacheTTL := config.CacheTTL cacheTTL := config.CacheTTL
@ -56,11 +56,12 @@ func NewIssuerManager(config keycloak.Config) (IssuerManager, error) {
} }
return &issuerManager{ return &issuerManager{
domainToIssuer: domainToIssuer, domainToIssuer: domainToIssuer,
keyContextIssuerDomain: keyContextIssuerDomain,
}, nil }, nil
} }
func (im *issuerManager) GetIssuer(ctx context.Context) (OidcVerifierProvider, error) { func (im *issuerManager) GetIssuer(ctx context.Context) (OidcVerifierProvider, error) {
if rawValue := ctx.Value(cs.CtContextIssuerDomain); rawValue != nil { if rawValue := ctx.Value(im.keyContextIssuerDomain); rawValue != nil {
// The issuer domain has been found in the context // The issuer domain has been found in the context
issuerDomain := getProtocolAndDomain(rawValue.(string)) issuerDomain := getProtocolAndDomain(rawValue.(string))
if issuer, ok := im.domainToIssuer[issuerDomain]; ok { if issuer, ok := im.domainToIssuer[issuerDomain]; ok {

21
toolbox/issuer_test.go

@ -5,11 +5,16 @@ import (
"fmt" "fmt"
"testing" "testing"
cs "github.com/cloudtrust/common-service"
"github.com/cloudtrust/keycloak-client" "github.com/cloudtrust/keycloak-client"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
type contextKey int
const (
keyContextIssuerDomain contextKey = iota
)
func TestGetProtocolAndDomain(t *testing.T) { func TestGetProtocolAndDomain(t *testing.T) {
var invalidURL = "not a valid URL" var invalidURL = "not a valid URL"
assert.Equal(t, invalidURL, getProtocolAndDomain(invalidURL)) assert.Equal(t, invalidURL, getProtocolAndDomain(invalidURL))
@ -17,28 +22,28 @@ func TestGetProtocolAndDomain(t *testing.T) {
} }
func TestNewIssuerManager(t *testing.T) { func TestNewIssuerManager(t *testing.T) {
{ t.Run("Invalid URL", func(t *testing.T) {
_, err := NewIssuerManager(keycloak.Config{AddrTokenProvider: ":"}) _, err := NewIssuerManager(keycloak.Config{AddrTokenProvider: ":"}, keyContextIssuerDomain)
assert.NotNil(t, err) assert.NotNil(t, err)
} })
defaultPath := "http://default.domain.com:5555" defaultPath := "http://default.domain.com:5555"
myDomainPath := "http://my.domain.com/path/to/somewhere" myDomainPath := "http://my.domain.com/path/to/somewhere"
otherDomainPath := "http://other.domain.com:2120/" otherDomainPath := "http://other.domain.com:2120/"
allDomains := fmt.Sprintf("%s %s %s", defaultPath, myDomainPath, otherDomainPath) allDomains := fmt.Sprintf("%s %s %s", defaultPath, myDomainPath, otherDomainPath)
prov, err := NewIssuerManager(keycloak.Config{AddrTokenProvider: allDomains}) prov, err := NewIssuerManager(keycloak.Config{AddrTokenProvider: allDomains}, keyContextIssuerDomain)
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, prov) assert.NotNil(t, prov)
// No issuer provided with context // No issuer provided with context
issuerNoContext, _ := prov.GetIssuer(context.Background()) issuerNoContext, _ := prov.GetIssuer(context.Background())
// Unrecognized issuer provided in context // Unrecognized issuer provided in context
issuerDefault, _ := prov.GetIssuer(context.WithValue(context.Background(), cs.CtContextIssuerDomain, "http://unknown.issuer.com/one/path")) issuerDefault, _ := prov.GetIssuer(context.WithValue(context.Background(), keyContextIssuerDomain, "http://unknown.issuer.com/one/path"))
// Case insensitive // Case insensitive
issuerMyDomain, _ := prov.GetIssuer(context.WithValue(context.Background(), cs.CtContextIssuerDomain, "http://MY.DOMAIN.COM/issuer")) issuerMyDomain, _ := prov.GetIssuer(context.WithValue(context.Background(), keyContextIssuerDomain, "http://MY.DOMAIN.COM/issuer"))
// Other domain // Other domain
issuerOtherDomain, _ := prov.GetIssuer(context.WithValue(context.Background(), cs.CtContextIssuerDomain, "http://other.domain.com:2120/any/thing/here")) issuerOtherDomain, _ := prov.GetIssuer(context.WithValue(context.Background(), keyContextIssuerDomain, "http://other.domain.com:2120/any/thing/here"))
assert.Equal(t, issuerNoContext, issuerDefault) assert.Equal(t, issuerNoContext, issuerDefault)
assert.NotEqual(t, issuerNoContext, issuerMyDomain) assert.NotEqual(t, issuerNoContext, issuerMyDomain)

8
toolbox/logger.go

@ -0,0 +1,8 @@
package toolbox
import "context"
// Logger interface for logging with level
type Logger interface {
Warn(ctx context.Context, keyvals ...interface{})
}

3
toolbox/mock_test.go

@ -0,0 +1,3 @@
package toolbox
//go:generate mockgen -destination=./mock/logger.go -package=mock -mock_names=Logger=Logger github.com/cloudtrust/keycloak-client/toolbox Logger

7
toolbox/oidc_connect.go

@ -11,7 +11,6 @@ import (
"time" "time"
errorhandler "github.com/cloudtrust/common-service/errors" errorhandler "github.com/cloudtrust/common-service/errors"
"github.com/cloudtrust/common-service/log"
"github.com/cloudtrust/keycloak-client" "github.com/cloudtrust/keycloak-client"
) )
@ -35,7 +34,7 @@ type oidcTokenProvider struct {
timeout time.Duration timeout time.Duration
tokenURL string tokenURL string
reqBody string reqBody string
logger log.Logger logger Logger
oidcToken oidcToken oidcToken oidcToken
validUntil int64 validUntil int64
} }
@ -46,7 +45,7 @@ const (
) )
// NewOidcTokenProvider creates an OidcTokenProvider // NewOidcTokenProvider creates an OidcTokenProvider
func NewOidcTokenProvider(config keycloak.Config, realm, username, password, clientID string, logger log.Logger) OidcTokenProvider { func NewOidcTokenProvider(config keycloak.Config, realm, username, password, clientID string, logger Logger) OidcTokenProvider {
var urls = strings.Split(config.AddrTokenProvider, " ") var urls = strings.Split(config.AddrTokenProvider, " ")
var keycloakPublicURL = urls[0] var keycloakPublicURL = urls[0]
@ -90,7 +89,7 @@ func (o *oidcTokenProvider) ProvideToken(ctx context.Context) (string, error) {
} }
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
buf.ReadFrom(resp.Body) _, _ = buf.ReadFrom(resp.Body)
err = json.Unmarshal(buf.Bytes(), &o.oidcToken) err = json.Unmarshal(buf.Bytes(), &o.oidcToken)
if err != nil { if err != nil {

20
toolbox/oidc_connect_test.go

@ -9,8 +9,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/cloudtrust/common-service/log" "github.com/golang/mock/gomock"
"github.com/cloudtrust/keycloak-client" "github.com/cloudtrust/keycloak-client"
"github.com/cloudtrust/keycloak-client/toolbox/mock"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -30,6 +32,12 @@ func (t *TestResponse) ServeHTTP(w http.ResponseWriter, r *http.Request) {
} }
func TestCreateToken(t *testing.T) { func TestCreateToken(t *testing.T) {
var mockCtrl = gomock.NewController(t)
defer mockCtrl.Finish()
var mockLogger = mock.NewLogger(mockCtrl)
mockLogger.EXPECT().Warn(gomock.Any(), gomock.Any()).AnyTimes()
var oidcToken = oidcToken{ var oidcToken = oidcToken{
AccessToken: `eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJZRTUtNUpBb2NOcG5zeEpEaGRyYVdyWlVCZTBMR2xfanNILUtnb1EwWi1FIn0.eyJqdGkiOiIxYjJkZDY2NS01ZGE1LTRiMzAtODY0MS0wNWQ4ZTk0NTQ2ZWQiLCJleHAiOjE1NzkyMDQ0ODYsIm5iZiI6MCwiaWF0IjoxNTc5MTY4NDg2LCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbInBhc3NmbG93LXJlYWxtIiwibXlfcmVhbG0tcmVhbG0iLCJDbG91ZHRydXN0LXJlYWxtIiwibWFzdGVyLXJlYWxtIiwiYWNjb3VudCJdLCJzdWIiOiI3OTU5MjhjMy03N2Y1LTRmMjQtOTI0NC02NzBkMGJmMDJhMmQiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZG1pbi1jbGkiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI5ZTQ5NDA1MS1kZGQ1LTRhODctYTczZC1hOWU5YjMwYmFlZGEiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImNyZWF0ZS1yZWFsbSIsIm9mZmxpbmVfYWNjZXNzIiwiYWRtaW4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InBhc3NmbG93LXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19LCJteV9yZWFsbS1yZWFsbSI6eyJyb2xlcyI6WyJ2aWV3LXJlYWxtIiwidmlldy1pZGVudGl0eS1wcm92aWRlcnMiLCJtYW5hZ2UtaWRlbnRpdHktcHJvdmlkZXJzIiwiaW1wZXJzb25hdGlvbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiQ2xvdWR0cnVzdC1yZWFsbSI6eyJyb2xlcyI6WyJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsInZpZXctcmVhbG0iLCJtYW5hZ2UtaWRlbnRpdHktcHJvdmlkZXJzIiwiaW1wZXJzb25hdGlvbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUgZ3JvdXBzIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJncm91cHMiOlsiL3RvZV9hZG1pbmlzdHJhdG9yIl0sInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.GrPUDdQUID0S38ZSwVqarAuSDXrl5cJju3uq32y6bNGPK9a8jcHBP5FEfMcZ3vieQPtWFeySMycwTEcH6x6lc-9bj1w5veL4yyTA1zk_ERPshfiobk0u94vuljnoz-PW7JvBLOy47Bk5cP9pHPbJMPY0kOFHTpXZHd6KwfcE_X8gizLw4rDhIpK1NEtABQVzUNvP9fDZOm2I1PHJbl0odRE7EFu9Xh5ya8DaUQ2RKUb0E5csnA3DYlFdEhtMV1MAKRzqplDzj8zLQ8f8fflzC9_g4vmnDUEKSBxq1f1qKmzm1-XUuqRYTNWHfOtRR9rXrEzn-6fymFcRHIVGW7kgzg`, AccessToken: `eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJZRTUtNUpBb2NOcG5zeEpEaGRyYVdyWlVCZTBMR2xfanNILUtnb1EwWi1FIn0.eyJqdGkiOiIxYjJkZDY2NS01ZGE1LTRiMzAtODY0MS0wNWQ4ZTk0NTQ2ZWQiLCJleHAiOjE1NzkyMDQ0ODYsIm5iZiI6MCwiaWF0IjoxNTc5MTY4NDg2LCJpc3MiOiJodHRwOi8vMTI3LjAuMC4xOjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjpbInBhc3NmbG93LXJlYWxtIiwibXlfcmVhbG0tcmVhbG0iLCJDbG91ZHRydXN0LXJlYWxtIiwibWFzdGVyLXJlYWxtIiwiYWNjb3VudCJdLCJzdWIiOiI3OTU5MjhjMy03N2Y1LTRmMjQtOTI0NC02NzBkMGJmMDJhMmQiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZG1pbi1jbGkiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI5ZTQ5NDA1MS1kZGQ1LTRhODctYTczZC1hOWU5YjMwYmFlZGEiLCJhY3IiOiIxIiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImNyZWF0ZS1yZWFsbSIsIm9mZmxpbmVfYWNjZXNzIiwiYWRtaW4iLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InBhc3NmbG93LXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19LCJteV9yZWFsbS1yZWFsbSI6eyJyb2xlcyI6WyJ2aWV3LXJlYWxtIiwidmlldy1pZGVudGl0eS1wcm92aWRlcnMiLCJtYW5hZ2UtaWRlbnRpdHktcHJvdmlkZXJzIiwiaW1wZXJzb25hdGlvbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwiQ2xvdWR0cnVzdC1yZWFsbSI6eyJyb2xlcyI6WyJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsInZpZXctcmVhbG0iLCJtYW5hZ2UtaWRlbnRpdHktcHJvdmlkZXJzIiwiaW1wZXJzb25hdGlvbiIsImNyZWF0ZS1jbGllbnQiLCJtYW5hZ2UtdXNlcnMiLCJxdWVyeS1yZWFsbXMiLCJ2aWV3LWF1dGhvcml6YXRpb24iLCJxdWVyeS1jbGllbnRzIiwicXVlcnktdXNlcnMiLCJtYW5hZ2UtZXZlbnRzIiwibWFuYWdlLXJlYWxtIiwidmlldy1ldmVudHMiLCJ2aWV3LXVzZXJzIiwidmlldy1jbGllbnRzIiwibWFuYWdlLWF1dGhvcml6YXRpb24iLCJtYW5hZ2UtY2xpZW50cyIsInF1ZXJ5LWdyb3VwcyJdfSwibWFzdGVyLXJlYWxtIjp7InJvbGVzIjpbInZpZXctcmVhbG0iLCJ2aWV3LWlkZW50aXR5LXByb3ZpZGVycyIsIm1hbmFnZS1pZGVudGl0eS1wcm92aWRlcnMiLCJpbXBlcnNvbmF0aW9uIiwiY3JlYXRlLWNsaWVudCIsIm1hbmFnZS11c2VycyIsInF1ZXJ5LXJlYWxtcyIsInZpZXctYXV0aG9yaXphdGlvbiIsInF1ZXJ5LWNsaWVudHMiLCJxdWVyeS11c2VycyIsIm1hbmFnZS1ldmVudHMiLCJtYW5hZ2UtcmVhbG0iLCJ2aWV3LWV2ZW50cyIsInZpZXctdXNlcnMiLCJ2aWV3LWNsaWVudHMiLCJtYW5hZ2UtYXV0aG9yaXphdGlvbiIsIm1hbmFnZS1jbGllbnRzIiwicXVlcnktZ3JvdXBzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUgZ3JvdXBzIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJncm91cHMiOlsiL3RvZV9hZG1pbmlzdHJhdG9yIl0sInByZWZlcnJlZF91c2VybmFtZSI6ImFkbWluIn0.GrPUDdQUID0S38ZSwVqarAuSDXrl5cJju3uq32y6bNGPK9a8jcHBP5FEfMcZ3vieQPtWFeySMycwTEcH6x6lc-9bj1w5veL4yyTA1zk_ERPshfiobk0u94vuljnoz-PW7JvBLOy47Bk5cP9pHPbJMPY0kOFHTpXZHd6KwfcE_X8gizLw4rDhIpK1NEtABQVzUNvP9fDZOm2I1PHJbl0odRE7EFu9Xh5ya8DaUQ2RKUb0E5csnA3DYlFdEhtMV1MAKRzqplDzj8zLQ8f8fflzC9_g4vmnDUEKSBxq1f1qKmzm1-XUuqRYTNWHfOtRR9rXrEzn-6fymFcRHIVGW7kgzg`,
ExpiresIn: 3600, ExpiresIn: 3600,
@ -46,31 +54,31 @@ func TestCreateToken(t *testing.T) {
defer ts.Close() defer ts.Close()
t.Run("No body in HTTP response", func(t *testing.T) { t.Run("No body in HTTP response", func(t *testing.T) {
var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "nobody", "user", "passwd", "clientID", log.NewNopLogger()) var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "nobody", "user", "passwd", "clientID", mockLogger)
var _, err = p.ProvideToken(context.TODO()) var _, err = p.ProvideToken(context.TODO())
assert.NotNil(t, err) assert.NotNil(t, err)
}) })
t.Run("Invalid credentials", func(t *testing.T) { t.Run("Invalid credentials", func(t *testing.T) {
var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "invalid", "user", "passwd", "clientID", log.NewNopLogger()) var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "invalid", "user", "passwd", "clientID", mockLogger)
var _, err = p.ProvideToken(context.TODO()) var _, err = p.ProvideToken(context.TODO())
assert.NotNil(t, err) assert.NotNil(t, err)
}) })
t.Run("Invalid JSON", func(t *testing.T) { t.Run("Invalid JSON", func(t *testing.T) {
var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "bad-json", "user", "passwd", "clientID", log.NewNopLogger()) var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "bad-json", "user", "passwd", "clientID", mockLogger)
var _, err = p.ProvideToken(context.TODO()) var _, err = p.ProvideToken(context.TODO())
assert.NotNil(t, err) assert.NotNil(t, err)
}) })
t.Run("No HTTP response", func(t *testing.T) { t.Run("No HTTP response", func(t *testing.T) {
var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL + "0"}, "bad-json", "user", "passwd", "clientID", log.NewNopLogger()) var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL + "0"}, "bad-json", "user", "passwd", "clientID", mockLogger)
var _, err = p.ProvideToken(context.TODO()) var _, err = p.ProvideToken(context.TODO())
assert.NotNil(t, err) assert.NotNil(t, err)
}) })
t.Run("Valid credentials", func(t *testing.T) { t.Run("Valid credentials", func(t *testing.T) {
var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "valid", "user", "passwd", "clientID", log.NewNopLogger()) var p = NewOidcTokenProvider(keycloak.Config{AddrTokenProvider: ts.URL}, "valid", "user", "passwd", "clientID", mockLogger)
var timeStart = time.Now() var timeStart = time.Now()

2
toolbox/oidc_verifier_test.go

@ -1,7 +1,5 @@
package toolbox package toolbox
//go:generate mockgen -destination=./mock/authmanager.go -package=mock -mock_names=AuthorizationManager=AuthorizationManager github.com/cloudtrust/common-service/security AuthorizationManager
import ( import (
"context" "context"
"encoding/json" "encoding/json"

Loading…
Cancel
Save