Skip to content

Commit 0e128b4

Browse files
authored
feat: keycloak OIDC auth provider (#2033) (#2101)
1 parent 4888ca5 commit 0e128b4

11 files changed

Lines changed: 439 additions & 193 deletions

aspell_custom.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ PC
3535
AuthConfig
3636
Cognito
3737
nutanix
38+
Keycloak
39+
OIDC

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.25.0
44

55
require (
66
github.com/ghodss/yaml v1.0.0
7+
github.com/go-viper/mapstructure/v2 v2.4.0
78
github.com/hashicorp/go-version v1.6.0
89
github.com/hashicorp/terraform-plugin-sdk v1.17.2
910
github.com/rancher/norman v0.8.4

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,10 +1723,10 @@ github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZ
17231723
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
17241724
github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M=
17251725
github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8=
1726-
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
1727-
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
17281726
github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k=
17291727
github.com/go-text/typesetting-utils v0.0.0-20230616150549-2a7df14b6a22/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
1728+
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
1729+
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
17301730
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
17311731
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
17321732
github.com/goccmack/gocc v0.0.0-20230228185258-2292f9e40198/go.mod h1:DTh/Y2+NbnOVVoypCCQrovMPDKUGp4yZpSbWg5D0XIM=

rancher2/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1227,6 +1227,8 @@ func getAuthConfigObject(kind string) (interface{}, error) {
12271227
return &managementClient.GenericOIDCConfig{}, nil
12281228
case managementClient.CognitoConfigType:
12291229
return &managementClient.CognitoConfig{}, nil
1230+
case managementClient.KeyCloakOIDCConfigType:
1231+
return &managementClient.KeyCloakOIDCConfig{}, nil
12301232
case managementClient.OIDCConfigType:
12311233
return &managementClient.OIDCConfig{}, nil
12321234
case managementClient.OKTAConfigType:

rancher2/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ func Provider() terraform.ResourceProvider {
118118
"rancher2_auth_config_okta": resourceRancher2AuthConfigOKTA(),
119119
"rancher2_auth_config_generic_oidc": resourceRancher2AuthConfigGenericOIDC(),
120120
"rancher2_auth_config_cognito": resourceRancher2AuthConfigCognito(),
121+
"rancher2_auth_config_keycloak_oidc": resourceRancher2AuthConfigKeyCloakOIDC(),
121122
"rancher2_auth_config_openldap": resourceRancher2AuthConfigOpenLdap(),
122123
"rancher2_auth_config_ping": resourceRancher2AuthConfigPing(),
123124
"rancher2_bootstrap": resourceRancher2Bootstrap(),
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package rancher2
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
8+
managementClient "github.com/rancher/rancher/pkg/client/generated/management/v3"
9+
)
10+
11+
func resourceRancher2AuthConfigKeyCloakOIDC() *schema.Resource {
12+
return &schema.Resource{
13+
Create: resourceRancher2AuthConfigKeyCloakOIDCCreate,
14+
Read: resourceRancher2AuthConfigKeyCloakOIDCRead,
15+
Update: resourceRancher2AuthConfigKeyCloakOIDCUpdate,
16+
Delete: resourceRancher2AuthConfigKeyCloakOIDCDelete,
17+
18+
Schema: authConfigKeyCloakOIDCFields(),
19+
}
20+
}
21+
22+
func resourceRancher2AuthConfigKeyCloakOIDCCreate(d *schema.ResourceData, meta interface{}) error {
23+
client, err := meta.(*Config).ManagementClient()
24+
if err != nil {
25+
return err
26+
}
27+
28+
auth, err := client.AuthConfig.ByID(AuthConfigKeyCloakOIDCName)
29+
if err != nil {
30+
return fmt.Errorf("[ERROR] Failed to get Auth Config %s: %s", AuthConfigKeyCloakOIDCName, err)
31+
}
32+
33+
log.Printf("[INFO] Creating Auth Config %s", AuthConfigKeyCloakOIDCName)
34+
35+
authOIDC, err := expandAuthConfigKeyCloakOIDC(d)
36+
if err != nil {
37+
return fmt.Errorf("[ERROR] Failed expanding Auth Config %s: %s", AuthConfigKeyCloakOIDCName, err)
38+
}
39+
40+
// Checking if other auth config is enabled
41+
if authOIDC.Enabled {
42+
err = meta.(*Config).CheckAuthConfigEnabled(AuthConfigKeyCloakOIDCName)
43+
if err != nil {
44+
return fmt.Errorf("[ERROR] Checking to enable Auth Config %s: %s", AuthConfigKeyCloakOIDCName, err)
45+
}
46+
}
47+
48+
newAuth := &managementClient.KeyCloakOIDCConfig{}
49+
err = meta.(*Config).UpdateAuthConfig(auth.Links["self"], authOIDC, newAuth)
50+
if err != nil {
51+
return fmt.Errorf("[ERROR] Updating Auth Config %s: %s", AuthConfigKeyCloakOIDCName, err)
52+
}
53+
54+
return resourceRancher2AuthConfigKeyCloakOIDCRead(d, meta)
55+
}
56+
57+
func resourceRancher2AuthConfigKeyCloakOIDCRead(d *schema.ResourceData, meta interface{}) error {
58+
log.Printf("[INFO] Refreshing Auth Config %s", AuthConfigKeyCloakOIDCName)
59+
client, err := meta.(*Config).ManagementClient()
60+
if err != nil {
61+
return err
62+
}
63+
64+
auth, err := client.AuthConfig.ByID(AuthConfigKeyCloakOIDCName)
65+
if err != nil {
66+
if IsNotFound(err) {
67+
log.Printf("[INFO] Auth Config %s not found.", AuthConfigKeyCloakOIDCName)
68+
d.SetId("")
69+
return nil
70+
}
71+
return err
72+
}
73+
74+
authOIDC, err := meta.(*Config).GetAuthConfig(auth)
75+
if err != nil {
76+
return err
77+
}
78+
79+
err = flattenAuthConfigKeyCloakOIDC(d, authOIDC.(*managementClient.KeyCloakOIDCConfig))
80+
if err != nil {
81+
return err
82+
}
83+
84+
return nil
85+
}
86+
87+
func resourceRancher2AuthConfigKeyCloakOIDCUpdate(d *schema.ResourceData, meta interface{}) error {
88+
log.Printf("[INFO] Updating Auth Config %s", AuthConfigKeyCloakOIDCName)
89+
return resourceRancher2AuthConfigKeyCloakOIDCCreate(d, meta)
90+
}
91+
92+
func resourceRancher2AuthConfigKeyCloakOIDCDelete(d *schema.ResourceData, meta interface{}) error {
93+
log.Printf("[INFO] Disabling Auth Config %s", AuthConfigKeyCloakOIDCName)
94+
95+
client, err := meta.(*Config).ManagementClient()
96+
if err != nil {
97+
return err
98+
}
99+
100+
auth, err := client.AuthConfig.ByID(AuthConfigKeyCloakOIDCName)
101+
if err != nil {
102+
if IsNotFound(err) {
103+
log.Printf("[INFO] Auth Config %s not found.", AuthConfigKeyCloakOIDCName)
104+
d.SetId("")
105+
return nil
106+
}
107+
return err
108+
}
109+
110+
if auth.Enabled == true {
111+
err = client.Post(auth.Actions["disable"], nil, nil)
112+
if err != nil {
113+
return fmt.Errorf("[ERROR] Disabling Auth Config %s: %s", AuthConfigKeyCloakOIDCName, err)
114+
}
115+
}
116+
117+
d.SetId("")
118+
return nil
119+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package rancher2
2+
3+
import (
4+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
5+
)
6+
7+
const AuthConfigKeyCloakOIDCName = "keycloakoidc"
8+
9+
//Schemas
10+
11+
func authConfigKeyCloakOIDCFields() map[string]*schema.Schema {
12+
return oidcSchemaFields()
13+
}

rancher2/structure_auth_config_cognito.go

Lines changed: 1 addition & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -32,101 +32,5 @@ func expandAuthConfigCognito(in *schema.ResourceData) (*managementClient.Cognito
3232
obj.Name = AuthConfigCognitoName
3333
obj.Type = managementClient.CognitoConfigType
3434

35-
if v, ok := in.Get("access_mode").(string); ok && v != "" {
36-
obj.AccessMode = v
37-
}
38-
39-
if v, ok := in.Get("allowed_principal_ids").([]any); ok && len(v) > 0 {
40-
obj.AllowedPrincipalIDs = toArrayString(v)
41-
}
42-
43-
if (obj.AccessMode == "required" || obj.AccessMode == "restricted") && len(obj.AllowedPrincipalIDs) == 0 {
44-
return nil, fmt.Errorf("expanding %s Auth Config: allowed_principal_ids is required on access_mode %s", AuthConfigCognitoName, obj.AccessMode)
45-
}
46-
47-
if v, ok := in.Get("enabled").(bool); ok {
48-
obj.Enabled = v
49-
}
50-
51-
if v, ok := in.Get("annotations").(map[string]any); ok && len(v) > 0 {
52-
obj.Annotations = toMapString(v)
53-
}
54-
55-
if v, ok := in.Get("labels").(map[string]any); ok && len(v) > 0 {
56-
obj.Labels = toMapString(v)
57-
}
58-
59-
if v, ok := in.Get("client_id").(string); ok && v != "" {
60-
obj.ClientID = v
61-
}
62-
63-
if v, ok := in.Get("client_secret").(string); ok && v != "" {
64-
obj.ClientSecret = v
65-
}
66-
67-
if v, ok := in.Get("issuer").(string); ok && v != "" {
68-
obj.Issuer = v
69-
}
70-
71-
if v, ok := in.Get("rancher_url").(string); ok && v != "" {
72-
obj.RancherURL = v
73-
}
74-
75-
if v, ok := in.Get("auth_endpoint").(string); ok && v != "" {
76-
obj.AuthEndpoint = v
77-
}
78-
79-
if v, ok := in.Get("token_endpoint").(string); ok && v != "" {
80-
obj.TokenEndpoint = v
81-
}
82-
83-
if v, ok := in.Get("userinfo_endpoint").(string); ok && v != "" {
84-
obj.UserInfoEndpoint = v
85-
}
86-
87-
if v, ok := in.Get("jwks_url").(string); ok && v != "" {
88-
obj.JWKSUrl = v
89-
}
90-
91-
if v, ok := in.Get("scopes").(string); ok && v != "" {
92-
obj.Scopes = v
93-
}
94-
95-
if v, ok := in.Get("group_search_enabled").(bool); ok {
96-
obj.GroupSearchEnabled = &v
97-
}
98-
99-
if v, ok := in.Get("groups_field").(string); ok && v != "" {
100-
obj.GroupsClaim = v
101-
}
102-
103-
if v, ok := in.Get("certificate").(string); ok && v != "" {
104-
obj.Certificate = v
105-
}
106-
107-
if v, ok := in.Get("private_key").(string); ok && v != "" {
108-
obj.PrivateKey = v
109-
}
110-
111-
if v, ok := in.Get("name_claim").(string); ok && v != "" {
112-
obj.NameClaim = v
113-
}
114-
115-
if v, ok := in.Get("email_claim").(string); ok && v != "" {
116-
obj.EmailClaim = v
117-
}
118-
119-
if v, ok := in.Get("logout_all_enabled").(bool); ok {
120-
obj.LogoutAllEnabled = v
121-
}
122-
123-
if v, ok := in.Get("logout_all_forced").(bool); ok {
124-
obj.LogoutAllForced = v
125-
}
126-
127-
if v, ok := in.Get("end_session_endpoint").(string); ok && v != "" {
128-
obj.EndSessionEndpoint = v
129-
}
130-
131-
return obj, nil
35+
return expandOIDCConfig(in, obj)
13236
}

0 commit comments

Comments
 (0)