Browse Source

Merge pull request #2 from cloudtrust/add-routes

Add routes
master
harture 7 years ago
committed by GitHub
parent
commit
83447b0ac9
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      Gopkg.lock
  2. 27
      attack_detection.go
  3. 189
      authentication_management.go
  4. 54
      client_attribute_certificate.go
  5. 29
      client_initial_access.go
  6. 14
      client_registration_policy.go
  7. 27
      client_role_mappings.go
  8. 0
      client_templates.go
  9. 41
      clients.go
  10. 53
      clients_test.go
  11. 0
      component.go
  12. 1
      groups.go
  13. 1
      identity_providers.go
  14. 1
      key.go
  15. 58
      keycloak_client.go
  16. 40
      keycloak_client_test.go
  17. 2
      realm.go
  18. 1
      realms_admin.go
  19. 1
      role_mapper.go
  20. 1
      roles.go
  21. 1
      root.go
  22. 1
      scope_mappings.go
  23. 1
      user_storage_provider.go
  24. 6
      users.go
  25. 23
      users_test.go

14
Gopkg.lock

@ -19,6 +19,12 @@
revision = "925541529c1fa6821df4e44ce2723319eb2be768"
version = "v1.0.0"
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
revision = "645ef00459ed84a119197bfb8d8205042c6df63d"
version = "v0.8.0"
[[projects]]
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
@ -31,6 +37,12 @@
packages = [".","cacheobject"]
revision = "0dec1b30a0215bb68605dfc568e8855066c9202d"
[[projects]]
name = "github.com/spf13/pflag"
packages = ["."]
revision = "e57e3eeb33f795204c1ca35f56c44f83227c6e66"
version = "v1.0.0"
[[projects]]
name = "github.com/stretchr/testify"
packages = ["assert","require"]
@ -82,6 +94,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "5771516553a6ddbd4ae08c137169a7ca8437e019d877ae76413fbb7191e491ee"
inputs-digest = "bcd4dc5f3937d83e106e1a9999b3a7f5a9544ba495a3375c920688c9e73afce8"
solver-name = "gps-cdcl"
solver-version = 1

27
attack_detection.go

@ -0,0 +1,27 @@
package keycloak
import (
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
attackDetectionPath = "/auth/admin/realms/:realm/attack-detection/brute-force/users"
attackDetectionIDPath = attackDetectionPath + "/:id"
)
// ClearAllLoginFailures clears any user login failures for all users. This can release temporary disabled users.
func (c *Client) ClearAllLoginFailures(realmName string) error {
return c.delete(url.Path(attackDetectionPath), url.Param("realm", realmName))
}
// GetAttackDetectionStatus gets the status of a username in brute force detection.
func (c *Client) GetAttackDetectionStatus(realmName, userID string) (map[string]interface{}, error) {
var resp = map[string]interface{}{}
var err = c.get(&resp, url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID))
return resp, err
}
// ClearUserLoginFailures clear any user login failures for the user. This can release temporary disabled user.
func (c *Client) ClearUserLoginFailures(realmName, userID string) error {
return c.delete(url.Path(attackDetectionIDPath), url.Param("realm", realmName), url.Param("id", userID))
}

189
authentication_management.go

@ -0,0 +1,189 @@
package keycloak
import (
"gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
authenticationManagementPath = "/auth/admin/realms/:realm/authentication"
)
// GetAuthenticatorProviders returns a list of authenticator providers.
func (c *Client) GetAuthenticatorProviders(realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/authenticator-providers"), url.Param("realm", realmName))
return resp, err
}
// GetClientAuthenticatorProviders returns a list of client authenticator providers.
func (c *Client) GetClientAuthenticatorProviders(realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/client-authenticator-providers"), url.Param("realm", realmName))
return resp, err
}
// GetAuthenticatorProviderConfig returns the authenticator provider’s configuration description.
func (c *Client) GetAuthenticatorProviderConfig(realmName, providerID string) (AuthenticatorConfigInfoRepresentation, error) {
var resp = AuthenticatorConfigInfoRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/config-description/:providerID"), url.Param("realm", realmName), url.Param("providerID", providerID))
return resp, err
}
// GetAuthenticatorConfig returns the authenticator configuration.
func (c *Client) GetAuthenticatorConfig(realmName, configID string) (AuthenticatorConfigRepresentation, error) {
var resp = AuthenticatorConfigRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID))
return resp, err
}
// UpdateAuthenticatorConfig updates the authenticator configuration.
func (c *Client) UpdateAuthenticatorConfig(realmName, configID string, config AuthenticatorConfigRepresentation) error {
return c.put(url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID), body.JSON(config))
}
// DeleteAuthenticatorConfig deletes the authenticator configuration.
func (c *Client) DeleteAuthenticatorConfig(realmName, configID string) error {
return c.delete(url.Path(authenticationManagementPath+"/config/:id"), url.Param("realm", realmName), url.Param("id", configID))
}
// CreateAuthenticationExecution add new authentication execution
func (c *Client) CreateAuthenticationExecution(realmName string, authExec AuthenticationExecutionRepresentation) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions"), url.Param("realm", realmName), body.JSON(authExec))
}
// DeleteAuthenticationExecution deletes the execution.
func (c *Client) DeleteAuthenticationExecution(realmName, executionID string) error {
return c.delete(url.Path(authenticationManagementPath+"/executions/:id"), url.Param("realm", realmName), url.Param("id", executionID))
}
// UpdateAuthenticationExecution update execution with new configuration.
func (c *Client) UpdateAuthenticationExecution(realmName, executionID string, authConfig AuthenticatorConfigRepresentation) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/config"), url.Param("realm", realmName), url.Param("id", executionID), body.JSON(authConfig))
}
// LowerExecutionPriority lowers the execution’s priority.
func (c *Client) LowerExecutionPriority(realmName, executionID string) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/lower-priority"), url.Param("realm", realmName), url.Param("id", executionID))
}
// RaiseExecutionPriority raise the execution’s priority.
func (c *Client) RaiseExecutionPriority(realmName, executionID string) error {
return c.post(nil, url.Path(authenticationManagementPath+"/executions/:id/raise-priority"), url.Param("realm", realmName), url.Param("id", executionID))
}
// CreateAuthenticationFlow creates a new authentication flow.
func (c *Client) CreateAuthenticationFlow(realmName string, authFlow AuthenticationFlowRepresentation) error {
return c.post(nil, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName), body.JSON(authFlow))
}
// GetAuthenticationFlows returns a list of authentication flows.
func (c *Client) GetAuthenticationFlows(realmName string) ([]AuthenticationFlowRepresentation, error) {
var resp = []AuthenticationFlowRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/flows"), url.Param("realm", realmName))
return resp, err
}
// CopyExistingAuthenticationFlow copy the existing authentication flow under a new name.
// 'flowAlias' is the name of the existing authentication flow,
// 'newName' is the new name of the authentication flow.
func (c *Client) CopyExistingAuthenticationFlow(realmName, flowAlias, newName string) error {
var m = map[string]string{"newName": newName}
return c.post(nil, url.Path(authenticationManagementPath+"/flows/:flowAlias/copy"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m))
}
// GetAuthenticationExecutionForFlow returns the authentication executions for a flow.
func (c *Client) GetAuthenticationExecutionForFlow(realmName, flowAlias string) (AuthenticationExecutionInfoRepresentation, error) {
var resp = AuthenticationExecutionInfoRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias))
return resp, err
}
// UpdateAuthenticationExecutionForFlow updates the authentication executions of a flow.
func (c *Client) UpdateAuthenticationExecutionForFlow(realmName, flowAlias string, authExecInfo AuthenticationExecutionInfoRepresentation) error {
return c.put(url.Path(authenticationManagementPath+"/flows/:flowAlias/executions"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(authExecInfo))
}
// CreateAuthenticationExecutionForFlow add a new authentication execution to a flow.
// 'flowAlias' is the alias of the parent flow.
func (c *Client) CreateAuthenticationExecutionForFlow(realmName, flowAlias, provider string) error {
var m = map[string]string{"provider": provider}
return c.post(url.Path(authenticationManagementPath+"/flows/:flowAlias/executions/execution"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m))
}
// CreateFlowWithExecutionForExistingFlow add a new flow with a new execution to an existing flow.
// 'flowAlias' is the alias of the parent authentication flow.
func (c *Client) CreateFlowWithExecutionForExistingFlow(realmName, flowAlias, alias, flowType, provider, description string) error {
var m = map[string]string{"alias": alias, "type": flowType, "provider": provider, "description": description}
return c.post(url.Path(authenticationManagementPath+"/flows/:flowAlias/executions/flow"), url.Param("realm", realmName), url.Param("flowAlias", flowAlias), body.JSON(m))
}
// GetAuthenticationFlow gets the authentication flow for id.
func (c *Client) GetAuthenticationFlow(realmName, flowID string) (AuthenticationFlowRepresentation, error) {
var resp = AuthenticationFlowRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID))
return resp, err
}
// DeleteAuthenticationFlow deletes an authentication flow.
func (c *Client) DeleteAuthenticationFlow(realmName, flowID string) error {
return c.delete(url.Path(authenticationManagementPath+"/flows/:id"), url.Param("realm", realmName), url.Param("id", flowID))
}
// GetFormActionProviders returns a list of form action providers.
func (c *Client) GetFormActionProviders(realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/form-action-providers"), url.Param("realm", realmName))
return resp, err
}
// GetFormProviders returns a list of form providers.
func (c *Client) GetFormProviders(realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/form-providers"), url.Param("realm", realmName))
return resp, err
}
// GetConfigDescriptionForClients returns the configuration descriptions for all clients.
func (c *Client) GetConfigDescriptionForClients(realmName string) (map[string]interface{}, error) {
var resp = map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/per-client-config-description"), url.Param("realm", realmName))
return resp, err
}
// RegisterRequiredAction register a new required action.
func (c *Client) RegisterRequiredAction(realmName, providerID, name string) error {
var m = map[string]string{"providerId": providerID, "name": name}
return c.post(url.Path(authenticationManagementPath+"/register-required-action"), url.Param("realm", realmName), body.JSON(m))
}
// GetRequiredActions returns a list of required actions.
func (c *Client) GetRequiredActions(realmName string) ([]RequiredActionProviderRepresentation, error) {
var resp = []RequiredActionProviderRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/required-actions"), url.Param("realm", realmName))
return resp, err
}
// GetRequiredAction returns the required action for the alias.
func (c *Client) GetRequiredAction(realmName, actionAlias string) (RequiredActionProviderRepresentation, error) {
var resp = RequiredActionProviderRepresentation{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias))
return resp, err
}
// UpdateRequiredAction updates the required action.
func (c *Client) UpdateRequiredAction(realmName, actionAlias string, action RequiredActionProviderRepresentation) error {
return c.put(url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias), body.JSON(action))
}
// DeleteRequiredAction deletes the required action.
func (c *Client) DeleteRequiredAction(realmName, actionAlias string) error {
return c.delete(url.Path(authenticationManagementPath+"/required-actions/:alias"), url.Param("realm", realmName), url.Param("alias", actionAlias))
}
// GetUnregisteredRequiredActions returns a list of unregistered required actions.
func (c *Client) GetUnregisteredRequiredActions(realmName string) ([]map[string]interface{}, error) {
var resp = []map[string]interface{}{}
var err = c.get(&resp, url.Path(authenticationManagementPath+"/unregistered-required-actions"), url.Param("realm", realmName))
return resp, err
}

54
client_attribute_certificate.go

@ -0,0 +1,54 @@
package keycloak
import (
"bytes"
"gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
clientAttrCertPath = "/auth/admin/realms/:realm/clients/:id/certificates/:attr"
)
// GetKeyInfo returns the key info. idClient is the id of client (not client-id).
func (c *Client) GetKeyInfo(realmName, idClient, attr string) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{}
var err = c.get(&resp, url.Path(clientAttrCertPath), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr))
return resp, err
}
// GetKeyStore returns a keystore file for the client, containing private key and public certificate. idClient is the id of client (not client-id).
func (c *Client) GetKeyStore(realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) {
var resp = []byte{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig))
return resp, err
}
// GenerateCertificate generates a new certificate with new key pair. idClient is the id of client (not client-id).
func (c *Client) GenerateCertificate(realmName, idClient, attr string) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/generate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr))
return resp, err
}
// GenerateKeyPairAndCertificate generates a keypair and certificate and serves the private key in a specified keystore format.
func (c *Client) GenerateKeyPairAndCertificate(realmName, idClient, attr string, keyStoreConfig KeyStoreConfig) ([]byte, error) {
var resp = []byte{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/generate-and-download"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.JSON(keyStoreConfig))
return resp, err
}
// UploadCertificatePrivateKey uploads a certificate and eventually a private key.
func (c *Client) UploadCertificatePrivateKey(realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/upload"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file)))
return resp, err
}
// UploadCertificate uploads only a certificate, not the private key.
func (c *Client) UploadCertificate(realmName, idClient, attr string, file []byte) (CertificateRepresentation, error) {
var resp = CertificateRepresentation{}
var err = c.post(&resp, url.Path(clientAttrCertPath+"/upload-certificate"), url.Param("realm", realmName), url.Param("id", idClient), url.Param("attr", attr), body.Reader(bytes.NewReader(file)))
return resp, err
}

29
client_initial_access.go

@ -0,0 +1,29 @@
package keycloak
import (
"gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
clientInitialAccessPath = "/auth/admin/realms/:realm/clients-initial-access"
)
// CreateClientInitialAccess creates a new initial access token.
func (c *Client) CreateClientInitialAccess(realmName string, access ClientInitialAccessCreatePresentation) (ClientInitialAccessPresentation, error) {
var resp = ClientInitialAccessPresentation{}
var err = c.post(&resp, url.Path(clientInitialAccessPath), url.Param("realm", realmName), body.JSON(access))
return resp, err
}
// GetClientInitialAccess returns a list of clients initial access.
func (c *Client) GetClientInitialAccess(realmName string) ([]ClientInitialAccessPresentation, error) {
var resp = []ClientInitialAccessPresentation{}
var err = c.get(&resp, url.Path(clientInitialAccessPath), url.Param("realm", realmName))
return resp, err
}
// DeleteClientInitialAccess deletes the client initial access.
func (c *Client) DeleteClientInitialAccess(realmName, accessID string) error {
return c.delete(url.Path(clientInitialAccessPath+"/:id"), url.Param("realm", realmName), url.Param("id", accessID))
}

14
client_registration_policy.go

@ -0,0 +1,14 @@
package keycloak
import "gopkg.in/h2non/gentleman.v2/plugins/url"
const (
clientRegistrationPolicyPath = "/auth/admin/realms/:realm/client-registration-policy/providers"
)
// GetClientRegistrationPolicy is the base path to retrieve providers with the configProperties properly filled.
func (c *Client) GetClientRegistrationPolicy(realmName, configID string) ([]ComponentTypeRepresentation, error) {
var resp = []ComponentTypeRepresentation{}
var err = c.get(&resp, url.Path(clientRegistrationPolicyPath), url.Param("realm", realmName))
return resp, err
}

27
client_role_mappings.go

@ -0,0 +1,27 @@
package keycloak
import (
"gopkg.in/h2non/gentleman.v2/plugins/body"
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
clientRoleMappingPath = "/auth/admin/realms/:realm/groups/:id/role-mappings/clients/:client"
)
// CreateClientsRoleMapping add client-level roles to the user role mapping.
func (c *Client) CreateClientsRoleMapping(realmName, groupID, clientID string, roles []RoleRepresentation) error {
return c.post(nil, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID), body.JSON(roles))
}
// GetClientsRoleMapping gets client-level role mappings for the user, and the app.
func (c *Client) GetClientsRoleMapping(realmName, groupID, clientID string) ([]RoleRepresentation, error) {
var resp = []RoleRepresentation{}
var err = c.get(&resp, url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID))
return resp, err
}
// DeleteClientsRoleMapping deletes client-level roles from user role mapping.
func (c *Client) DeleteClientsRoleMapping(realmName, groupID, clientID string) error {
return c.delete(url.Path(clientRoleMappingPath), url.Param("realm", realmName), url.Param("id", groupID), url.Param("client", clientID))
}

0
client_test.go → client_templates.go

41
clients.go

@ -0,0 +1,41 @@
package keycloak
import (
"fmt"
"gopkg.in/h2non/gentleman.v2/plugins/url"
)
const (
clientsPath = "/auth/admin/realms/:realm/clients"
clientIDPath = clientsPath + "/:id"
clientSecret = clientsPath + "/client-secret"
)
// GetClients returns a list of clients belonging to the realm.
// Parameters: clientId (filter by clientId),
// viewableOnly (filter clients that cannot be viewed in full by admin, default="false")
func (c *Client) GetClients(realmName string, paramKV ...string) ([]ClientRepresentation, error) {
if len(paramKV)%2 != 0 {
return nil, fmt.Errorf("the number of key/val parameters should be even")
}
var resp = []ClientRepresentation{}
var plugins = append(createQueryPlugins(paramKV...), url.Path(clientsPath), url.Param("realm", realmName))
var err = c.get(&resp, plugins...)
return resp, err
}
// GetClient get the representation of the client. idClient is the id of client (not client-id).
func (c *Client) GetClient(realmName, idClient string) (ClientRepresentation, error) {
var resp = ClientRepresentation{}
var err = c.get(&resp, url.Path(clientIDPath), url.Param("realm", realmName), url.Param("id", idClient))
return resp, err
}
// GetSecret get the client secret. idClient is the id of client (not client-id).
func (c *Client) GetSecret(realmName, idClient string) (CredentialRepresentation, error) {
var resp = CredentialRepresentation{}
var err = c.get(&resp, url.Path(clientSecret), url.Param("realm", realmName), url.Param("id", idClient))
return resp, err
}

53
clients_test.go

@ -0,0 +1,53 @@
package keycloak
import (
"encoding/json"
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func TestPlayground(t *testing.T) {
var client = initTest(t)
var clients, err = client.GetClients("master")
for _, c := range clients {
printStruct(c)
}
assert.Nil(t, err)
}
func TestCreateRealm(t *testing.T) {
var client = initTest(t)
var clients, err = client.GetClients("master")
for i, c := range clients {
fmt.Println(i, *(c.Id), *c.ClientId)
}
assert.Nil(t, err)
}
func TestGetClient(t *testing.T) {
var client = initTest(t)
var c, err = client.GetClient("318ab6db-c056-4d2f-b4f6-c0b585ee45b3", "master")
fmt.Println(*(c.Id), *c.ClientId, c.Secret)
assert.Nil(t, err)
}
func TestGetSecret(t *testing.T) {
var client = initTest(t)
var c, err = client.GetSecret("318ab6db-c056-4d2f-b4f6-c0b585ee45b3", "master")
fmt.Println(*(c.Value))
assert.Nil(t, err)
}
func printStruct(data interface{}) {
var s, err = json.Marshal(data)
if err != nil {
fmt.Println("could not marshal json")
return
}
fmt.Println(string(s))
fmt.Println()
}

0
user_test.go → component.go

1
groups.go

@ -0,0 +1 @@
package keycloak

1
identity_providers.go

@ -0,0 +1 @@
package keycloak

1
key.go

@ -0,0 +1 @@
package keycloak

58
client.go → keycloak_client.go

@ -2,13 +2,13 @@ package keycloak
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"time"
oidc "github.com/coreos/go-oidc"
"github.com/pkg/errors"
"gopkg.in/h2non/gentleman.v2"
"gopkg.in/h2non/gentleman.v2/plugin"
"gopkg.in/h2non/gentleman.v2/plugins/query"
@ -39,13 +39,13 @@ func New(config Config) (*Client, error) {
var err error
u, err = url.Parse(config.Addr)
if err != nil {
return nil, fmt.Errorf("could not parse URL: %v", err)
return nil, errors.Wrap(err, "could not parse URL")
}
}
if u.Scheme != "http" {
return nil, fmt.Errorf("protocol not supported, your address must start with http://, not %v", u.Scheme)
}
// if u.Scheme != "http" {
// return nil, fmt.Errorf("protocol not supported, your address must start with http://, not %v", u.Scheme)
// }
var httpClient = gentleman.New()
{
@ -59,7 +59,7 @@ func New(config Config) (*Client, error) {
var issuer = fmt.Sprintf("%s/auth/realms/master", u.String())
oidcProvider, err = oidc.NewProvider(context.Background(), issuer)
if err != nil {
return nil, fmt.Errorf("could not create oidc provider: %v", err)
return nil, errors.Wrap(err, "could not create oidc provider")
}
}
@ -88,7 +88,7 @@ func (c *Client) getToken() error {
var err error
resp, err = req.Do()
if err != nil {
return fmt.Errorf("could not get token: %v", err)
return errors.Wrap(err, "could not get token")
}
}
defer resp.Close()
@ -98,7 +98,7 @@ func (c *Client) getToken() error {
var err error
err = resp.JSON(&unmarshalledBody)
if err != nil {
return fmt.Errorf("could not unmarshal response: %v", err)
return errors.Wrap(err, "could not unmarshal response")
}
}
@ -127,6 +127,7 @@ func (c *Client) verifyToken() error {
// get is a HTTP get method.
func (c *Client) get(data interface{}, plugins ...plugin.Plugin) error {
var req = c.httpClient.Get()
req = applyPlugins(req, c.accessToken, plugins...)
var resp *gentleman.Response
@ -134,7 +135,7 @@ func (c *Client) get(data interface{}, plugins ...plugin.Plugin) error {
var err error
resp, err = req.Do()
if err != nil {
return fmt.Errorf("could not get response: %v", err)
return errors.Wrap(err, "could not get response")
}
switch {
@ -143,30 +144,37 @@ func (c *Client) get(data interface{}, plugins ...plugin.Plugin) error {
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return fmt.Errorf("could not get token: %v", err)
return errors.Wrap(err, "could not get token: %v")
}
}
return c.get(data, plugins...)
case resp.StatusCode >= 400:
return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes()))
case resp.StatusCode >= 200:
return json.Unmarshal(resp.Bytes(), data)
switch resp.Header.Get("Content-Type") {
case "application/json":
return resp.JSON(data)
case "application/octet-stream":
data = resp.Bytes()
return nil
default:
return fmt.Errorf("unkown http content-type: %v", resp.Header.Get("Content-Type"))
}
default:
return fmt.Errorf("unknown response status code: %v", resp.StatusCode)
}
}
}
func (c *Client) post(plugins ...plugin.Plugin) error {
func (c *Client) post(data interface{}, plugins ...plugin.Plugin) error {
var req = c.httpClient.Post()
req = applyPlugins(req, c.accessToken, plugins...)
var resp *gentleman.Response
{
var err error
resp, err = req.Do()
if err != nil {
return fmt.Errorf("could not get response: %v", err)
return errors.Wrap(err, "could not get response")
}
switch {
@ -175,14 +183,22 @@ func (c *Client) post(plugins ...plugin.Plugin) error {
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return fmt.Errorf("could not get token: %v", err)
return errors.Wrap(err, "could not get token")
}
}
return c.post(plugins...)
return c.post(data, plugins...)
case resp.StatusCode >= 400:
return fmt.Errorf("invalid status code: '%v': %v", resp.RawResponse.Status, string(resp.Bytes()))
case resp.StatusCode >= 200:
return nil
switch resp.Header.Get("Content-Type") {
case "application/json":
return resp.JSON(data)
case "application/octet-stream":
data = resp.Bytes()
return nil
default:
return fmt.Errorf("unkown http content-type: %v", resp.Header.Get("Content-Type"))
}
default:
return fmt.Errorf("unknown response status code: %v", resp.StatusCode)
}
@ -198,7 +214,7 @@ func (c *Client) delete(plugins ...plugin.Plugin) error {
var err error
resp, err = req.Do()
if err != nil {
return fmt.Errorf("could not get response: %v", err)
return errors.Wrap(err, "could not get response")
}
switch {
@ -207,7 +223,7 @@ func (c *Client) delete(plugins ...plugin.Plugin) error {
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return fmt.Errorf("could not get token: %v", err)
return errors.Wrap(err, "could not get token")
}
}
return c.delete(plugins...)
@ -230,7 +246,7 @@ func (c *Client) put(plugins ...plugin.Plugin) error {
var err error
resp, err = req.Do()
if err != nil {
return fmt.Errorf("could not get response: %v", err)
return errors.Wrap(err, "could not get response")
}
switch {
@ -239,7 +255,7 @@ func (c *Client) put(plugins ...plugin.Plugin) error {
if err = c.verifyToken(); err != nil {
var err = c.getToken()
if err != nil {
return fmt.Errorf("could not get token: %v", err)
return errors.Wrap(err, "could not get token: %v")
}
}
return c.put(plugins...)

40
keycloak_client_test.go

@ -0,0 +1,40 @@
package keycloak
import (
"flag"
"fmt"
"os"
"testing"
"time"
"github.com/stretchr/testify/require"
)
var (
hostPort = flag.String("hostport", "10.244.18.2:80", "keycloak host:port")
username = flag.String("username", "admin", "keycloak user name")
password = flag.String("password", "admin", "keycloak password")
to = flag.Int("timeout", 20, "timeout in seconds")
)
func TestMain(m *testing.M) {
flag.Parse()
result := m.Run()
os.Exit(result)
}
func initTest(t *testing.T) *Client {
var config = Config{
Addr: fmt.Sprintf("http://%s", *hostPort),
Username: *username,
Password: *password,
Timeout: time.Duration(*to) * time.Second,
}
var client *Client
{
var err error
client, err = New(config)
require.Nil(t, err, "could not create client")
}
return client
}

2
realm.go

@ -21,7 +21,7 @@ func (c *Client) GetRealms() ([]RealmRepresentation, error) {
// CreateRealm creates the realm from its RealmRepresentation.
func (c *Client) CreateRealm(realm RealmRepresentation) error {
return c.post(url.Path(realmRootPath), body.JSON(realm))
return c.post(nil, url.Path(realmRootPath), body.JSON(realm))
}
// GetRealm get the top level represention of the realm. Nested information like users are

1
realms_admin.go

@ -0,0 +1 @@
package keycloak

1
role_mapper.go

@ -0,0 +1 @@
package keycloak

1
roles.go

@ -0,0 +1 @@
package keycloak

1
root.go

@ -0,0 +1 @@
package keycloak

1
scope_mappings.go

@ -0,0 +1 @@
package keycloak

1
user_storage_provider.go

@ -0,0 +1 @@
package keycloak

6
user.go → users.go

@ -29,8 +29,8 @@ func (c *Client) GetUsers(realmName string, paramKV ...string) ([]UserRepresenta
}
// CreateUser creates the user from its UserRepresentation. The username must be unique.
func (c *Client) CreateUser(realm string, user UserRepresentation) error {
return c.post(url.Path(userPath), url.Param("realm", realm), body.JSON(user))
func (c *Client) CreateUser(realmName string, user UserRepresentation) error {
return c.post(nil, url.Path(userPath), url.Param("realm", realmName), body.JSON(user))
}
// CountUsers returns the number of users in the realm.
@ -47,7 +47,7 @@ func (c *Client) GetUser(realmName, userID string) (UserRepresentation, error) {
return resp, err
}
// UpdateUser update the user.
// UpdateUser updates the user.
func (c *Client) UpdateUser(realmName, userID string, user UserRepresentation) error {
return c.put(url.Path(userIDPath), url.Param("realm", realmName), url.Param("id", userID), body.JSON(user))
}

23
users_test.go

@ -0,0 +1,23 @@
package keycloak
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetUsers(t *testing.T) {
var c = initTest(t)
var users []UserRepresentation
{
var err error
users, err = c.GetUsers("master")
require.Nil(t, err, "could not get users")
}
for _, i := range users {
fmt.Println(i.Credentials)
assert.NotZero(t, *i.Username)
}
}
Loading…
Cancel
Save