Skip to content

Commit df8dd7a

Browse files
Adds realm import functionality
Enables importing a Keycloak realm from a JSON file. This feature allows users to pre-configure Keycloak instances with specific realm settings, clients, and users, simplifying the setup and configuration process. A new test has been added to verify the import functionality.
1 parent 642c5e9 commit df8dd7a

File tree

4 files changed

+97
-7
lines changed

4 files changed

+97
-7
lines changed

src/Testcontainers.Keycloak/KeycloakBuilder.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ public KeycloakBuilder WithPassword(string password)
6060
.WithEnvironment("KEYCLOAK_ADMIN_PASSWORD", password);
6161
}
6262

63+
/// <summary>
64+
/// Sets the Keycloak to Import Realm file.
65+
/// </summary>
66+
/// <param name="path">The path to realm-export.json</param>
67+
/// <returns>A configured instance of <see cref="KeycloakBuilder" />.</returns>
68+
public KeycloakBuilder WithRealm(string path)
69+
{
70+
return Clone(new ContainerConfiguration(command: new AppendEnumerable<string>(["--import-realm"])))
71+
.WithBindMount(path, "/opt/keycloak/data/import/realm-export.json");
72+
}
73+
6374
/// <inheritdoc />
6475
public override KeycloakContainer Build()
6576
{

tests/Testcontainers.Keycloak.Tests/KeycloakContainerTest.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
using System.IO;
2+
using System.Linq;
3+
14
namespace Testcontainers.Keycloak;
25

36
public abstract class KeycloakContainerTest : IAsyncLifetime
@@ -85,4 +88,28 @@ public KeycloakV26Configuration()
8588
{
8689
}
8790
}
91+
92+
[UsedImplicitly]
93+
public sealed class KeycloakRealmConfiguration : KeycloakContainerTest
94+
{
95+
public KeycloakRealmConfiguration()
96+
: base(new KeycloakBuilder().WithRealm(Path.GetFullPath("realm-export.json")).Build())
97+
{
98+
}
99+
100+
[Fact]
101+
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
102+
public async Task RealmIsImported()
103+
{
104+
// Given
105+
var keycloakClient = new KeycloakClient(_keycloakContainer.GetBaseAddress(), KeycloakBuilder.DefaultUsername, KeycloakBuilder.DefaultPassword);
106+
107+
// When
108+
var realms = await keycloakClient.GetRealmsAsync("master", TestContext.Current.CancellationToken)
109+
.ConfigureAwait(true);
110+
111+
// Then
112+
Assert.True(realms.Count() == 2);
113+
}
114+
}
88115
}

tests/Testcontainers.Keycloak.Tests/Testcontainers.Keycloak.Tests.csproj

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@
66
<OutputType>Exe</OutputType>
77
</PropertyGroup>
88
<ItemGroup>
9-
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
10-
<PackageReference Include="coverlet.collector"/>
11-
<PackageReference Include="xunit.runner.visualstudio"/>
12-
<PackageReference Include="xunit.v3"/>
13-
<PackageReference Include="Keycloak.Net.Core"/>
9+
<PackageReference Include="Microsoft.NET.Test.Sdk" />
10+
<PackageReference Include="coverlet.collector" />
11+
<PackageReference Include="xunit.runner.visualstudio" />
12+
<PackageReference Include="xunit.v3" />
13+
<PackageReference Include="Keycloak.Net.Core" />
1414
</ItemGroup>
1515
<ItemGroup>
16-
<ProjectReference Include="../../src/Testcontainers.Keycloak/Testcontainers.Keycloak.csproj"/>
17-
<ProjectReference Include="../Testcontainers.Commons/Testcontainers.Commons.csproj"/>
16+
<ProjectReference Include="../../src/Testcontainers.Keycloak/Testcontainers.Keycloak.csproj" />
17+
<ProjectReference Include="../Testcontainers.Commons/Testcontainers.Commons.csproj" />
18+
</ItemGroup>
19+
<ItemGroup>
20+
<None Update="realm-export.json">
21+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
22+
</None>
1823
</ItemGroup>
1924
</Project>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"realm": "test-realm",
3+
"enabled": true,
4+
"clients": [
5+
{
6+
"clientId": "test-client",
7+
"secret": "secret",
8+
"enabled": true,
9+
"protocol": "openid-connect",
10+
"publicClient": false,
11+
"directAccessGrantsEnabled": true,
12+
"serviceAccountsEnabled": true,
13+
"name": "Test Client",
14+
"attributes": {
15+
"jwt.client.claims": "true"
16+
},
17+
"protocolMappers": [
18+
{
19+
"name": "audience",
20+
"protocol": "openid-connect",
21+
"protocolMapper": "oidc-audience-mapper",
22+
"consentRequired": false,
23+
"config": {
24+
"included.client.audience": "test-client",
25+
"id.token.claim": "true",
26+
"access.token.claim": "true"
27+
}
28+
}
29+
]
30+
}
31+
],
32+
"users": [
33+
{
34+
"username": "admin",
35+
"enabled": true,
36+
"emailVerified": true,
37+
"credentials": [
38+
{
39+
"type": "password",
40+
"value": "admin",
41+
"temporary": false
42+
}
43+
],
44+
"email": "admin@example.com"
45+
}
46+
]
47+
}

0 commit comments

Comments
 (0)