Skip to content
This repository has been archived by the owner on Mar 8, 2022. It is now read-only.

Commit

Permalink
Merge pull request #487 from kevinschoonover/master
Browse files Browse the repository at this point in the history
Add support for Management API tokens
  • Loading branch information
sergiught authored Feb 14, 2022
2 parents c26c503 + 0588ca3 commit f78386c
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 16 deletions.
45 changes: 31 additions & 14 deletions auth0/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,24 @@ func Provider() *schema.Provider {
DefaultFunc: schema.EnvDefaultFunc("AUTH0_DOMAIN", nil),
},
"client_id": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("AUTH0_CLIENT_ID", nil),
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AUTH0_CLIENT_ID", nil),
RequiredWith: []string{"client_secret"},
ConflictsWith: []string{"api_token"},
},
"client_secret": {
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("AUTH0_CLIENT_SECRET", nil),
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AUTH0_CLIENT_SECRET", nil),
RequiredWith: []string{"client_id"},
ConflictsWith: []string{"api_token"},
},
"api_token": {
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AUTH0_API_TOKEN", nil),
ConflictsWith: []string{"client_id", "client_secret"},
},
"debug": {
Type: schema.TypeBool,
Expand Down Expand Up @@ -82,11 +92,6 @@ func Provider() *schema.Provider {
// client is stored and passed into the subsequent resources as the meta parameter.
func ConfigureProvider(terraformVersion string) func(data *schema.ResourceData) (interface{}, error) {
return func(data *schema.ResourceData) (interface{}, error) {
domain := data.Get("domain").(string)
id := data.Get("client_id").(string)
secret := data.Get("client_secret").(string)
debug := data.Get("debug").(bool)

providerVersion := version.ProviderVersion
sdkVersion := auth0.Version
terraformSDKVersion := meta.SDKVersionString()
Expand All @@ -99,9 +104,21 @@ func ConfigureProvider(terraformVersion string) func(data *schema.ResourceData)
terraformVersion,
)

return management.New(
domain,
management.WithClientCredentials(id, secret),
domain := data.Get("domain").(string)
debug := data.Get("debug").(bool)
clientID := data.Get("client_id").(string)
clientSecret := data.Get("client_secret").(string)
apiToken := data.Get("api_token").(string)

authenticationOption := management.WithStaticToken(apiToken)
// if api_token is not specified, authenticate with client ID and client secret.
// This is safe because of the provider schema.
if apiToken == "" {
authenticationOption = management.WithClientCredentials(clientID, clientSecret)
}

return management.New(domain,
authenticationOption,
management.WithDebug(debug),
management.WithUserAgent(userAgent),
)
Expand Down
80 changes: 80 additions & 0 deletions auth0/provider_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package auth0

import (
"errors"
"os"
"sort"
"strings"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
Expand Down Expand Up @@ -71,3 +74,80 @@ func TestProvider_debugDefaults(t *testing.T) {
}
}
}

func TestProvider_configValidation(t *testing.T) {
testCases := []struct {
name string
resourceConfig map[string]interface{}
expectedErrors []error
}{
{
name: "missing client id",
resourceConfig: map[string]interface{}{"domain": "test", "client_secret": "test"},
expectedErrors: []error{errors.New("\"client_secret\": all of `client_id,client_secret` must be specified")},
},
{
name: "missing client secret",
resourceConfig: map[string]interface{}{"domain": "test", "client_id": "test"},
expectedErrors: []error{errors.New("\"client_id\": all of `client_id,client_secret` must be specified")},
},
{
name: "conflicting auth0 client and management token without domain",
resourceConfig: map[string]interface{}{"client_id": "test", "client_secret": "test", "api_token": "test"},
expectedErrors: []error{
errors.New("\"domain\": required field is not set"),
errors.New("\"client_id\": conflicts with api_token"),
errors.New("\"client_secret\": conflicts with api_token"),
errors.New("\"api_token\": conflicts with client_id"),
},
},
{
name: "valid auth0 client",
resourceConfig: map[string]interface{}{"domain": "valid_domain", "client_id": "test", "client_secret": "test"},
expectedErrors: nil,
},
{
name: "valid auth0 token",
resourceConfig: map[string]interface{}{"domain": "valid_domain", "api_token": "test"},
expectedErrors: nil,
},
}

originalEnviroment := os.Environ()
os.Clearenv()
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
c := terraform.NewResourceConfigRaw(test.resourceConfig)
p := Provider()

_, errs := p.Validate(c)
assertErrorsSliceEqual(t, test.expectedErrors, errs)
})
}

for _, e := range originalEnviroment {
environmentPair := strings.Split(e, "=")
os.Setenv(environmentPair[0], environmentPair[1])
}
}

func sortErrors(errs []error) {
sort.Slice(errs, func(i, j int) bool {
return errs[i].Error() < errs[j].Error()
})
}

func assertErrorsSliceEqual(t *testing.T, expected, actual []error) {
if len(expected) != len(actual) {
t.Fatalf("actual did not match expected. len(expected) != len(actual). expected: %v, actual: %v", expected, actual)
}

sortErrors(expected)
sortErrors(actual)

for i := range expected {
if expected[i].Error() != actual[i].Error() {
t.Fatalf("actual did not match expected. expected[%d] != actual[%d]. expected: %v, actual: %v", i, i, expected, actual)
}
}
}
9 changes: 7 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ provider "auth0" {
## Argument Reference

* `domain` - (Required) Your Auth0 domain name. It can also be sourced from the `AUTH0_DOMAIN` environment variable.
* `client_id` - (Required) Your Auth0 client ID. It can also be sourced from the `AUTH0_CLIENT_ID` environment variable.
* `client_secret` - (Required) Your Auth0 client secret. It can also be sourced from the `AUTH0_CLIENT_SECRET` environment variable.
* `client_id` - (Optional) Your Auth0 client ID. It can also be sourced from the `AUTH0_CLIENT_ID` environment variable.
* `client_secret` - (Optional) Your Auth0 client secret. It can also be sourced from the `AUTH0_CLIENT_SECRET` environment variable.
* `api_token` - (Optional) Your Auth0 [management api access token](https://auth0.com/docs/security/tokens/access-tokens/management-api-access-tokens).
It can also be sourced from the `AUTH0_API_TOKEN` environment variable. Can be
used instead of `client_id` + `client_secret`. If both are specified,
`management_token` will be used over `client_id` + `client_secret` fields.
* `debug` - (Optional) Indicates whether or not to turn on debug mode.

## Environment Variables
Expand All @@ -51,3 +55,4 @@ $ terraform plan
## Importing resources

To import Auth0 resources, you will need to know their id. You can use the [Auth0 API Explorer](https://auth0.com/docs/api/management/v2) to easily find your resource id.

0 comments on commit f78386c

Please sign in to comment.