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 docs/resources/custom_user_token.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ resource "rancher2_custom_user_token" "foo" {

The following arguments are supported:

* `auth_provider` - (Optional/ForceNew) The auth provider to use. Default `local` (string). One of `local`, `activedirectory`, `adfs`, `azuread`, `freeipa`, `generic_oidc`, `github`, `keycloak`, `okta`, `openldap`, `ping`
* `username` - (Required/ForceNew) The user username (string)
* `password` - (Required/ForceNew) The user password (string)
* `cluster_id` - (Optional/ForceNew) Cluster ID for scoped token (string)
Expand Down
2 changes: 1 addition & 1 deletion rancher2/resource_rancher2_bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ logged:
for {
for _, pass := range loginPass {
if len(pass) > 0 {
tokenID, token, err = DoUserLogin(meta.(*Config).URL, bootstrapDefaultUser, pass, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, meta.(*Config).CACerts, meta.(*Config).Insecure)
tokenID, token, err = DoUserLogin(meta.(*Config).URL, "local", bootstrapDefaultUser, pass, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, meta.(*Config).CACerts, meta.(*Config).Insecure)
if err == nil {
break logged
}
Expand Down
2 changes: 1 addition & 1 deletion rancher2/resource_rancher2_custom_user_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func doUserLogin(d *schema.ResourceData, meta interface{}) (*managementClient.Cl
}

log.Printf("[DEBUG] Creating Temp API Token for User %s", d.Get("username").(string))
tempTokenID, tempTokenValue, err := DoUserLogin(meta.(*Config).URL, d.Get("username").(string), d.Get("password").(string), "0", "Temp Terraform API token", meta.(*Config).CACerts, meta.(*Config).Insecure)
tempTokenID, tempTokenValue, err := DoUserLogin(meta.(*Config).URL, d.Get("auth_provider").(string), d.Get("username").(string), d.Get("password").(string), "0", "Temp Terraform API token", meta.(*Config).CACerts, meta.(*Config).Insecure)
if err != nil {
return nil, fmt.Errorf("[ERROR] Login with %s user: %v", d.Get("username").(string), err)
}
Expand Down
21 changes: 21 additions & 0 deletions rancher2/schema_custom_user_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,33 @@ package rancher2

import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/helper/validation"
)

//Schemas

func customUserTokenFields() map[string]*schema.Schema {
s := map[string]*schema.Schema{
"auth_provider": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: "The provider to use for authentication",
Default: "local",
ValidateFunc: validation.StringInSlice([]string{
"local",
"activedirectory",
"adfs",
"azuread",
"freeipa",
"generic_oidc",
"github",
"keycloak",
"okta",
"openldap",
"ping",
}, false),
},
"password": {
Type: schema.TypeString,
Required: true,
Expand Down
20 changes: 17 additions & 3 deletions rancher2/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,28 @@ func NewListOpts(filters map[string]interface{}) *types.ListOpts {
return listOpts
}

func DoUserLogin(url, user, pass, ttl, desc, cacert string, insecure bool) (string, string, error) {
func DoUserLogin(url, provider, user, pass, ttl, desc, cacert string, insecure bool) (string, string, error) {
TTL, err := strconv.ParseInt(ttl, 10, 64)
if err != nil || TTL < 0 {
return "", "", fmt.Errorf("Invalid ttl value: %s", ttl)
}

authType := map[string]string{
"local": "local",
"activedirectory": "activeDirectory",
"adfs": "adfs",
"azuread": "azureAD",
"freeipa": "freeIpa",
"generic_oidc": "generic_oidc",
"github": "github",
"keycloak": "keyCloak",
"okta": "okta",
"openldap": "openLdap",
"ping": "ping",
}

payload, err := json.Marshal(map[string]any{
"type": "localProvider",
"type": fmt.Sprintf("%sProvider", authType[provider]),
"username": user,
"password": pass,
"ttl": TTL,
Expand All @@ -157,7 +171,7 @@ func DoUserLogin(url, user, pass, ttl, desc, cacert string, insecure bool) (stri
}

loginURL := url + "/v1-public/login"
v3loginURL := url + "/v3-public/localProviders/local?action=login"
v3loginURL := fmt.Sprintf("%s/v3-public/%sProviders/%s?action=login", url, authType[provider], provider)

loginHead := map[string]string{
"Accept": "application/json",
Expand Down
26 changes: 15 additions & 11 deletions rancher2/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"github.com/stretchr/testify/require"
)

const (
localProdvider = "local"
)

type loginInput struct {
Type string `json:"type"`
Username string `json:"username"`
Expand Down Expand Up @@ -44,7 +48,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
id, token, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
require.NoError(t, err)
assert.Equal(t, tokenID, id)
assert.Equal(t, tokenValue, token)
Expand All @@ -62,7 +66,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
id, token, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
require.NoError(t, err)
assert.Equal(t, "saml-user-abc123", id, "ext/ prefix should be stripped from ID")
assert.Equal(t, tokenValue, token)
Expand All @@ -78,7 +82,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
_, _, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
require.Error(t, err)
assert.Contains(t, err.Error(), "Unauthorized")
})
Expand All @@ -92,7 +96,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
_, _, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
require.Error(t, err)
assert.Contains(t, err.Error(), "invalid token format")
})
Expand All @@ -109,7 +113,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
_, _, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
require.Error(t, err)
})

Expand All @@ -122,7 +126,7 @@ func TestDoUserLogin(t *testing.T) {
callCount++

if r.URL.Path == "/v1-public/login" {
// Simulate v1 endpoint not available
// Simulate v3 endpoint not available
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(http.StatusText(http.StatusNotFound)))
return
Expand All @@ -147,7 +151,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
id, token, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
require.NoError(t, err)
assert.Equal(t, tokenID, id)
assert.Equal(t, tokenValue, token)
Expand All @@ -171,7 +175,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
_, _, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
require.Error(t, err)
assert.Contains(t, err.Error(), "Unauthorized")
})
Expand All @@ -182,7 +186,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, "not-a-number", bootstrapDefaultSessionDesc, "", true)
_, _, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, "not-a-number", bootstrapDefaultSessionDesc, "", true)
require.Error(t, err)
assert.Contains(t, err.Error(), "Invalid ttl value")
})
Expand All @@ -193,7 +197,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, "-1000", bootstrapDefaultSessionDesc, "", true)
_, _, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, "-1000", bootstrapDefaultSessionDesc, "", true)
require.Error(t, err)
assert.Contains(t, err.Error(), "Invalid ttl value")
})
Expand All @@ -215,7 +219,7 @@ func TestDoUserLogin(t *testing.T) {
}))
defer srv.Close()

id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, "0", bootstrapDefaultSessionDesc, "", true)
id, token, err := DoUserLogin(srv.URL, localProdvider, bootstrapDefaultUser, bootstrapDefaultPassword, "0", bootstrapDefaultSessionDesc, "", true)
require.NoError(t, err)
assert.Equal(t, tokenID, id)
assert.Equal(t, tokenValue, token)
Expand Down
Loading