keycloak-api-manager 3.2.1 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +27 -0
- package/Handlers/clientsHandler.js +240 -30
- package/Handlers/groupsHandler.js +16 -1
- package/Handlers/httpApiHelper.js +87 -0
- package/Handlers/realmsHandler.js +26 -4
- package/Handlers/usersHandler.js +43 -10
- package/README.md +341 -10
- package/index.js +159 -29
- package/package.json +3 -14
- package/test/.mocharc.json +4 -0
- package/test/TESTING.md +327 -0
- package/test/config/CONFIGURATION.md +170 -0
- package/test/config/default.json +36 -0
- package/test/config/local.json.example +7 -0
- package/test/config/secrets.json.example +7 -0
- package/test/diagnostic-protocol-mappers.js +189 -0
- package/test/docker-keycloak/DEPLOYMENT_GUIDE.md +262 -0
- package/test/docker-keycloak/certs/.gitkeep +7 -0
- package/test/docker-keycloak/docker-compose-https.yml +50 -0
- package/test/docker-keycloak/docker-compose.yml +59 -0
- package/test/docker-keycloak/setup-keycloak.js +501 -0
- package/test/enableServerFeatures.js +315 -0
- package/test/helpers/config.js +218 -0
- package/test/helpers/docker-helpers.js +513 -0
- package/test/helpers/setup.js +186 -0
- package/test/package.json +18 -0
- package/test/setup.js +194 -0
- package/test/specs/authenticationManagement.test.js +224 -0
- package/test/specs/clientCredentials.test.js +76 -0
- package/test/specs/clientScopes.test.js +388 -0
- package/test/specs/clients.test.js +791 -0
- package/test/specs/components.test.js +151 -0
- package/test/specs/debugClientLibrary.test.js +88 -0
- package/test/specs/groups.test.js +362 -0
- package/test/specs/identityProviders.test.js +292 -0
- package/test/specs/realms.test.js +390 -0
- package/test/specs/roles.test.js +322 -0
- package/test/specs/users.test.js +445 -0
- package/test/testConfig.js +69 -0
- package/.mocharc.json +0 -7
- package/docker-compose.yml +0 -27
- package/test/authenticationManagement.test.js +0 -329
- package/test/clientScopes.test.js +0 -256
- package/test/clients.test.js +0 -284
- package/test/components.test.js +0 -122
- package/test/config.js +0 -137
- package/test/docker-helpers.js +0 -111
- package/test/groups.test.js +0 -284
- package/test/identityProviders.test.js +0 -197
- package/test/mocha.env.js +0 -55
- package/test/realms.test.js +0 -349
- package/test/roles.test.js +0 -215
- package/test/users.test.js +0 -405
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Test Configuration
|
|
2
|
+
|
|
3
|
+
This directory contains hierarchical configuration files managed by [propertiesmanager](https://www.npmjs.com/package/propertiesmanager).
|
|
4
|
+
|
|
5
|
+
## Configuration Files
|
|
6
|
+
|
|
7
|
+
### `default.json` (required, committed to git)
|
|
8
|
+
Base configuration with non-sensitive defaults. Contains the "test" environment section with:
|
|
9
|
+
|
|
10
|
+
- **keycloak**: Admin connection settings (baseUrl, realmName, clientId, username, grantType)
|
|
11
|
+
- **realm**: Test realm infrastructure specifications (realm name, client, user, roles, groups, scopes)
|
|
12
|
+
|
|
13
|
+
**When to edit**: Update non-sensitive defaults that all developers should use.
|
|
14
|
+
|
|
15
|
+
### `secrets.json` (required, gitignored)
|
|
16
|
+
Sensitive credentials overlaid on default.json. Contains passwords and secrets.
|
|
17
|
+
|
|
18
|
+
**Structure**:
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"test": {
|
|
22
|
+
"keycloak": {
|
|
23
|
+
"password": "admin"
|
|
24
|
+
},
|
|
25
|
+
"realm": {
|
|
26
|
+
"user": {
|
|
27
|
+
"password": "test-password"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**When to create**: Before running tests for the first time. Copy structure above and fill in your Keycloak admin password.
|
|
35
|
+
|
|
36
|
+
### `local.json` (optional, gitignored)
|
|
37
|
+
Developer-specific overrides for local environments. Useful for:
|
|
38
|
+
- Custom baseUrl (localhost instead of tunnel)
|
|
39
|
+
- Different realm names
|
|
40
|
+
- Custom ports
|
|
41
|
+
|
|
42
|
+
**Example**:
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"test": {
|
|
46
|
+
"keycloak": {
|
|
47
|
+
"baseUrl": "http://localhost:8080"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**When to create**: Only if you need to override defaults for your local environment.
|
|
54
|
+
|
|
55
|
+
### `local.json.example` (committed to git)
|
|
56
|
+
Template showing example local overrides. Copy to `local.json` and customize.
|
|
57
|
+
|
|
58
|
+
## Configuration Loading
|
|
59
|
+
|
|
60
|
+
Files are merged in this order:
|
|
61
|
+
1. **default.json** - Base configuration
|
|
62
|
+
2. **secrets.json** - Overlays sensitive credentials
|
|
63
|
+
3. **local.json** - Overlays developer-specific settings (if exists)
|
|
64
|
+
|
|
65
|
+
The environment section is determined by `NODE_ENV` (default: "test").
|
|
66
|
+
|
|
67
|
+
## Important Notes
|
|
68
|
+
|
|
69
|
+
### Environment Wrapper Required
|
|
70
|
+
All configuration must be wrapped in an environment key:
|
|
71
|
+
|
|
72
|
+
✅ **Correct**:
|
|
73
|
+
```json
|
|
74
|
+
{
|
|
75
|
+
"test": {
|
|
76
|
+
"keycloak": { "baseUrl": "..." }
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
❌ **Incorrect**:
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"keycloak": { "baseUrl": "..." }
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Git Ignored Files
|
|
89
|
+
These files are excluded from git (see `.gitignore`):
|
|
90
|
+
- `secrets.json` - Contains passwords
|
|
91
|
+
- `local.json` - Developer-specific customizations
|
|
92
|
+
|
|
93
|
+
### Security
|
|
94
|
+
- Never commit `secrets.json` or `local.json`
|
|
95
|
+
- Keep passwords out of `default.json`
|
|
96
|
+
- Use secure passwords in production-like environments
|
|
97
|
+
|
|
98
|
+
## Configuration Schema
|
|
99
|
+
|
|
100
|
+
### keycloak (admin connection)
|
|
101
|
+
```json
|
|
102
|
+
{
|
|
103
|
+
"baseUrl": "http://127.0.0.1:9998", // Keycloak server URL
|
|
104
|
+
"realmName": "master", // Admin realm (usually "master")
|
|
105
|
+
"clientId": "admin-cli", // Admin client ID
|
|
106
|
+
"username": "admin", // Admin username
|
|
107
|
+
"password": "admin", // Admin password (in secrets.json)
|
|
108
|
+
"grantType": "password", // OAuth2 grant type
|
|
109
|
+
"tokenLifeSpan": 60 // Token refresh interval (seconds)
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Diagnostic Script Configuration
|
|
114
|
+
|
|
115
|
+
The manual diagnostic script [test/diagnostic-protocol-mappers.js](../diagnostic-protocol-mappers.js)
|
|
116
|
+
uses the same `test` configuration (including `baseUrl`, credentials, and realm settings).
|
|
117
|
+
It is not part of the automated test suite and must be run manually.
|
|
118
|
+
|
|
119
|
+
Run it with:
|
|
120
|
+
```bash
|
|
121
|
+
node test/diagnostic-protocol-mappers.js
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Make sure `baseUrl` points to a reachable Keycloak instance and `secrets.json` contains valid credentials.
|
|
125
|
+
|
|
126
|
+
### realm (test infrastructure)
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"name": "keycloak-api-manager-test-realm", // Test realm name
|
|
130
|
+
"client": {
|
|
131
|
+
"clientId": "test-client", // Test client ID
|
|
132
|
+
"clientSecret": "test-client-secret" // Test client secret
|
|
133
|
+
},
|
|
134
|
+
"user": {
|
|
135
|
+
"username": "test-user", // Test user username
|
|
136
|
+
"password": "test-password", // Test user password (in secrets.json)
|
|
137
|
+
"email": "test-user@test.local", // Test user email
|
|
138
|
+
"firstName": "Test", // Test user first name
|
|
139
|
+
"lastName": "User" // Test user last name
|
|
140
|
+
},
|
|
141
|
+
"roles": ["test-role-1", "test-role-2", "test-admin-role"], // Roles to create
|
|
142
|
+
"group": {
|
|
143
|
+
"name": "test-group" // Test group name
|
|
144
|
+
},
|
|
145
|
+
"clientScope": {
|
|
146
|
+
"name": "test-scope" // Test client scope name
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Troubleshooting
|
|
152
|
+
|
|
153
|
+
### "Configuration loading failed"
|
|
154
|
+
- Ensure `secrets.json` exists with valid JSON
|
|
155
|
+
- Check that environment wrapper "test" is present in all files
|
|
156
|
+
- Verify JSON syntax (no trailing commas, proper quotes)
|
|
157
|
+
|
|
158
|
+
### "Access denied" errors during tests
|
|
159
|
+
- Check admin username/password in `secrets.json`
|
|
160
|
+
- Verify `baseUrl` points to accessible Keycloak instance
|
|
161
|
+
- If using SSH tunnel, ensure it's active
|
|
162
|
+
|
|
163
|
+
### "Realm not found" errors
|
|
164
|
+
- Ensure global setup ran successfully (check console output)
|
|
165
|
+
- Verify realm name matches between config and test expectations
|
|
166
|
+
- Check that Keycloak instance is running and accessible
|
|
167
|
+
|
|
168
|
+
## More Information
|
|
169
|
+
|
|
170
|
+
See main project [README.md](../../README.md) for overall test architecture and execution instructions.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"test": {
|
|
3
|
+
"keycloak": {
|
|
4
|
+
"baseUrl": "https://smart-dell-sml.crs4.it:8443",
|
|
5
|
+
"realmName": "master",
|
|
6
|
+
"clientId": "admin-cli",
|
|
7
|
+
"username": "admin",
|
|
8
|
+
"grantType": "password",
|
|
9
|
+
"tokenLifeSpan": 60
|
|
10
|
+
},
|
|
11
|
+
"realm": {
|
|
12
|
+
"name": "keycloak-api-manager-test-realm",
|
|
13
|
+
"client": {
|
|
14
|
+
"clientId": "test-client",
|
|
15
|
+
"clientSecret": "test-client-secret"
|
|
16
|
+
},
|
|
17
|
+
"user": {
|
|
18
|
+
"username": "test-user",
|
|
19
|
+
"email": "test-user@test.local",
|
|
20
|
+
"firstName": "Test",
|
|
21
|
+
"lastName": "User"
|
|
22
|
+
},
|
|
23
|
+
"roles": [
|
|
24
|
+
"test-role-1",
|
|
25
|
+
"test-role-2",
|
|
26
|
+
"test-admin-role"
|
|
27
|
+
],
|
|
28
|
+
"group": {
|
|
29
|
+
"name": "test-group"
|
|
30
|
+
},
|
|
31
|
+
"clientScope": {
|
|
32
|
+
"name": "test-scope"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const http = require('http');
|
|
3
|
+
const https = require('https');
|
|
4
|
+
|
|
5
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'test';
|
|
6
|
+
process.env.PROPERTIES_PATH = path.join(__dirname, 'config');
|
|
7
|
+
|
|
8
|
+
const { conf } = require('propertiesmanager');
|
|
9
|
+
const keycloakManager = require('keycloak-api-manager');
|
|
10
|
+
const { TEST_REALM } = require('./testConfig');
|
|
11
|
+
|
|
12
|
+
function requestAdmin(baseUrl, token, apiPath, method = 'GET', body) {
|
|
13
|
+
const url = new URL(apiPath, baseUrl);
|
|
14
|
+
const transport = url.protocol === 'https:' ? https : http;
|
|
15
|
+
const payload = body ? JSON.stringify(body) : null;
|
|
16
|
+
|
|
17
|
+
const options = {
|
|
18
|
+
method,
|
|
19
|
+
headers: {
|
|
20
|
+
Accept: 'application/json',
|
|
21
|
+
Authorization: `Bearer ${token}`,
|
|
22
|
+
...(payload ? { 'Content-Type': 'application/json' } : {}),
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
const req = transport.request(url, options, (res) => {
|
|
28
|
+
let data = '';
|
|
29
|
+
res.on('data', (chunk) => {
|
|
30
|
+
data += chunk;
|
|
31
|
+
});
|
|
32
|
+
res.on('end', () => {
|
|
33
|
+
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
34
|
+
try {
|
|
35
|
+
const result = {
|
|
36
|
+
data: data ? JSON.parse(data) : null,
|
|
37
|
+
statusCode: res.statusCode,
|
|
38
|
+
headers: res.headers,
|
|
39
|
+
};
|
|
40
|
+
resolve(result);
|
|
41
|
+
} catch {
|
|
42
|
+
resolve({
|
|
43
|
+
data: data || null,
|
|
44
|
+
statusCode: res.statusCode,
|
|
45
|
+
headers: res.headers,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
} else {
|
|
49
|
+
const error = new Error(`HTTP ${res.statusCode}: ${data}`);
|
|
50
|
+
error.statusCode = res.statusCode;
|
|
51
|
+
error.response = data;
|
|
52
|
+
reject(error);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
req.on('error', reject);
|
|
58
|
+
if (payload) {
|
|
59
|
+
req.write(payload);
|
|
60
|
+
}
|
|
61
|
+
req.end();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function main() {
|
|
66
|
+
try {
|
|
67
|
+
// Configura keycloak manager
|
|
68
|
+
const keycloakConfig = (conf && conf.keycloak) || {};
|
|
69
|
+
console.log('keycloakConfig baseUrl:', keycloakConfig.baseUrl);
|
|
70
|
+
|
|
71
|
+
if (!keycloakConfig.baseUrl) {
|
|
72
|
+
throw new Error('baseUrl not configured in keycloak config');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
await keycloakManager.configure(keycloakConfig);
|
|
76
|
+
|
|
77
|
+
keycloakManager.setConfig({ realmName: TEST_REALM });
|
|
78
|
+
const token = keycloakManager.getToken();
|
|
79
|
+
const baseUrl = keycloakConfig.baseUrl.endsWith('/') ? keycloakConfig.baseUrl : `${keycloakConfig.baseUrl}/`;
|
|
80
|
+
|
|
81
|
+
console.log('\n=== PROTOCOL MAPPER DIRECT API TEST ===');
|
|
82
|
+
console.log('Base URL:', baseUrl);
|
|
83
|
+
console.log();
|
|
84
|
+
|
|
85
|
+
// 1. Trova il test client
|
|
86
|
+
const clients = await keycloakManager.clients.find({ clientId: 'test-client' });
|
|
87
|
+
if (!clients || !clients.length) {
|
|
88
|
+
console.log('❌ Test client not found');
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
const testClient = clients[0];
|
|
92
|
+
console.log(`✅ Found test client: ${testClient.clientId} (ID: ${testClient.id})\n`);
|
|
93
|
+
|
|
94
|
+
// 2. Prova a creare un protocol mapper con API diretta
|
|
95
|
+
const apiPath = `/admin/realms/${TEST_REALM}/clients/${testClient.id}/protocol-mappers/models`;
|
|
96
|
+
|
|
97
|
+
const protocolMapper = {
|
|
98
|
+
name: `direct-api-test-${Date.now()}`,
|
|
99
|
+
protocol: 'openid-connect',
|
|
100
|
+
protocolMapper: 'oidc-usermodel-attribute-mapper',
|
|
101
|
+
consentRequired: false,
|
|
102
|
+
config: {
|
|
103
|
+
'user.attribute': 'email',
|
|
104
|
+
'claim.name': 'email_test',
|
|
105
|
+
'jsonType.label': 'String',
|
|
106
|
+
'id.token.claim': 'true',
|
|
107
|
+
'access.token.claim': 'true',
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
console.log(`📡 Direct API POST: ${apiPath}`);
|
|
112
|
+
console.log(`Payload: ${JSON.stringify(protocolMapper, null, 2)}\n`);
|
|
113
|
+
|
|
114
|
+
const result = await requestAdmin(
|
|
115
|
+
baseUrl,
|
|
116
|
+
token.accessToken,
|
|
117
|
+
apiPath,
|
|
118
|
+
'POST',
|
|
119
|
+
protocolMapper
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
console.log(`✅ SUCCESS - Status: ${result.statusCode}`);
|
|
123
|
+
console.log(`Location: ${result.headers.location || 'N/A'}\n`);
|
|
124
|
+
|
|
125
|
+
// 3. Verifica che sia stato creato
|
|
126
|
+
const listResult = await requestAdmin(
|
|
127
|
+
baseUrl,
|
|
128
|
+
token.accessToken,
|
|
129
|
+
apiPath,
|
|
130
|
+
'GET'
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
const createdMapper = listResult.data?.find(m => m.name === protocolMapper.name);
|
|
134
|
+
if (createdMapper) {
|
|
135
|
+
console.log(`✅ Mapper verified in list:`);
|
|
136
|
+
console.log(` ID: ${createdMapper.id}`);
|
|
137
|
+
console.log(` Name: ${createdMapper.name}`);
|
|
138
|
+
console.log(` Protocol Mapper: ${createdMapper.protocolMapper}\n`);
|
|
139
|
+
|
|
140
|
+
// Cleanup
|
|
141
|
+
await requestAdmin(
|
|
142
|
+
baseUrl,
|
|
143
|
+
token.accessToken,
|
|
144
|
+
`${apiPath}/${createdMapper.id}`,
|
|
145
|
+
'DELETE'
|
|
146
|
+
);
|
|
147
|
+
console.log('🧹 Cleanup: Mapper deleted\n');
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// 4. Prova con il client manager della libreria
|
|
151
|
+
console.log('=== TESTING THROUGH KEYCLOAK MANAGER ===\n');
|
|
152
|
+
|
|
153
|
+
try {
|
|
154
|
+
await keycloakManager.clients.addProtocolMapper(
|
|
155
|
+
{ id: testClient.id },
|
|
156
|
+
{
|
|
157
|
+
name: `library-test-${Date.now()}`,
|
|
158
|
+
protocol: 'openid-connect',
|
|
159
|
+
protocolMapper: 'oidc-usermodel-attribute-mapper',
|
|
160
|
+
consentRequired: false,
|
|
161
|
+
config: {
|
|
162
|
+
'user.attribute': 'username',
|
|
163
|
+
'claim.name': 'user_name',
|
|
164
|
+
'jsonType.label': 'String',
|
|
165
|
+
'id.token.claim': 'true',
|
|
166
|
+
'access.token.claim': 'true',
|
|
167
|
+
},
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
console.log('✅ SUCCESS through keycloak-api-manager');
|
|
171
|
+
} catch (err) {
|
|
172
|
+
console.log('❌ FAILED through keycloak-api-manager');
|
|
173
|
+
console.log(`Error: ${err.message}\n`);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
console.log('\n=== SUMMARY ===');
|
|
177
|
+
console.log('Direct API: ✅ Works');
|
|
178
|
+
console.log('Library: Check output above');
|
|
179
|
+
|
|
180
|
+
} catch (err) {
|
|
181
|
+
console.error('❌ ERROR:', err.message);
|
|
182
|
+
if (err.response) {
|
|
183
|
+
console.error('Response:', err.response);
|
|
184
|
+
}
|
|
185
|
+
process.exit(1);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
main();
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Keycloak Deployment Setup Guide
|
|
2
|
+
|
|
3
|
+
## Quick Start
|
|
4
|
+
|
|
5
|
+
### Local HTTP (Development)
|
|
6
|
+
```bash
|
|
7
|
+
npm run setup-keycloak
|
|
8
|
+
# Select: 1 (Local)
|
|
9
|
+
# Select: 1 (HTTP)
|
|
10
|
+
# ✓ Keycloak accessible at http://localhost:8080
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Local HTTPS (Production-like)
|
|
14
|
+
```bash
|
|
15
|
+
npm run setup-keycloak
|
|
16
|
+
# Select: 1 (Local)
|
|
17
|
+
# Select: 2 (HTTPS)
|
|
18
|
+
#
|
|
19
|
+
# If certificates exist in test/docker-keycloak/certs:
|
|
20
|
+
# ✓ Script automatically uses them
|
|
21
|
+
#
|
|
22
|
+
# Otherwise, enter certificate path when prompted:
|
|
23
|
+
# Certificate directory path: /path/to/certs
|
|
24
|
+
# (or press Enter to use default location)
|
|
25
|
+
#
|
|
26
|
+
# ✓ Keycloak accessible at https://localhost:8443
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Remote HTTP
|
|
30
|
+
```bash
|
|
31
|
+
npm run setup-keycloak
|
|
32
|
+
# Choose deployment: Remote (auto-selected, no Docker locally)
|
|
33
|
+
# Enable HTTPS: 1 (No - HTTP)
|
|
34
|
+
# Remote host/IP: smart@smart-dell-sml.crs4.it
|
|
35
|
+
# ✓ Keycloak deployed at http://smart-dell-sml.crs4.it:8080
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Remote HTTPS
|
|
39
|
+
```bash
|
|
40
|
+
npm run setup-keycloak
|
|
41
|
+
# Choose deployment: Remote (auto-selected)
|
|
42
|
+
# Enable HTTPS: 2 (Yes - HTTPS)
|
|
43
|
+
# → Certificates automatically loaded from: test/docker-keycloak/certs
|
|
44
|
+
# Remote host/IP: smart@smart-dell-sml.crs4.it
|
|
45
|
+
# ✓ Certificates copied to remote and deployed with HTTPS
|
|
46
|
+
# ✓ Keycloak accessible at https://smart-dell-sml.crs4.it:8443
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Features
|
|
50
|
+
|
|
51
|
+
### ✅ Local Deployment
|
|
52
|
+
- **HTTP Mode**: Development environment, no certificates needed
|
|
53
|
+
- **HTTPS Mode**: Production-like environment using SSL/TLS certificates
|
|
54
|
+
- **Automatic Health Checks**: Waits for Keycloak to be fully ready
|
|
55
|
+
- **Docker Integration**: Uses docker-compose for easy container management
|
|
56
|
+
|
|
57
|
+
### ✅ Remote Deployment via SSH
|
|
58
|
+
- **Automatic File Transfer**: Copies docker-compose files via SCP
|
|
59
|
+
- **Certificate Management**: Copies certificates to remote server if HTTPS enabled
|
|
60
|
+
- **SSH Connectivity**: Verifies SSH connection before deployment
|
|
61
|
+
- **Health Checks**: Confirms Keycloak is running on remote server
|
|
62
|
+
|
|
63
|
+
### ✅ Configuration Management
|
|
64
|
+
- **.env Files**: Auto-generated configuration files
|
|
65
|
+
- **Certificate Mounting**: Automatic mounting of SSL certificates
|
|
66
|
+
- **Hostname Configuration**: Sets proper KEYCLOAK_HOSTNAME for remote servers
|
|
67
|
+
- **Port Configuration**: Supports custom ports for HTTPS
|
|
68
|
+
|
|
69
|
+
## File Structure
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
keycloak-api-manager/
|
|
73
|
+
├── docker-compose.yml # HTTP configuration
|
|
74
|
+
├── docker-compose-https.yml # HTTPS configuration
|
|
75
|
+
├── .env # Generated by setup script (gitignored)
|
|
76
|
+
├── .env.example # Reference configuration
|
|
77
|
+
└── test/
|
|
78
|
+
└── setup-keycloak.js # Interactive setup script
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Certificate Configuration
|
|
82
|
+
|
|
83
|
+
### Default Location
|
|
84
|
+
For local HTTPS deployments, the script automatically searches for certificates in:
|
|
85
|
+
```
|
|
86
|
+
test/docker-keycloak/certs/
|
|
87
|
+
├── keycloak.crt (X.509 certificate)
|
|
88
|
+
└── keycloak.key (Private key)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**If found**: Script uses them automatically ✅
|
|
92
|
+
**If not found**: Script prompts you to enter a custom path
|
|
93
|
+
|
|
94
|
+
The default location allows you to:
|
|
95
|
+
- Generate certificates once and commit them to the repo
|
|
96
|
+
- Run the script without entering certificate path every time
|
|
97
|
+
- Keep certificates organized with the deployment infrastructure
|
|
98
|
+
|
|
99
|
+
### For Remote Deployments - Automatic Certificate Handling
|
|
100
|
+
|
|
101
|
+
When deploying to a remote server with HTTPS, the script **automatically**:
|
|
102
|
+
1. Loads certificates from the local `test/docker-keycloak/certs/` directory
|
|
103
|
+
2. Verifies they exist (fails with clear error if missing)
|
|
104
|
+
3. Copies them to the remote server in `deployment_path/certs/`
|
|
105
|
+
4. Uses them for the HTTPS configuration
|
|
106
|
+
|
|
107
|
+
**No manual prompts** - just ensure you have valid certificates in `test/docker-keycloak/certs/`:
|
|
108
|
+
```bash
|
|
109
|
+
test/docker-keycloak/certs/
|
|
110
|
+
├── keycloak.crt
|
|
111
|
+
└── keycloak.key
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### For Local Deployments - Custom Certificate Path
|
|
115
|
+
|
|
116
|
+
For local HTTPS deployments, certificates are first sought in `test/docker-keycloak/certs/`.
|
|
117
|
+
If not found there, you will be prompted to enter a custom path:
|
|
118
|
+
```bash
|
|
119
|
+
Certificate directory path (or press Enter for default): /path/to/your/certs
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Certificate Files Required
|
|
123
|
+
For HTTPS deployments, ensure the certificate directory contains:
|
|
124
|
+
- `keycloak.crt` - X.509 certificate file
|
|
125
|
+
- `keycloak.key` - Unencrypted private key file
|
|
126
|
+
|
|
127
|
+
Example self-signed certificate generation:
|
|
128
|
+
```bash
|
|
129
|
+
# Generate self-signed certificate for testing
|
|
130
|
+
openssl req -x509 -newkey rsa:2048 -keyout keycloak.key \
|
|
131
|
+
-out keycloak.crt -days 365 -nodes \
|
|
132
|
+
-subj "/CN=keycloak.test/O=Test/C=US"
|
|
133
|
+
|
|
134
|
+
# Place in the default location
|
|
135
|
+
mkdir -p test/docker-keycloak/certs
|
|
136
|
+
cp keycloak.crt keycloak.key test/docker-keycloak/certs/
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Configuration Details
|
|
140
|
+
|
|
141
|
+
### Environment Variables
|
|
142
|
+
|
|
143
|
+
**HTTP Version**:
|
|
144
|
+
- `KEYCLOAK_HOSTNAME`: Hostname for Keycloak (localhost for local, hostname for remote)
|
|
145
|
+
|
|
146
|
+
**HTTPS Version**:
|
|
147
|
+
- `KEYCLOAK_CERT_PATH`: Path to certificate directory
|
|
148
|
+
- `KEYCLOAK_HOSTNAME`: Hostname for Keycloak (must match certificate CN for production)
|
|
149
|
+
|
|
150
|
+
### Docker Compose Files
|
|
151
|
+
|
|
152
|
+
**docker-compose.yml** (HTTP):
|
|
153
|
+
```yaml
|
|
154
|
+
- Image: keycloak/keycloak:latest
|
|
155
|
+
- Ports: 8080 (HTTP)
|
|
156
|
+
- Database: In-memory (KC_DB: dev-mem)
|
|
157
|
+
- Admin Creds: admin:admin
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**docker-compose-https.yml** (HTTPS):
|
|
161
|
+
```yaml
|
|
162
|
+
- Image: keycloak/keycloak:latest
|
|
163
|
+
- Ports: 8080 (HTTP), 8443 (HTTPS)
|
|
164
|
+
- Certificates: Mounted from KEYCLOAK_CERT_PATH
|
|
165
|
+
- Admin Creds: admin:admin
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Troubleshooting
|
|
169
|
+
|
|
170
|
+
### SSH Connection Failed
|
|
171
|
+
```bash
|
|
172
|
+
# Verify SSH access
|
|
173
|
+
ssh -v smart@smart-dell-sml.crs4.it 'echo OK'
|
|
174
|
+
|
|
175
|
+
# Check SSH key permissions
|
|
176
|
+
ls -la ~/.ssh/id_ed25519
|
|
177
|
+
chmod 600 ~/.ssh/id_ed25519
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### HTTPS Certificate Issues
|
|
181
|
+
```bash
|
|
182
|
+
# Verify certificate files exist
|
|
183
|
+
ls -la /path/to/certs/keycloak.crt
|
|
184
|
+
ls -la /path/to/certs/keycloak.key
|
|
185
|
+
|
|
186
|
+
# Test certificate validity
|
|
187
|
+
openssl x509 -in keycloak.crt -text -noout
|
|
188
|
+
|
|
189
|
+
# For browser access with self-signed cert:
|
|
190
|
+
# - Use curl -k (insecure flag)
|
|
191
|
+
# - Add browser exception for the domain
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Keycloak Takes Too Long to Start
|
|
195
|
+
```bash
|
|
196
|
+
# Check container logs
|
|
197
|
+
docker-compose -f docker-compose.yml logs -f
|
|
198
|
+
|
|
199
|
+
# Or remotely
|
|
200
|
+
ssh smart@smart-dell-sml.crs4.it 'cd /home/smart/keycloak && docker-compose -f docker-compose-https.yml logs -f'
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Port Already in Use
|
|
204
|
+
```bash
|
|
205
|
+
# Check what's using the port
|
|
206
|
+
lsof -i :8080
|
|
207
|
+
lsof -i :8443
|
|
208
|
+
|
|
209
|
+
# Kill existing container
|
|
210
|
+
docker-compose down
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Running Tests with Different Deployments
|
|
214
|
+
|
|
215
|
+
After deploying Keycloak with the setup script, run tests:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
# Tests will automatically detect and connect to Keycloak
|
|
219
|
+
npm test
|
|
220
|
+
|
|
221
|
+
# The test setup handles:
|
|
222
|
+
# - Local HTTP: Connects to http://localhost:8080
|
|
223
|
+
# - Local HTTPS: Connects to https://localhost:8443
|
|
224
|
+
# - Remote: Can be configured in test/config/default.json
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Advanced Configuration
|
|
228
|
+
|
|
229
|
+
### Custom Keycloak Version
|
|
230
|
+
Edit `docker-compose.yml` or `docker-compose-https.yml`:
|
|
231
|
+
```yaml
|
|
232
|
+
services:
|
|
233
|
+
keycloak:
|
|
234
|
+
image: keycloak/keycloak:25.0 # Change version here
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Custom Database
|
|
238
|
+
Edit docker-compose files, change `KC_DB`:
|
|
239
|
+
```yaml
|
|
240
|
+
environment:
|
|
241
|
+
KC_DB: postgres # Instead of dev-mem
|
|
242
|
+
KC_DB_URL_HOST: postgres-host
|
|
243
|
+
KC_DB_URL_PORT: 5432
|
|
244
|
+
KC_DB_USERNAME: keycloak
|
|
245
|
+
KC_DB_PASSWORD: password
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Additional Environment Variables
|
|
249
|
+
Add to `.env`:
|
|
250
|
+
```bash
|
|
251
|
+
KC_LOG_LEVEL=INFO
|
|
252
|
+
KC_METRICS_ENABLED=true
|
|
253
|
+
KC_CACHE=ispn
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Support
|
|
257
|
+
|
|
258
|
+
For issues or questions:
|
|
259
|
+
- Check Docker logs: `docker-compose logs -f`
|
|
260
|
+
- Check Keycloak admin console: http://localhost:8080
|
|
261
|
+
- Review certificates: `openssl x509 -in keycloak.crt -text -noout`
|
|
262
|
+
- Test connectivity: `curl -k https://localhost:8443/health/ready`
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# This directory is for storing SSL certificates
|
|
2
|
+
# Place your keycloak.crt and keycloak.key files here
|
|
3
|
+
# They will NOT be committed to git (see .gitignore)
|
|
4
|
+
#
|
|
5
|
+
# Example:
|
|
6
|
+
# cp /path/to/your/keycloak.crt keycloak.crt
|
|
7
|
+
# cp /path/to/your/keycloak.key keycloak.key
|