Skip to content

Commit a97b5f5

Browse files
feat: support generic OIDC provider (#1644) (#1648)
Co-authored-by: Sergei Starostin <[email protected]>
1 parent 2e54049 commit a97b5f5

8 files changed

+652
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
page_title: "rancher2_auth_config_generic_oidc Resource"
3+
---
4+
5+
# rancher2\_auth\_config\_generic\_oidc Resource
6+
7+
Provides a Rancher v2 Auth Config Generic OIDC resource. This can be used to configure and enable the Generic OIDC authentication provider for Rancher v2.
8+
9+
In addition to the built-in local auth, only one external auth config provider can be enabled at a time.
10+
11+
## Example Usage
12+
13+
This example configures Rancher to use GitLab as a Generic OIDC provider.
14+
15+
```hcl
16+
resource "rancher2_auth_config_generic_oidc" "generic_oidc" {
17+
name = "genericoidc"
18+
client_id = "<GITLAB_APPLICATION_ID>"
19+
client_secret = "<GITLAB_CLIENT_SECRET>"
20+
issuer = "https://gitlab.com"
21+
rancher_url = "https://<RANCHER_URL>/verify-auth"
22+
23+
# OIDC claim mapping
24+
scopes = "openid profile email read_api"
25+
groups_field = "groups"
26+
27+
# For the 'genericoidc' provider, group processing must be explicitly enabled.
28+
group_search_enabled = true
29+
}
30+
```
31+
32+
## Argument Reference
33+
34+
The following arguments are supported:
35+
36+
* `client_id` - (Required/Sensitive) The OIDC Client ID.
37+
* `client_secret` - (Required/Sensitive) The OIDC Client Secret.
38+
* `issuer` - (Required) The OIDC issuer URL.
39+
* `rancher_url` - (Required) The URL of the Rancher server. This is used as the redirect URI for the OIDC provider.
40+
* `access_mode` - (Optional) Access mode for auth. `required`, `restricted`, `unrestricted` are supported. Default `unrestricted` (string)
41+
* `allowed_principal_ids` - (Optional) Allowed principal IDs for auth. Required if `access_mode` is `required` or `restricted`. Ex: `genericoidc_user://<USER_ID>` `genericoidc_group://<GROUP_ID>` (list)
42+
* `auth_endpoint` - (Optional/Computed) The OIDC Auth Endpoint URL.
43+
* `certificate` - (Optional/Sensitive) A PEM-encoded CA certificate for the OIDC provider.
44+
* `enabled` - (Optional) Enable the auth config provider. Default `true` (bool)
45+
* `groups_field` - (Optional/Computed) The name of the OIDC claim to use for the user's group memberships. Default `groups` (string)
46+
* `group_search_enabled` - (Optional) Enable group search. Default `false` (bool)
47+
* `jwks_url` - (Optional/Computed) The OIDC JWKS URL.
48+
* `private_key` - (Optional/Sensitive) A PEM-encoded private key for the OIDC provider.
49+
* `scopes` - (Optional/Computed) The OIDC scopes to request. Defaults to `openid profile email` (string)
50+
* `token_endpoint` - (Optional/Computed) The OIDC Token Endpoint URL.
51+
* `userinfo_endpoint` - (Optional/Computed) The OIDC User Info Endpoint URL.
52+
* `annotations` - (Optional/Computed) Annotations of the resource (map)
53+
* `labels` - (Optional/Computed) Labels of the resource (map)
54+
55+
## Attributes Reference
56+
57+
The following attributes are exported:
58+
59+
* `id` - (Computed) The ID of the resource (string)
60+
* `name` - (Computed) The name of the resource (string)
61+
* `type` - (Computed) The type of the resource (string)
62+
63+
## Import
64+
65+
Generic OIDC auth config can be imported using its name.
66+
67+
```
68+
$ terraform import rancher2_auth_config_generic_oidc.generic_oidc genericoidc
69+
```

rancher2/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,8 @@ func getAuthConfigObject(kind string) (interface{}, error) {
12561256
return &managementClient.GithubConfig{}, nil
12571257
case managementClient.KeyCloakConfigType:
12581258
return &managementClient.KeyCloakConfig{}, nil
1259+
case managementClient.GenericOIDCConfigType:
1260+
return &managementClient.GenericOIDCConfig{}, nil
12591261
case managementClient.OKTAConfigType:
12601262
return &managementClient.OKTAConfig{}, nil
12611263
case managementClient.OpenLdapConfigType:

rancher2/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ func Provider() terraform.ResourceProvider {
115115
"rancher2_auth_config_github": resourceRancher2AuthConfigGithub(),
116116
"rancher2_auth_config_keycloak": resourceRancher2AuthConfigKeyCloak(),
117117
"rancher2_auth_config_okta": resourceRancher2AuthConfigOKTA(),
118+
"rancher2_auth_config_generic_oidc": resourceRancher2AuthConfigGenericOIDC(),
118119
"rancher2_auth_config_openldap": resourceRancher2AuthConfigOpenLdap(),
119120
"rancher2_auth_config_ping": resourceRancher2AuthConfigPing(),
120121
"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 resourceRancher2AuthConfigGenericOIDC() *schema.Resource {
12+
return &schema.Resource{
13+
Create: resourceRancher2AuthConfigGenericOIDCCreate,
14+
Read: resourceRancher2AuthConfigGenericOIDCRead,
15+
Update: resourceRancher2AuthConfigGenericOIDCUpdate,
16+
Delete: resourceRancher2AuthConfigGenericOIDCDelete,
17+
18+
Schema: authConfigGenericOIDCFields(),
19+
}
20+
}
21+
22+
func resourceRancher2AuthConfigGenericOIDCCreate(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(AuthConfigGenericOIDCName)
29+
if err != nil {
30+
return fmt.Errorf("[ERROR] Failed to get Auth Config %s: %s", AuthConfigGenericOIDCName, err)
31+
}
32+
33+
log.Printf("[INFO] Creating Auth Config %s", AuthConfigGenericOIDCName)
34+
35+
authOIDC, err := expandAuthConfigGenericOIDC(d)
36+
if err != nil {
37+
return fmt.Errorf("[ERROR] Failed expanding Auth Config %s: %s", AuthConfigGenericOIDCName, err)
38+
}
39+
40+
// Checking if other auth config is enabled
41+
if authOIDC.Enabled {
42+
err = meta.(*Config).CheckAuthConfigEnabled(AuthConfigGenericOIDCName)
43+
if err != nil {
44+
return fmt.Errorf("[ERROR] Checking to enable Auth Config %s: %s", AuthConfigGenericOIDCName, err)
45+
}
46+
}
47+
48+
newAuth := &managementClient.OIDCConfig{}
49+
err = meta.(*Config).UpdateAuthConfig(auth.Links["self"], authOIDC, newAuth)
50+
if err != nil {
51+
return fmt.Errorf("[ERROR] Updating Auth Config %s: %s", AuthConfigGenericOIDCName, err)
52+
}
53+
54+
return resourceRancher2AuthConfigGenericOIDCRead(d, meta)
55+
}
56+
57+
func resourceRancher2AuthConfigGenericOIDCRead(d *schema.ResourceData, meta interface{}) error {
58+
log.Printf("[INFO] Refreshing Auth Config %s", AuthConfigGenericOIDCName)
59+
client, err := meta.(*Config).ManagementClient()
60+
if err != nil {
61+
return err
62+
}
63+
64+
auth, err := client.AuthConfig.ByID(AuthConfigGenericOIDCName)
65+
if err != nil {
66+
if IsNotFound(err) {
67+
log.Printf("[INFO] Auth Config %s not found.", AuthConfigGenericOIDCName)
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 = flattenAuthConfigGenericOIDC(d, authOIDC.(*managementClient.OIDCConfig))
80+
if err != nil {
81+
return err
82+
}
83+
84+
return nil
85+
}
86+
87+
func resourceRancher2AuthConfigGenericOIDCUpdate(d *schema.ResourceData, meta interface{}) error {
88+
log.Printf("[INFO] Updating Auth Config %s", AuthConfigGenericOIDCName)
89+
return resourceRancher2AuthConfigGenericOIDCCreate(d, meta)
90+
}
91+
92+
func resourceRancher2AuthConfigGenericOIDCDelete(d *schema.ResourceData, meta interface{}) error {
93+
log.Printf("[INFO] Disabling Auth Config %s", AuthConfigGenericOIDCName)
94+
95+
client, err := meta.(*Config).ManagementClient()
96+
if err != nil {
97+
return err
98+
}
99+
100+
auth, err := client.AuthConfig.ByID(AuthConfigGenericOIDCName)
101+
if err != nil {
102+
if IsNotFound(err) {
103+
log.Printf("[INFO] Auth Config %s not found.", AuthConfigGenericOIDCName)
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", AuthConfigGenericOIDCName, err)
114+
}
115+
}
116+
117+
d.SetId("")
118+
return nil
119+
}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
package rancher2
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"time"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
10+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
11+
)
12+
13+
const (
14+
testAccRancher2AuthConfigGenericOIDCName = "genericoidc"
15+
testAccRancher2AuthConfigGenericOIDCType = "rancher2_auth_config_generic_oidc"
16+
)
17+
18+
var (
19+
testAccProviders map[string]terraform.ResourceProvider
20+
testAccProvider *schema.Provider
21+
testAccRancher2AuthConfigGenericOIDCClientID = os.Getenv("RANCHER_OIDC_CLIENT_ID")
22+
testAccRancher2AuthConfigGenericOIDCClientSecret = os.Getenv("RANCHER_OIDC_CLIENT_SECRET")
23+
testAccRancher2AuthConfigGenericOIDCIssuerURL = os.Getenv("RANCHER_OIDC_ISSUER_URL")
24+
testAccRancher2AuthConfigGenericOIDCRancherURL = os.Getenv("RANCHER_URL")
25+
)
26+
27+
func init() {
28+
testAccProvider = Provider().(*schema.Provider)
29+
testAccProviders = map[string]terraform.ResourceProvider{
30+
"rancher2": testAccProvider,
31+
}
32+
}
33+
34+
func testAccCheckRancher2AuthConfigGenericOIDCExists(name string) resource.TestCheckFunc {
35+
return func(s *terraform.State) error {
36+
rs, ok := s.RootModule().Resources[name]
37+
if !ok {
38+
return fmt.Errorf("Not found: %s", name)
39+
}
40+
41+
if rs.Primary.ID == "" {
42+
return fmt.Errorf("No Auth Config Generic OIDC ID is set")
43+
}
44+
45+
// Reading the auth config can be slow, add a delay.
46+
time.Sleep(2 * time.Second)
47+
48+
return nil
49+
}
50+
}
51+
52+
func testAccCheckRancher2AuthConfigGenericOIDCConfig() resource.TestCheckFunc {
53+
return func(s *terraform.State) error {
54+
client, err := testAccProvider.Meta().(*Config).ManagementClient()
55+
if err != nil {
56+
return err
57+
}
58+
59+
auth, err := client.AuthConfig.ByID(AuthConfigGenericOIDCName)
60+
if err != nil {
61+
return fmt.Errorf("Failed to get Auth Config %s: %s", AuthConfigGenericOIDCName, err)
62+
}
63+
64+
if auth.Enabled != true {
65+
return fmt.Errorf("Auth Config %s is not enabled", AuthConfigGenericOIDCName)
66+
}
67+
68+
return nil
69+
}
70+
}
71+
72+
func testAccCheckRancher2AuthConfigGenericOIDCDisabled(s *terraform.State) error {
73+
client, err := testAccProvider.Meta().(*Config).ManagementClient()
74+
if err != nil {
75+
return err
76+
}
77+
78+
auth, err := client.AuthConfig.ByID(AuthConfigGenericOIDCName)
79+
if err != nil {
80+
if IsNotFound(err) {
81+
return nil
82+
}
83+
return err
84+
}
85+
86+
if auth.Enabled == true {
87+
return fmt.Errorf("Auth Config %s is still enabled", AuthConfigGenericOIDCName)
88+
}
89+
90+
return nil
91+
}
92+
93+
func testAccRancher2AuthConfigGenericOIDCConfig() string {
94+
return fmt.Sprintf(`
95+
resource "rancher2_auth_config_generic_oidc" "genericoidc" {
96+
client_id = "%s"
97+
client_secret = "%s"
98+
issuer = "%s"
99+
rancher_url = "%s/verify-auth"
100+
enabled = true
101+
scopes = "openid profile email"
102+
groups_field = "groups"
103+
group_search_enabled = true
104+
}
105+
`, testAccRancher2AuthConfigGenericOIDCClientID, testAccRancher2AuthConfigGenericOIDCClientSecret, testAccRancher2AuthConfigGenericOIDCIssuerURL, testAccRancher2AuthConfigGenericOIDCRancherURL)
106+
}
107+
108+
func testAccRancher2AuthConfigGenericOIDCUpdateConfig() string {
109+
return fmt.Sprintf(`
110+
resource "rancher2_auth_config_generic_oidc" "genericoidc" {
111+
client_id = "%s"
112+
client_secret = "%s"
113+
issuer = "%s"
114+
rancher_url = "%s/verify-auth"
115+
enabled = true
116+
scopes = "openid profile"
117+
groups_field = "group"
118+
group_search_enabled = false
119+
}
120+
`, testAccRancher2AuthConfigGenericOIDCClientID, testAccRancher2AuthConfigGenericOIDCClientSecret, testAccRancher2AuthConfigGenericOIDCIssuerURL, testAccRancher2AuthConfigGenericOIDCRancherURL)
121+
}

0 commit comments

Comments
 (0)