Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions aspell_custom.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ destructuring
yaml
ttl
pkce
oidcclients
51 changes: 51 additions & 0 deletions docs/resources/oidc_client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
page_title: "rancher2_oidc_client Resource"
---

# rancher2\_oidc_client Resource

Provides a Rancher OIDC Client. This can be used to configure the OIDC Clients
available for the Rancher OIDC Provider.

## Example Usage

### Creating a Rancher OIDC Client.
Comment thread
bigkevmcd marked this conversation as resolved.

```hcl
resource "rancher2_oidc_client" "oidc-test-client" {
description = "Access for Test Client"
token_expiration_seconds = 600 # expiration of the id_token and access_token
refresh_token_expiration_seconds = 7200 # expiration of the refresh_token
redirect_uris = [
"http://127.0.0.1:5556/auth/rancher/callback",
"http://127.0.0.1:33418/",
"https://vscode.dev/redirect"
]
}
```

## Argument Reference

The following arguments are supported:

* `description` - A human-readable description for the OIDC Client.
* `token_expiration_seconds` - ID Token and Access Token will only be valid for this many seconds.
* `refresh_token_expiration_seconds` - How long can the refresh token be used for?
* `redirect_uris` - Provides a list of allowed redirect URIs for this OIDC Client.
Comment thread
bigkevmcd marked this conversation as resolved.
* `annotations` - (Optional/Computed) Annotations for OIDC Client object (map)
* `labels` - (Optional/Computed) Labels for OIDC Client object (map)

## Attributes Reference

The following attributes are exported:

* `id` - (Computed) The ID of the resource (string)
* `client_id` - (Computed) The ID to be used when authenticating as this OIDC Client.
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.

## Import

OIDC Clients can be imported using the Client name in the format `<client_name>`

Comment thread
bigkevmcd marked this conversation as resolved.
```
$ terraform import rancher2_oidc_client.foo &lt;CLIENT_NAME&gt;
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.
```
1 change: 1 addition & 0 deletions rancher2/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ func Provider() terraform.ResourceProvider {
"rancher2_namespace": resourceRancher2Namespace(),
"rancher2_node_driver": resourceRancher2NodeDriver(),
"rancher2_node_pool": resourceRancher2NodePool(),
"rancher2_oidc_client": resourceRancher2OIDCClient(),
"rancher2_pod_security_admission_configuration_template": resourceRancher2PodSecurityAdmissionConfigurationTemplate(),
Comment thread
bigkevmcd marked this conversation as resolved.
"rancher2_project": resourceRancher2Project(),
"rancher2_project_role_template_binding": resourceRancher2ProjectRoleTemplateBinding(),
Expand Down
175 changes: 175 additions & 0 deletions rancher2/resource_rancher2_oidc_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
package rancher2

import (
"fmt"
"log"
"maps"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
managementClient "github.com/rancher/rancher/pkg/client/generated/management/v3"
)

func resourceRancher2OIDCClient() *schema.Resource {
return &schema.Resource{
Create: resourceRancher2OIDCClientCreate,
Read: resourceRancher2OIDCClientRead,
Update: resourceRancher2OIDCClientUpdate,
Delete: resourceRancher2OIDCClientDelete,
Comment thread
bigkevmcd marked this conversation as resolved.
Importer: &schema.ResourceImporter{
State: resourceRancher2OIDCClientImport,
},

Schema: oidcClientFields(),
}
Comment thread
bigkevmcd marked this conversation as resolved.
}

func oidcClientFields() map[string]*schema.Schema {
s := map[string]*schema.Schema{
"token_expiration_seconds": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "The duration (in seconds) before an access token and ID token expire.",
},
"refresh_token_expiration_seconds": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "The duration (in seconds) a refresh token remains valid before it expires.",
},
"redirect_uris": {
Description: "List of allowed redirect_uris for this client.",
Required: true,
Type: schema.TypeList,
Comment thread
bigkevmcd marked this conversation as resolved.
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
"description": {
Type: schema.TypeString,
Optional: true,
Description: "OIDCClient description",
},
"client_id": {
Type: schema.TypeString,
Computed: true,
Description: "The Client ID for OIDC Access.",
},
}
Comment thread
bigkevmcd marked this conversation as resolved.

maps.Copy(s, commonAnnotationLabelFields())

return s
Comment thread
bigkevmcd marked this conversation as resolved.
}

func resourceRancher2OIDCClientCreate(d *schema.ResourceData, meta any) error {
log.Printf("[INFO] Creating OIDCClient")
oidcClient, err := expandOIDCClient(d)
if err != nil {
return err
}

client, err := meta.(managementClientGetter).ManagementClient()
if err != nil {
return fmt.Errorf("getting a client when creating OIDC Client: %w", err)
}
Comment thread
bigkevmcd marked this conversation as resolved.

createdClient, err := client.OIDCClient.Create(oidcClient)
if err != nil {
return fmt.Errorf("creating OIDCClient: %w", err)
}

d.SetId(createdClient.ID)

return resourceRancher2OIDCClientRead(d, meta)
}

func resourceRancher2OIDCClientRead(d *schema.ResourceData, meta any) error {
log.Printf("[INFO] Refreshing OIDCClient ID %s", d.Id())

client, err := meta.(managementClientGetter).ManagementClient()
if err != nil {
return fmt.Errorf("getting a client when reading OIDC Client: %w", err)
}
oidcClient, err := client.OIDCClient.ByID(d.Id())
if err != nil {
if IsNotFound(err) || IsForbidden(err) || IsNotAccessibleByID(err) {
d.SetId("")
return nil
}
return fmt.Errorf("reading OIDC Client %s: %w", d.Id(), err)
}
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.

return flattenOIDCClient(d, oidcClient)
}

func resourceRancher2OIDCClientUpdate(d *schema.ResourceData, meta any) error {
log.Printf("[INFO] Updating OIDCClient ID %s", d.Id())

client, err := meta.(managementClientGetter).ManagementClient()
if err != nil {
return fmt.Errorf("getting a client when updating OIDC Client: %w", err)
}
Comment thread
bigkevmcd marked this conversation as resolved.

oidcClient, err := client.OIDCClient.ByID(d.Id())
if err != nil {
return fmt.Errorf("getting OIDC Client %s for update: %w", d.Id(), err)
}

update := map[string]any{
"labels": toMapString(d.Get("labels").(map[string]any)),
"annotations": toMapString(d.Get("annotations").(map[string]any)),
"description": d.Get("description"),
"redirectURIs": toArrayString(d.Get("redirect_uris").([]any)),
Comment thread
bigkevmcd marked this conversation as resolved.
"tokenExpirationSeconds": d.Get("token_expiration_seconds"),
"refreshTokenExpirationSeconds": d.Get("refresh_token_expiration_seconds"),
}
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.

_, err = client.OIDCClient.Update(oidcClient, update)
if err != nil {
return fmt.Errorf("updating OIDC Client %s: %w", d.Id(), err)
}

return resourceRancher2OIDCClientRead(d, meta)
}

func resourceRancher2OIDCClientDelete(d *schema.ResourceData, meta any) error {
log.Printf("[INFO] Deleting OIDCClient ID %s", d.Id())

client, err := meta.(managementClientGetter).ManagementClient()
if err != nil {
return fmt.Errorf("getting a client when deleting OIDC Client: %w", err)
}

oidcClient, err := client.OIDCClient.ByID(d.Id())
if err != nil {
if IsNotFound(err) || IsForbidden(err) || IsNotAccessibleByID(err) {
d.SetId("")
return nil
}
return fmt.Errorf("getting OIDC Client %s for deletion: %w", d.Id(), err)
}
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.
Comment thread
bigkevmcd marked this conversation as resolved.

err = client.OIDCClient.Delete(oidcClient)
if err != nil {
if !IsNotFound(err) {
return fmt.Errorf("deleting OIDC Client %s: %w", d.Id(), err)
}
}

d.SetId("")
return nil
}

func resourceRancher2OIDCClientImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
err := resourceRancher2OIDCClientRead(d, meta)
if err != nil || d.Id() == "" {
return []*schema.ResourceData{}, err
}

return []*schema.ResourceData{d}, nil
}
Comment thread
bigkevmcd marked this conversation as resolved.

type managementClientGetter interface {
ManagementClient() (*managementClient.Client, error)
}
Loading
Loading