Skip to content

Commit

Permalink
chore: refactor keycloak groups tests
Browse files Browse the repository at this point in the history
Also add failing test for empty groups returning an error.
  • Loading branch information
smlx committed Jan 17, 2025
1 parent e69a887 commit 887fbab
Show file tree
Hide file tree
Showing 4 changed files with 356 additions and 12 deletions.
86 changes: 74 additions & 12 deletions internal/keycloak/groups_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,64 @@
package keycloak_test

import (
"encoding/json"
"bytes"
"context"
"io"
"net/http"
"net/http/httptest"
"os"
"reflect"
"testing"

"github.com/alecthomas/assert/v2"
"github.com/uselagoon/lagoon-opensearch-sync/internal/keycloak"
)

func TestGroupsUnmarshal(t *testing.T) {
// newTestGroupsServer sets up a mock keycloak which responds with
// appropriate group JSON data to exercise Groups.
func newTestGroupsServer(tt *testing.T, testDataPath string) *httptest.Server {
// load the discovery JSON first, because the mux closure needs to
// reference its buffer
discoveryBuf, err := os.ReadFile("testdata/realm.oidc.discovery.json")
if err != nil {
tt.Fatal(err)
return nil
}
// configure router with the URLs that OIDC discovery and JWKS require
mux := http.NewServeMux()
mux.HandleFunc("/auth/realms/lagoon/.well-known/openid-configuration",
func(w http.ResponseWriter, r *http.Request) {
d := bytes.NewBuffer(discoveryBuf)
_, err = io.Copy(w, d)
if err != nil {
tt.Fatal(err)
}
})
// configure the "all groups" path
mux.HandleFunc("/auth/admin/realms/lagoon/groups",
func(w http.ResponseWriter, r *http.Request) {
f, err := os.Open(testDataPath)
if err != nil {
tt.Fatal(err)
return
}
_, err = io.Copy(w, f)
if err != nil {
tt.Fatal(err)
}
})
ts := httptest.NewServer(mux)
// now replace the example URL in the discovery JSON with the actual
// httptest server URL
discoveryBuf = bytes.ReplaceAll(discoveryBuf,
[]byte("https://keycloak.example.com"), []byte(ts.URL))
return ts
}

func TestGroups(t *testing.T) {
var testCases = map[string]struct {
input string
expect []keycloak.Group
input string
expect []keycloak.Group
expectError bool
}{
"unmarshal groups": {
input: "testdata/groups.json",
Expand Down Expand Up @@ -110,20 +156,36 @@ func TestGroupsUnmarshal(t *testing.T) {
},
},
},
// https://github.com/uselagoon/lagoon-opensearch-sync/issues/150
"empty groups error response": {
input: "testdata/groups.empty.json",
expectError: true,
},
}
for name, tc := range testCases {
t.Run(name, func(tt *testing.T) {
jb, err := os.ReadFile(tc.input)
ts := newTestGroupsServer(tt, tc.input)
defer ts.Close()
ctx := context.Background()
k, err := keycloak.NewClientCredentialsClient(
ctx,
ts.URL,
"test-client-id",
"test-client-secret",
)
if err != nil {
tt.Fatal(err)
}
var groups []keycloak.Group
if err = json.Unmarshal(jb, &groups); err != nil {
tt.Fatal(err)
}
if !reflect.DeepEqual(tc.expect, groups) {
tt.Fatalf("expected %v, got %v", tc.expect, groups)
// override internal client credentials HTTP client for testing
k.UseDefaultHTTPClient()
// execute test
groups, err := k.Groups(ctx)
if tc.expectError {
assert.Error(tt, err, name)
} else {
assert.NoError(tt, err, name)
}
assert.Equal(tt, tc.expect, groups, name)
})
}
}
9 changes: 9 additions & 0 deletions internal/keycloak/helper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package keycloak

import "net/http"

// UseDefaultHTTPClient uses the default http client to avoid token refresh in
// tests.
func (c *Client) UseDefaultHTTPClient() {
c.httpClient = http.DefaultClient
}
1 change: 1 addition & 0 deletions internal/keycloak/testdata/groups.empty.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
272 changes: 272 additions & 0 deletions internal/keycloak/testdata/realm.oidc.discovery.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
{
"authorization_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"authorization_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"authorization_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/auth",
"authorization_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"backchannel_authentication_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/ext/ciba/auth",
"backchannel_authentication_request_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"ES256",
"RS256",
"ES512",
"PS256",
"PS512",
"RS512"
],
"backchannel_logout_session_supported": true,
"backchannel_logout_supported": true,
"backchannel_token_delivery_modes_supported": [
"poll",
"ping"
],
"check_session_iframe": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/login-status-iframe.html",
"claim_types_supported": [
"normal"
],
"claims_parameter_supported": true,
"claims_supported": [
"aud",
"sub",
"iss",
"auth_time",
"name",
"given_name",
"family_name",
"preferred_username",
"email",
"acr"
],
"code_challenge_methods_supported": [
"plain",
"S256"
],
"device_authorization_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/auth/device",
"end_session_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/logout",
"frontchannel_logout_session_supported": true,
"frontchannel_logout_supported": true,
"grant_types_supported": [
"authorization_code",
"implicit",
"refresh_token",
"password",
"client_credentials",
"urn:ietf:params:oauth:grant-type:device_code",
"urn:openid:params:grant-type:ciba"
],
"id_token_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"id_token_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"id_token_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"introspection_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/token/introspect",
"introspection_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"introspection_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"issuer": "https://keycloak.example.com/auth/realms/lagoon",
"jwks_uri": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/certs",
"mtls_endpoint_aliases": {
"backchannel_authentication_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/ext/ciba/auth",
"device_authorization_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/auth/device",
"introspection_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/token/introspect",
"pushed_authorization_request_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/ext/par/request",
"registration_endpoint": "https://keycloak.example.com/auth/realms/lagoon/clients-registrations/openid-connect",
"revocation_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/revoke",
"token_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/token",
"userinfo_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/userinfo"
},
"pushed_authorization_request_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/ext/par/request",
"registration_endpoint": "https://keycloak.example.com/auth/realms/lagoon/clients-registrations/openid-connect",
"request_object_encryption_alg_values_supported": [
"RSA-OAEP",
"RSA-OAEP-256",
"RSA1_5"
],
"request_object_encryption_enc_values_supported": [
"A256GCM",
"A192GCM",
"A128GCM",
"A128CBC-HS256",
"A192CBC-HS384",
"A256CBC-HS512"
],
"request_object_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
],
"request_parameter_supported": true,
"request_uri_parameter_supported": true,
"require_pushed_authorization_requests": false,
"require_request_uri_registration": true,
"response_modes_supported": [
"query",
"fragment",
"form_post",
"query.jwt",
"fragment.jwt",
"form_post.jwt",
"jwt"
],
"response_types_supported": [
"code",
"none",
"id_token",
"token",
"id_token token",
"code id_token",
"code token",
"code id_token token"
],
"revocation_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/revoke",
"revocation_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"revocation_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"scopes_supported": [
"openid",
"email",
"roles",
"address",
"offline_access",
"web-origins",
"profile",
"microprofile-jwt",
"phone"
],
"subject_types_supported": [
"public",
"pairwise"
],
"tls_client_certificate_bound_access_tokens": true,
"token_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/token",
"token_endpoint_auth_methods_supported": [
"private_key_jwt",
"client_secret_basic",
"client_secret_post",
"tls_client_auth",
"client_secret_jwt"
],
"token_endpoint_auth_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512"
],
"userinfo_endpoint": "https://keycloak.example.com/auth/realms/lagoon/protocol/openid-connect/userinfo",
"userinfo_signing_alg_values_supported": [
"PS384",
"ES384",
"RS384",
"HS256",
"HS512",
"ES256",
"RS256",
"HS384",
"ES512",
"PS256",
"PS512",
"RS512",
"none"
]
}

0 comments on commit 887fbab

Please sign in to comment.