Skip to content

Commit 9bd3f0d

Browse files
authored
Implement authentication timeout. (#12)
* Support auth expiry. * Support multiple keycloak versions in integration tests. * Implement possible auth types.
1 parent d900747 commit 9bd3f0d

File tree

11 files changed

+317
-80
lines changed

11 files changed

+317
-80
lines changed

Makefile

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ GO_INTEGRATION_PACKAGES = $(shell go list ./... | grep integration)
1515
GO_FILES = $(shell find . -name "*.go" | grep -v vendor | uniq)
1616
CI_TEST_REPORTS ?= /tmp/test-results
1717

18-
1918
.PHONY: init-ci
2019
init-ci:
2120
@echo "$(OK_COLOR)==> Installing minimal build requirements$(NO_COLOR)"
@@ -55,16 +54,25 @@ test: format lint
5554
go test -race -cover $(GO_PACKAGES)
5655

5756
# Test integration
58-
.PHONY: integration
59-
integration:
60-
@echo "$(OK_COLOR)==> Integration testing $(NO_COLOR)"
57+
.PHONY: integration-start
58+
integration-start:
6159
docker-compose -f $(PWD)/integration/docker-compose.yml up -d
62-
go test -race $(GO_INTEGRATION_PACKAGES)
63-
make integration-clean
60+
61+
.PHONY: integration
62+
integration: integration-start integration-test integration-stop
63+
64+
.PHONY: integration-stop
65+
integration-stop:
66+
docker-compose -f $(PWD)/integration/docker-compose.yml down
6467

6568
.PHONY: integration-clean
6669
integration-clean:
67-
docker-compose -f $(PWD)/integration/docker-compose.yml down
70+
rm -rf $(PWD)/build/database
71+
72+
.PHONY: integration-test
73+
integration-test:
74+
@echo "$(OK_COLOR)==> Integration testing $(NO_COLOR)"
75+
go test -race -v $(GO_INTEGRATION_PACKAGES)
6876

6977
# Generate coverage
7078
.PHONY: coverage

Readme.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ go get -u github.com/Azuka/keycloak-admin-go/...
2020
make init
2121
make test
2222
make integration
23+
#optionally
24+
make integration-clean
2325
```
2426
### Local CI
2527
- Install CircleCI locally: https://circleci.com/docs/2.0/local-cli
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
3+
# See https://github.com/mrts/docker-postgresql-multiple-databases
4+
5+
set -e
6+
set -u
7+
8+
function create_user_and_database() {
9+
local database=$1
10+
echo " Creating user and database '$database'"
11+
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
12+
CREATE USER $database;
13+
CREATE DATABASE $database;
14+
GRANT ALL PRIVILEGES ON DATABASE $database TO $database;
15+
EOSQL
16+
}
17+
18+
if [ -n "$POSTGRES_MULTIPLE_DATABASES" ]; then
19+
echo "Multiple database creation requested: $POSTGRES_MULTIPLE_DATABASES"
20+
for db in $(echo $POSTGRES_MULTIPLE_DATABASES | tr ',' ' '); do
21+
create_user_and_database $db
22+
done
23+
echo "Multiple databases created"
24+
fi

integration/docker-compose.yml

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,39 @@ services:
55
image: postgres:9.6
66
volumes:
77
- ../build/database:/var/lib/postgresql/data
8+
- ../build/create-multiple-postgresql-databases.sh:/docker-entrypoint-initdb.d/databases.sh
89
environment:
910
POSTGRES_USER: keycloak
1011
POSTGRES_PASSWORD: changeme
11-
POSTGRES_DB: keycloak
12+
POSTGRES_MULTIPLE_DATABASES: '"keycloak-4.0.0","keycloak-4.1.0","keycloak-4.8.0"'
1213

13-
keycloak:
14+
keycloak-4.0.0:
1415
image: jboss/keycloak:4.0.0.Final
16+
restart: always
1517
ports:
1618
- 9090:8080
1719
depends_on:
1820
- keycloak-db
1921
environment:
2022
KEYCLOAK_USER: keycloak-admin
2123
KEYCLOAK_PASSWORD: changeme
22-
DB_DATABASE: keycloak
24+
DB_DATABASE: keycloak-4.0.0
25+
DB_USER: keycloak
26+
DB_PASSWORD: changeme
27+
DB_ADDR: keycloak-db
28+
DB_VENDOR: postgres
29+
30+
keycloak-4.8.0:
31+
image: jboss/keycloak:4.8.0.Final
32+
restart: always
33+
ports:
34+
- 9098:8080
35+
depends_on:
36+
- keycloak-db
37+
environment:
38+
KEYCLOAK_USER: keycloak-admin
39+
KEYCLOAK_PASSWORD: changeme
40+
DB_DATABASE: keycloak-4.8.0
2341
DB_USER: keycloak
2442
DB_PASSWORD: changeme
2543
DB_ADDR: keycloak-db

integration/realm_test.go

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import (
66

77
func (suite *integrationTester) TestRealmFetch() {
88
realm, err := suite.client.Realm.Get(suite.ctx, keycloakAdminRealm)
9-
suite.NotNil(realm)
10-
suite.NoError(err)
11-
suite.Equal(keycloakAdminRealm, realm.ID)
9+
suite.NotNil(realm, suite.version)
10+
suite.NoError(err, suite.version)
11+
suite.Equal(keycloakAdminRealm, realm.ID, suite.version)
1212
}
1313

1414
func (suite *integrationTester) TestRealmDelete() {
@@ -21,10 +21,10 @@ func (suite *integrationTester) TestRealmDelete() {
2121
}
2222

2323
err := suite.client.Realm.Create(suite.ctx, newRealm)
24-
suite.NoError(err)
24+
suite.NoError(err, suite.version)
2525

2626
err = suite.client.Realm.Delete(suite.ctx, realmName)
27-
suite.NoError(err)
27+
suite.NoError(err, suite.version)
2828
}
2929

3030
func (suite *integrationTester) TestRealmCreate() {
@@ -50,25 +50,25 @@ func (suite *integrationTester) TestRealmCreate() {
5050
}
5151

5252
err := suite.client.Realm.Create(suite.ctx, newRealm)
53-
suite.NoError(err)
53+
suite.NoError(err, suite.version)
5454

5555
actualRealm, err := suite.client.Realm.Get(suite.ctx, realmName)
56-
suite.NoError(err)
57-
suite.NotNil(actualRealm)
58-
suite.Equal(actualRealm.ID, newRealm.ID)
59-
suite.Equal(actualRealm.Realm, newRealm.Realm)
56+
suite.NoError(err, suite.version)
57+
suite.NotNil(actualRealm, suite.version)
58+
suite.Equal(actualRealm.ID, newRealm.ID, suite.version)
59+
suite.Equal(actualRealm.Realm, newRealm.Realm, suite.version)
6060

61-
suite.Equal(actualRealm.AccessCodeLifespan, newRealm.AccessCodeLifespan)
62-
suite.Equal(actualRealm.AccessCodeLifespanLogin, newRealm.AccessCodeLifespanLogin)
63-
suite.Equal(actualRealm.AccessCodeLifespanUserAction, newRealm.AccessCodeLifespanUserAction)
64-
suite.Equal(actualRealm.AccessTokenLifespan, newRealm.AccessTokenLifespan)
65-
suite.Equal(actualRealm.AccessTokenLifespanForImplicitFlow, newRealm.AccessTokenLifespanForImplicitFlow)
66-
suite.Equal(actualRealm.AccountTheme, newRealm.AccountTheme)
67-
suite.Equal(actualRealm.ActionTokenGeneratedByAdminLifespan, newRealm.ActionTokenGeneratedByAdminLifespan)
68-
suite.Equal(actualRealm.ActionTokenGeneratedByUserLifespan, newRealm.ActionTokenGeneratedByUserLifespan)
69-
suite.Equal(actualRealm.AdminEventsDetailsEnabled, newRealm.AdminEventsDetailsEnabled)
70-
suite.Equal(actualRealm.AdminEventsEnabled, newRealm.AdminEventsEnabled)
71-
suite.Equal(actualRealm.AdminTheme, newRealm.AdminTheme)
72-
suite.Equal(actualRealm.DisplayName, newRealm.DisplayName)
73-
suite.Equal(actualRealm.DisplayNameHTML, newRealm.DisplayNameHTML)
61+
suite.Equal(actualRealm.AccessCodeLifespan, newRealm.AccessCodeLifespan, suite.version)
62+
suite.Equal(actualRealm.AccessCodeLifespanLogin, newRealm.AccessCodeLifespanLogin, suite.version)
63+
suite.Equal(actualRealm.AccessCodeLifespanUserAction, newRealm.AccessCodeLifespanUserAction, suite.version)
64+
suite.Equal(actualRealm.AccessTokenLifespan, newRealm.AccessTokenLifespan, suite.version)
65+
suite.Equal(actualRealm.AccessTokenLifespanForImplicitFlow, newRealm.AccessTokenLifespanForImplicitFlow, suite.version)
66+
suite.Equal(actualRealm.AccountTheme, newRealm.AccountTheme, suite.version)
67+
suite.Equal(actualRealm.ActionTokenGeneratedByAdminLifespan, newRealm.ActionTokenGeneratedByAdminLifespan, suite.version)
68+
suite.Equal(actualRealm.ActionTokenGeneratedByUserLifespan, newRealm.ActionTokenGeneratedByUserLifespan, suite.version)
69+
suite.Equal(actualRealm.AdminEventsDetailsEnabled, newRealm.AdminEventsDetailsEnabled, suite.version)
70+
suite.Equal(actualRealm.AdminEventsEnabled, newRealm.AdminEventsEnabled, suite.version)
71+
suite.Equal(actualRealm.AdminTheme, newRealm.AdminTheme, suite.version)
72+
suite.Equal(actualRealm.DisplayName, newRealm.DisplayName, suite.version)
73+
suite.Equal(actualRealm.DisplayNameHTML, newRealm.DisplayNameHTML, suite.version)
7474
}

integration/suite_test.go

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,44 @@ import (
1414
"github.com/stretchr/testify/suite"
1515
)
1616

17-
const keycloakEndpoint = "http://127.0.0.1:9090/auth/"
1817
const keycloakAdmin = "keycloak-admin"
1918
const keycloakPassword = "changeme"
2019
const keycloakAdminRealm = "master"
2120
const keycloakAdminClientID = "admin-cli"
2221

22+
var keyCloakEndpoints = map[string]string{
23+
"4.0.0": "http://127.0.0.1:9090/auth/",
24+
"4.8.0": "http://127.0.0.1:9098/auth/",
25+
}
26+
2327
type integrationTester struct {
2428
ready chan struct{}
2529
suite.Suite
26-
client *keycloak.Client
27-
ctx context.Context
30+
client *keycloak.Client
31+
ctx context.Context
32+
version string
33+
endpoint string
2834
}
2935

30-
func getHTTPClient(ctx context.Context) *http.Client {
31-
36+
func (suite *integrationTester) httpClient() *http.Client {
3237
config := auth.Config{
33-
ClientID: keycloakAdminClientID,
34-
TokenURL: keycloakEndpoint + "realms/" + keycloakAdminRealm + "/protocol/openid-connect/token",
35-
EndpointParams: url.Values{
36-
"username": {keycloakAdmin},
37-
"password": {keycloakPassword},
38-
"grant_type": {"password"},
39-
"client_id": {keycloakAdminClientID},
40-
},
38+
ClientID: keycloakAdminClientID,
39+
Username: keycloakAdmin,
40+
Password: keycloakPassword,
41+
GrantType: auth.PasswordGrant,
42+
TokenURL: suite.endpoint + "realms/" + keycloakAdminRealm + "/protocol/openid-connect/token",
4143
}
4244

4345
http.DefaultClient.Timeout = time.Second * 5
44-
45-
return config.Client(ctx)
46+
return config.Client(suite.ctx)
4647
}
4748

4849
func (suite *integrationTester) SetupSuite() {
4950
suite.ready = make(chan struct{})
5051
suite.ctx = context.Background()
5152

5253
connect := func() error {
53-
_, err := http.Get(keycloakEndpoint)
54+
_, err := http.Get(suite.endpoint)
5455

5556
if err == nil {
5657
close(suite.ready)
@@ -63,23 +64,28 @@ func (suite *integrationTester) SetupSuite() {
6364
}
6465

6566
// Setup test client
66-
u, _ := url.Parse(keycloakEndpoint + "admin")
67-
suite.client = keycloak.NewClient(*u, getHTTPClient(suite.ctx))
67+
u, _ := url.Parse(suite.endpoint + "admin")
68+
suite.client = keycloak.NewClient(*u, suite.httpClient())
6869
suite.client.Debug()
6970

70-
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*2)
71+
ctx, cancel := context.WithTimeout(context.Background(), time.Minute*10)
7172
defer cancel()
7273

7374
go func() {
7475
err := backoff.Retry(connect, backoff.WithContext(backoff.NewExponentialBackOff(), ctx))
7576
if err != nil {
76-
fmt.Println("error connecting: ", err)
77+
panic(fmt.Errorf("error connecting: %+v", err))
7778
}
7879
}()
7980

8081
<-suite.ready
8182
}
8283

8384
func TestKeycloakAdminIntegration(t *testing.T) {
84-
suite.Run(t, &integrationTester{})
85+
for version, endpoint := range keyCloakEndpoints {
86+
suite.Run(t, &integrationTester{
87+
version: version,
88+
endpoint: endpoint,
89+
})
90+
}
8591
}

integration/user_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ func (suite *integrationTester) TestUserFetch() {
88
users, err := suite.client.Users.Find(suite.ctx, keycloakAdminRealm, map[string]string{
99
"username": keycloakAdmin,
1010
})
11-
suite.NotNil(users)
12-
suite.NoError(err)
13-
suite.Len(users, 1)
14-
suite.Equal(keycloakAdmin, users[0].Username)
15-
suite.True(*users[0].Enabled)
11+
suite.NotNil(users, suite.version)
12+
suite.NoError(err, suite.version)
13+
suite.Len(users, 1, suite.version)
14+
suite.Equal(keycloakAdmin, users[0].Username, suite.version)
15+
suite.True(*users[0].Enabled, suite.version)
1616

1717
user := users[0]
1818
t := true
1919
user.EmailVerified = &t
2020

2121
err = suite.client.Users.Update(suite.ctx, keycloakAdminRealm, &user)
22-
suite.NoError(err)
22+
suite.NoError(err, suite.version)
2323
}
2424

2525
func (suite *integrationTester) TestUserCreate() {
@@ -31,6 +31,6 @@ func (suite *integrationTester) TestUserCreate() {
3131

3232
id, err := suite.client.Users.Create(suite.ctx, keycloakAdminRealm, user)
3333

34-
suite.NotEmpty(id)
35-
suite.NoError(err)
34+
suite.NotEmpty(id, suite.version)
35+
suite.NoError(err, suite.version)
3636
}

0 commit comments

Comments
 (0)