Skip to content

Commit 6cb61ce

Browse files
feat: support signed JWT client authentication (#1250)
Signed-off-by: Tuan Kiet Truong <[email protected]>
1 parent 0f2af8c commit 6cb61ce

File tree

9 files changed

+209
-27
lines changed

9 files changed

+209
-27
lines changed

docs/index.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ If you are using the legacy Wildfly distribution of Keycloak, you will need to s
1616

1717
## Keycloak Setup
1818

19-
This Terraform provider can be configured to use the [client credentials](https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/)
20-
or [password](https://www.oauth.com/oauth2-servers/access-tokens/password-grant/) grant types. If you aren't
19+
This Terraform provider can be configured to use the [client credentials](https://www.oauth.com/oauth2-servers/access-tokens/client-credentials/) or [password](https://www.oauth.com/oauth2-servers/access-tokens/password-grant/) grant types. If you aren't
2120
sure which to use, the client credentials grant is recommended, as it was designed for machine to machine authentication.
2221

2322
### Client Credentials Grant Setup (recommended)
@@ -31,6 +30,18 @@ like to manage your entire Keycloak instance, or in any other realm if you only
3130
1. Set `Service Accounts Enabled` to `ON`.
3231
1. Grant required roles for managing Keycloak via the `Service Account Roles` tab in the client you created in step 1, see [Assigning Roles](#assigning-roles) section below.
3332

33+
Out of the many [authentication methods](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication) of the client credentials grant type, this Terraform provider supports the authentication using the `client secret` or the `private key signed JWT`.
34+
35+
#### Client Secret Authentication Type Setup
36+
37+
This is the default client authentication type and requires no further step.
38+
39+
#### Private Key Signed JWT Authentication Type Setup
40+
These steps assume that you have already followed the steps for the client credentials grant and have created the client `terraform`.
41+
42+
1. Change the `Client authenticator` in the `Credentials`tab to `Signed JWT`.
43+
1. Generate or import a key pair via `Keys`. In case the key pair is generated by the Keycloak server, a keystore file would be downloaded and you have to extract the private key and keep it safe.
44+
3445
### Password Grant Setup
3546

3647
These steps will assume that you are using the `admin-cli` client, which is already correctly configured for this type
@@ -52,7 +63,7 @@ account within the `foo` realm.
5263
the realm clients to a user or service account within the `master` realm. For example, given a Keycloak instance with realms
5364
`master`, `foo`, and `bar`, assign the `create-client` client role from the clients `master-realm`, `foo-realm`, and `bar-realm`.
5465

55-
## Example Usage (client credentials grant)
66+
## Example Usage (client credentials grant - client secret)
5667

5768
```hcl
5869
provider "keycloak" {
@@ -62,6 +73,16 @@ provider "keycloak" {
6273
}
6374
```
6475

76+
## Example Usage (client credentials grant - private key signed JWT)
77+
78+
```hcl
79+
provider "keycloak" {
80+
client_id = "terraform"
81+
jwt_signing_key = "<pem-formatted-private-key>"
82+
url = "http://localhost:8080"
83+
}
84+
```
85+
6586
## Example Usage (password grant)
6687

6788
```hcl
@@ -82,6 +103,8 @@ The following arguments are supported:
82103
- `client_secret` - (Optional) The secret for the client used by the provider for authentication via the client credentials grant. This can be found or changed using the "Credentials" tab in the client settings. Defaults to the environment variable `KEYCLOAK_CLIENT_SECRET`. This attribute is required when using the client credentials grant, and cannot be set when using the password grant.
83104
- `username` - (Optional) The username of the user used by the provider for authentication via the password grant. Defaults to the environment variable `KEYCLOAK_USER`. This attribute is required when using the password grant, and cannot be set when using the client credentials grant.
84105
- `password` - (Optional) The password of the user used by the provider for authentication via the password grant. Defaults to the environment variable `KEYCLOAK_PASSWORD`. This attribute is required when using the password grant, and cannot be set when using the client credentials grant.
106+
- `jwt_signing_key` - (Optional) The PEM-formatted private key used by provider to generate a signed JWT for authentication.
107+
- `jwt_signing_alg` - (Optional) The signing algorithm used by provider to generate a signed JWT for authentication. Defaults to `RS256`.
85108
- `realm` - (Optional) The realm used by the provider for authentication. Defaults to the environment variable `KEYCLOAK_REALM`, or `master` if the environment variable is not specified.
86109
- `initial_login` - (Optional) Optionally avoid Keycloak login during provider setup, for when Keycloak itself is being provisioned by terraform. Defaults to true, which is the original method.
87110
- `client_timeout` - (Optional) Sets the timeout of the client when addressing Keycloak, in seconds. Defaults to the environment variable `KEYCLOAK_CLIENT_TIMEOUT`, or `15` if the environment variable is not specified.

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ module github.com/keycloak/terraform-provider-keycloak
22

33
require (
44
dario.cat/mergo v1.0.2
5+
github.com/golang-jwt/jwt/v5 v5.2.2
56
github.com/hashicorp/errwrap v1.1.0
67
github.com/hashicorp/go-cty v1.5.0
78
github.com/hashicorp/go-retryablehttp v0.7.8

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
3535
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
3636
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
3737
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
38+
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
39+
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
3840
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
3941
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw=
4042
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=

keycloak/keycloak_client.go

Lines changed: 103 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,12 @@ import (
1616
"strings"
1717
"time"
1818

19+
"github.com/hashicorp/go-uuid"
1920
"github.com/hashicorp/go-version"
2021
"github.com/hashicorp/terraform-plugin-log/tflog"
2122

23+
"github.com/golang-jwt/jwt/v5"
24+
2225
"golang.org/x/net/publicsuffix"
2326

2427
"github.com/hashicorp/go-retryablehttp"
@@ -38,19 +41,22 @@ type KeycloakClient struct {
3841
}
3942

4043
type ClientCredentials struct {
41-
ClientId string
42-
ClientSecret string
43-
Username string
44-
Password string
45-
GrantType string
46-
AccessToken string `json:"access_token"`
47-
RefreshToken string `json:"refresh_token"`
48-
TokenType string `json:"token_type"`
44+
ClientId string
45+
ClientSecret string
46+
JWTSigningKey string
47+
JWTSigningAlg string
48+
Username string
49+
Password string
50+
GrantType string
51+
AccessToken string `json:"access_token"`
52+
RefreshToken string `json:"refresh_token"`
53+
TokenType string `json:"token_type"`
4954
}
5055

5156
const (
52-
apiUrl = "/admin"
53-
tokenUrl = "%s/realms/%s/protocol/openid-connect/token"
57+
apiUrl = "/admin"
58+
issuerUrl = "%s/realms/%s"
59+
tokenUrl = "%s/realms/%s/protocol/openid-connect/token"
5460
)
5561

5662
// https://access.redhat.com/articles/2342881
@@ -60,20 +66,23 @@ var redHatSSO7VersionMap = map[int]string{
6066
4: "9.0.17",
6167
}
6268

63-
func NewKeycloakClient(ctx context.Context, url, basePath, clientId, clientSecret, realm, username, password string, initialLogin bool, clientTimeout int, caCert string, tlsInsecureSkipVerify bool, userAgent string, redHatSSO bool, additionalHeaders map[string]string) (*KeycloakClient, error) {
69+
func NewKeycloakClient(ctx context.Context, url, basePath, clientId, clientSecret, realm, username, password, jwtSigningAlg, jwtSigningKey string, initialLogin bool, clientTimeout int, caCert string, tlsInsecureSkipVerify bool, userAgent string, redHatSSO bool, additionalHeaders map[string]string) (*KeycloakClient, error) {
6470
clientCredentials := &ClientCredentials{
65-
ClientId: clientId,
66-
ClientSecret: clientSecret,
71+
ClientId: clientId,
72+
ClientSecret: clientSecret,
73+
JWTSigningKey: jwtSigningKey,
74+
JWTSigningAlg: jwtSigningAlg,
6775
}
76+
6877
if password != "" && username != "" {
6978
clientCredentials.Username = username
7079
clientCredentials.Password = password
7180
clientCredentials.GrantType = "password"
72-
} else if clientSecret != "" {
81+
} else if clientSecret != "" || jwtSigningKey != "" {
7382
clientCredentials.GrantType = "client_credentials"
7483
} else {
7584
if initialLogin {
76-
return nil, fmt.Errorf("must specify client id, username and password for password grant, or client id and secret for client credentials grant")
85+
return nil, fmt.Errorf("must specify client id, username and password for password grant, either client id and client secret or JWT Signing Key for client credentials grant")
7786
} else {
7887
tflog.Warn(ctx, "missing required keycloak credentials, but proceeding anyways as initial_login is false")
7988
}
@@ -113,7 +122,10 @@ func NewKeycloakClient(ctx context.Context, url, basePath, clientId, clientSecre
113122

114123
func (keycloakClient *KeycloakClient) login(ctx context.Context) error {
115124
accessTokenUrl := fmt.Sprintf(tokenUrl, keycloakClient.baseUrl, keycloakClient.realm)
116-
accessTokenData := keycloakClient.getAuthenticationFormData()
125+
accessTokenData, err := keycloakClient.getAuthenticationFormData(ctx, accessTokenUrl)
126+
if err != nil {
127+
return err
128+
}
117129

118130
tflog.Debug(ctx, "Login request", map[string]interface{}{
119131
"request": accessTokenData.Encode(),
@@ -204,7 +216,10 @@ func (keycloakClient *KeycloakClient) login(ctx context.Context) error {
204216

205217
func (keycloakClient *KeycloakClient) Refresh(ctx context.Context) error {
206218
refreshTokenUrl := fmt.Sprintf(tokenUrl, keycloakClient.baseUrl, keycloakClient.realm)
207-
refreshTokenData := keycloakClient.getAuthenticationFormData()
219+
refreshTokenData, err := keycloakClient.getAuthenticationFormData(ctx, refreshTokenUrl)
220+
if err != nil {
221+
return err
222+
}
208223

209224
tflog.Debug(ctx, "Refresh request", map[string]interface{}{
210225
"request": refreshTokenData.Encode(),
@@ -258,7 +273,7 @@ func (keycloakClient *KeycloakClient) Refresh(ctx context.Context) error {
258273
return nil
259274
}
260275

261-
func (keycloakClient *KeycloakClient) getAuthenticationFormData() url.Values {
276+
func (keycloakClient *KeycloakClient) getAuthenticationFormData(ctx context.Context, kc_url string) (url.Values, error) {
262277
authenticationFormData := url.Values{}
263278
authenticationFormData.Set("client_id", keycloakClient.clientCredentials.ClientId)
264279
authenticationFormData.Set("grant_type", keycloakClient.clientCredentials.GrantType)
@@ -272,10 +287,26 @@ func (keycloakClient *KeycloakClient) getAuthenticationFormData() url.Values {
272287
}
273288

274289
} else if keycloakClient.clientCredentials.GrantType == "client_credentials" {
275-
authenticationFormData.Set("client_secret", keycloakClient.clientCredentials.ClientSecret)
290+
if keycloakClient.clientCredentials.JWTSigningKey != "" {
291+
signedJWT, err := newSignedJWT(
292+
ctx,
293+
fmt.Sprintf(issuerUrl, keycloakClient.baseUrl, keycloakClient.realm),
294+
keycloakClient.clientCredentials.ClientId,
295+
keycloakClient.clientCredentials.JWTSigningAlg,
296+
keycloakClient.clientCredentials.JWTSigningKey,
297+
)
298+
if err != nil {
299+
return nil, fmt.Errorf("failed to create signed JWT: %v", err)
300+
}
301+
authenticationFormData.Set("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer")
302+
authenticationFormData.Set("client_assertion", signedJWT)
303+
} else {
304+
authenticationFormData.Set("client_secret", keycloakClient.clientCredentials.ClientSecret)
305+
}
306+
276307
}
277308

278-
return authenticationFormData
309+
return authenticationFormData, nil
279310
}
280311

281312
func (keycloakClient *KeycloakClient) addRequestHeaders(request *http.Request) {
@@ -556,3 +587,55 @@ func newHttpClient(tlsInsecureSkipVerify bool, clientTimeout int, caCert string)
556587

557588
return httpClient, nil
558589
}
590+
591+
func newSignedJWT(ctx context.Context, url, clientId, alg, jwtSigningKey string) (string, error) {
592+
// Create the Claims
593+
jti, err := uuid.GenerateUUID()
594+
if err != nil {
595+
return "", fmt.Errorf("failed to generate JWT ID: %v", err)
596+
}
597+
598+
claims := jwt.MapClaims{
599+
"jti": jti,
600+
"iss": clientId,
601+
"sub": clientId,
602+
"aud": url,
603+
"exp": jwt.NewNumericDate(time.Now().Add(time.Second * 60)),
604+
"iat": jwt.NewNumericDate(time.Now()),
605+
}
606+
607+
signingMethod := jwt.GetSigningMethod(alg)
608+
if signingMethod == nil {
609+
return "", fmt.Errorf("unsupported signing method: %s", alg)
610+
}
611+
612+
// Create the token
613+
token := jwt.NewWithClaims(jwt.GetSigningMethod(alg), claims)
614+
615+
var key any
616+
if _, isRsa := signingMethod.(*jwt.SigningMethodRSA); isRsa {
617+
key, err = jwt.ParseRSAPrivateKeyFromPEM([]byte(jwtSigningKey))
618+
} else if _, isEcdsa := signingMethod.(*jwt.SigningMethodECDSA); isEcdsa {
619+
key, err = jwt.ParseECPrivateKeyFromPEM([]byte(jwtSigningKey))
620+
} else if _, isEd25519 := signingMethod.(*jwt.SigningMethodEd25519); isEd25519 {
621+
key, err = jwt.ParseEdPrivateKeyFromPEM([]byte(jwtSigningKey))
622+
} else {
623+
err = fmt.Errorf("unsupported signing method: %s", signingMethod)
624+
}
625+
626+
if err != nil {
627+
return "", err
628+
}
629+
tokenString, err := token.SignedString(key)
630+
if err != nil {
631+
fmt.Println(err)
632+
return "", err
633+
}
634+
635+
jwtClientAssertionArgs := map[string]any{
636+
"jti": jti,
637+
}
638+
tflog.Debug(ctx, "Generated client_assertion", jwtClientAssertionArgs)
639+
640+
return tokenString, nil
641+
}

keycloak/keycloak_client_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package keycloak
22

33
import (
44
"context"
5-
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
65
"os"
76
"strconv"
87
"testing"
8+
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
910
)
1011

1112
var requiredEnvironmentVariables = []string{
@@ -48,7 +49,7 @@ func TestAccKeycloakApiClientRefresh(t *testing.T) {
4849
t.Fatal("KEYCLOAK_CLIENT_TIMEOUT must be an integer")
4950
}
5051

51-
keycloakClient, err := NewKeycloakClient(ctx, os.Getenv("KEYCLOAK_URL"), "", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), os.Getenv("KEYCLOAK_USER"), os.Getenv("KEYCLOAK_PASSWORD"), true, clientTimeout, "", false, "", false, map[string]string{
52+
keycloakClient, err := NewKeycloakClient(ctx, os.Getenv("KEYCLOAK_URL"), "", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), os.Getenv("KEYCLOAK_USER"), os.Getenv("KEYCLOAK_PASSWORD"), "", "", true, clientTimeout, "", false, "", false, map[string]string{
5253
"foo": "bar",
5354
})
5455
if err != nil {

provider/provider.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,19 @@ func KeycloakProvider(client *keycloak.KeycloakClient) *schema.Provider {
149149
Type: schema.TypeString,
150150
DefaultFunc: schema.EnvDefaultFunc("KEYCLOAK_PASSWORD", nil),
151151
},
152+
"jwt_signing_alg": {
153+
Optional: true,
154+
Type: schema.TypeString,
155+
Description: "The algorithm used to sign the JWT when client-jwt is used. Defaults to RS256.",
156+
Default: "RS256",
157+
},
158+
"jwt_signing_key": {
159+
Optional: true,
160+
Type: schema.TypeString,
161+
Description: "The PEM-formatted private key used to sign the JWT when client-jwt is used.",
162+
Sensitive: true,
163+
DefaultFunc: schema.EnvDefaultFunc("KEYCLOAK_JWT_SIGNING_KEY", nil),
164+
},
152165
"realm": {
153166
Optional: true,
154167
Type: schema.TypeString,
@@ -216,6 +229,8 @@ func KeycloakProvider(client *keycloak.KeycloakClient) *schema.Provider {
216229
clientSecret := data.Get("client_secret").(string)
217230
username := data.Get("username").(string)
218231
password := data.Get("password").(string)
232+
jwtSigningAlg := data.Get("jwt_signing_alg").(string)
233+
jwtSigningKey := data.Get("jwt_signing_key").(string)
219234
realm := data.Get("realm").(string)
220235
initialLogin := data.Get("initial_login").(bool)
221236
clientTimeout := data.Get("client_timeout").(int)
@@ -231,7 +246,7 @@ func KeycloakProvider(client *keycloak.KeycloakClient) *schema.Provider {
231246

232247
userAgent := fmt.Sprintf("HashiCorp Terraform/%s (+https://www.terraform.io) Terraform Plugin SDK/%s", provider.TerraformVersion, meta.SDKVersionString())
233248

234-
keycloakClient, err := keycloak.NewKeycloakClient(ctx, url, basePath, clientId, clientSecret, realm, username, password, initialLogin, clientTimeout, rootCaCertificate, tlsInsecureSkipVerify, userAgent, redHatSSO, additionalHeaders)
249+
keycloakClient, err := keycloak.NewKeycloakClient(ctx, url, basePath, clientId, clientSecret, realm, username, password, jwtSigningAlg, jwtSigningKey, initialLogin, clientTimeout, rootCaCertificate, tlsInsecureSkipVerify, userAgent, redHatSSO, additionalHeaders)
235250
if err != nil {
236251
diags = append(diags, diag.Diagnostic{
237252
Severity: diag.Error,
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package provider
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
)
11+
12+
func TestAccKeycloakProvider_signedJWT(t *testing.T) {
13+
t.Parallel()
14+
jwtSigningKey := "-----BEGIN PRIVATE KEY-----\r\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDEgtQWZtM/nSIX\r\npuJ9aJ9elurICPD1FEKOaIQBg6MihHYDDQxkIT93FkGLTRPMNFNgSXUKKj7IW9Ih\r\nxpv7v4ltsRaNmT0n2CFmVDGQI9404M1vz7V6Gj70feHWtcwzF42kvsCMEETwsW0j\r\nkOSX2RXun7RPaLSfXavki0w1ql3/nKVxQMuFgmMZrQzpIGh/EPpRjEWgL9HRYlp4\r\nX5wbW/GGzDuUldJoJBWhBWb8uOVSJcmXcgZ45k5LxkGTjTXPlgYJorVSdS8bkoBx\r\nBRa3COwilTwUFiBNna4HwnMmLFiKEYMhCGO+HvyFm4AKzhhShHQSm8VrISWsD05F\r\ng0Uo/LEHAgMBAAECggEANe9gjat4NKAIoOw9gsUp5LjQRMnrdKC0aci23oGGT22C\r\nxHCa44qalDFoGPc1RVlhPu66cGlK5QwKnxmXa1/VNOWjdobGGb8A38ig99pYXTQM\r\nPrGIMjSs7cb1Ksyn+KfwyPRP/cFjYpqYBWh5zVGYau+rehYXaRw5FxfCeYJCnWqi\r\ndPKZPb8num2NOr4ts3zFGbf7Ni47k4Ma07alEuAi9Whi+ONagFI9P0sgyYl63Zen\r\nJTshWkKNuljkvKfNS7a8PGkSar2iYDJE3GkfiGP2sOJzpvPDQbWDhZMFhlHzS9hK\r\n8BELVcR/qIaSlXY4AekeQTONaXOwwX9Fj/7fKMVUZQKBgQDmiGuaAfDGfAY3uO73\r\n6keESta35yoFz2IarzTW2GhJagNfJX7wUOLvjPEmgwI+QU4PA9hisEePSyjHaz4V\r\nRLn47pmV9aQDwKfKjZdLL8G63gMbhWup5keTKpXU8LpWWiTK0C9ouV/M2HO2IymC\r\n0dv1RHaVpBhOSMbxX26TQ8O+3QKBgQDaOEEXaEe7uAqIlj0W7HbZevaGLz4PVE17\r\nYqWBD50T+hiXTgCRnOee5sQPVjUrmBjk7QQ8sBentoVlL418XFH1MY+IcNy9B7/d\r\nKpxpwPCEjJchFdKAZvDs9QFdf2VOAvxM1HAZM01qdGMrq/wXLTMHPnB3Os3cTWaB\r\ncWgvcvInMwKBgQCp0pkhjIhoTvjtl4hCjQ0+ATuHofys5waoDaVpF2ZLnpL5Rk/q\r\njEuAmF0VN7ExVz4/hV+j46PzhTR3IyNK26P8Ixh1Bc1bDlMMvZ1UP8wA8odrgK+9\r\nKuxTFy3k/ajm7+TmmtIx3U0bQ+CJrgFoY1wbo+GPfqCBGs+jA+AbD/Jk6QKBgG3F\r\nVID41PTJ/Ip+wNYyNwrpfu86/oXpi1xg4A5PE14ENbCO7VxSSHU3cjKg0/hM92DZ\r\nFYONtSiJeQrQY+TF7/heaOxikbeJGWugzrOn+ZVDv5ZGCvDKV7FrAbfNqOEYQWBI\r\nkOcsVmoRh/1k81eZRg0DzME9VGbYjJLawGT19nffAoGADDoFR5YT3Hj1gi4xrCv7\r\nUsdorG0VqXJNpkFEv53MHUO5zZocd9Iv7zcQ+weTDlJE38nTEixBcfXHzyPcY8IW\r\nrRMDTOcfL/vPSADig7pRyLankKEtaS2QE2BKwDP7hkoQMkllVDe4OPflghmCclYd\r\nDamFJ27n4ONrNiy142vb+MY=\r\n-----END PRIVATE KEY-----"
15+
testAccProvider = KeycloakProvider(keycloakClient)
16+
17+
os.Setenv("KEYCLOAK_CLIENT_ID", "terraform-jwt")
18+
os.Setenv("KEYCLOAK_JWT_SIGNING_KEY", jwtSigningKey)
19+
20+
defer func() {
21+
os.Setenv("KEYCLOAK_CLIENT_ID", "terraform")
22+
os.Unsetenv("KEYCLOAK_JWT_SIGNING_KEY")
23+
}()
24+
25+
clientId := acctest.RandomWithPrefix("tf-acc")
26+
resource.Test(t, resource.TestCase{
27+
ProviderFactories: map[string]func() (*schema.Provider, error){
28+
"keycloak": func() (*schema.Provider, error) {
29+
return testAccProvider, nil
30+
},
31+
},
32+
PreCheck: func() { testAccPreCheck(t) },
33+
Steps: []resource.TestStep{
34+
{
35+
Config: testKeycloakOpenidClient_basic(clientId),
36+
},
37+
},
38+
})
39+
}

provider/provider_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func init() {
5858
}
5959
}
6060

61-
keycloakClient, err = keycloak.NewKeycloakClient(testCtx, os.Getenv("KEYCLOAK_URL"), "", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), "", "", true, 120, "", false, userAgent, false, map[string]string{
61+
keycloakClient, err = keycloak.NewKeycloakClient(testCtx, os.Getenv("KEYCLOAK_URL"), "", os.Getenv("KEYCLOAK_CLIENT_ID"), os.Getenv("KEYCLOAK_CLIENT_SECRET"), os.Getenv("KEYCLOAK_REALM"), "", "", "", "", true, 120, "", false, userAgent, false, map[string]string{
6262
"foo": "bar",
6363
})
6464
if err != nil {

0 commit comments

Comments
 (0)