Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
dnna committed Aug 29, 2017
1 parent 0dca3b6 commit e6fd137
Show file tree
Hide file tree
Showing 5 changed files with 364 additions and 1 deletion.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
crash.log
.terraform
terraform-lib
docker-compose.yml
Dockerfile
main.tf
terraform-provider-auth0
terraform.tfstate
terraform.tfstate.backup
62 changes: 61 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,62 @@
# terraform-provider-auth0
A custom provider for terraform

A custom provider for terraform.

## Installation

1. Download the latest [release](github.com/dnna/terraform-provider-auth0/releases) for your platform
2. rename the file to `terraform-provider-auth0`
3. Copy the file to the same directory as terraform `dirname $(which terraform)` is installed

## Usage

### auth0_client

#### Example Usage

Provides an auth0 client

```hcl
resource "auth0_client" "test-client" {
name = "p-test-dev2"
is_token_endpoint_ip_header_trusted = true
is_first_party = false
description = ""
cross_origin_auth = false
sso = true
token_endpoint_auth_method = "client_secret_post"
grant_types = [ "authorization_code", "implicit", "refresh_token", "client_credentials" ]
app_type = "non_interactive"
custom_login_page_on = true
}
```

The output will look like this:

```sh
resource.auth0_client.test-client.client_id = "generated_client_id"
resource.auth0_client.test-client.client_secret = "generated_client_secret"
```

#### Argument Reference

Arguments have the same names as provided in Auth0 Management API documentation (https://auth0.com/docs/api/management/v2#!/Clients).
The provider itself requires 2 parameters:


- `domain` - The provided domain for the Auth0 account
- `access_token` - An access token with sufficient permissions to access the Auth0 Management API and perform CRUD operations on clients

#### Attributes Reference

- `client_id` - The client ID of the new client
- `client_secret` - The client secret of the new client

## Develop

```sh
go get github.com/dnna/terraform-provider-auth0
cd $GOPATH/src/github.com/dnna/terraform-provider-auth0
go get ./...
$EDITOR .
```
14 changes: 14 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import (
"github.com/hashicorp/terraform/plugin"
"github.com/hashicorp/terraform/terraform"
)

func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: func() terraform.ResourceProvider {
return Provider()
},
})
}
40 changes: 40 additions & 0 deletions provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

import (
"log"

"github.com/hashicorp/terraform/helper/schema"
)

func Provider() *schema.Provider {
return &schema.Provider{
Schema: map[string]*schema.Schema{
"domain": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("MANAGEMENT_API_DOMAIN", nil),
},
"access_token": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("MANAGEMENT_API_ACCESS_TOKEN", nil),
},
},

ResourcesMap: map[string]*schema.Resource{
"auth0_client": resourceClient(),
},

ConfigureFunc: providerConfigure,
}
}

type Config struct {
domain string
accessToken string
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
log.Println("[INFO] Initializing Auth0 client")
return Config{domain: d.Get("domain").(string), accessToken: d.Get("access_token").(string)}, nil
}
240 changes: 240 additions & 0 deletions resource_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
package main

import (
"encoding/json"
"io/ioutil"
"net/http"
"log"
"bytes"
"errors"

"github.com/hashicorp/terraform/helper/schema"
)

func resourceClient() *schema.Resource {
return &schema.Resource{
Create: resourceClientCreate,
Read: resourceClientRead,
Update: resourceClientUpdate,
Delete: resourceClientDelete,

Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"description": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"is_token_endpoint_ip_header_trusted": &schema.Schema{
Type: schema.TypeBool,
Required: true,
},
"is_first_party": &schema.Schema{
Type: schema.TypeBool,
Required: true,
},
"cross_origin_auth": &schema.Schema{
Type: schema.TypeBool,
Required: true,
},
"sso": &schema.Schema{
Type: schema.TypeBool,
Required: true,
},
"token_endpoint_auth_method": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"grant_types": &schema.Schema{
Type: schema.TypeList,
Elem: &schema.Schema{Type: schema.TypeString},
Required: true,
},
"custom_login_page_on": &schema.Schema{
Type: schema.TypeBool,
Required: true,
},
"app_type": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
},
}
}

type Client struct {
Client_id string `json:"client_id,omitempty"`
Client_secret string `json:"client_secret,omitempty"`
Name string `json:"name"`
Is_token_endpoint_ip_header_trusted bool `json:"is_token_endpoint_ip_header_trusted"`
Is_first_party bool `json:"is_first_party"`
Description string `json:"description"`
Cross_origin_auth bool `json:"cross_origin_auth"`
Sso bool `json:"sso"`
Token_endpoint_auth_method string `json:"token_endpoint_auth_method"`
Grant_types []interface{} `json:"grant_types"`
App_type string `json:"app_type"`
Custom_login_page_on bool `json:"custom_login_page_on"`
}

func resourceClientCreate(d *schema.ResourceData, m interface{}) error {
reqClient := Client{
Name: d.Get("name").(string),
Is_token_endpoint_ip_header_trusted: d.Get("is_token_endpoint_ip_header_trusted").(bool),
Is_first_party: d.Get("is_first_party").(bool),
Description: d.Get("description").(string),
Cross_origin_auth: d.Get("cross_origin_auth").(bool),
Sso: d.Get("sso").(bool),
Token_endpoint_auth_method: d.Get("token_endpoint_auth_method").(string),
Grant_types: d.Get("grant_types").([]interface{}),
App_type: d.Get("app_type").(string),
Custom_login_page_on: d.Get("custom_login_page_on").(bool),
}

jsonValue, err := json.Marshal(reqClient)
if err != nil {
return err
}
log.Println("Request JSON: " + string(jsonValue))

config := m.(Config)
client := http.Client{}
req, err := http.NewRequest("POST", "https://" + config.domain + "/api/v2/clients", bytes.NewBuffer(jsonValue))
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer" + config.accessToken)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
log.Println("Response JSON:" + string(data))

if(resp.StatusCode != 201) {
return errors.New("Error: Invalid status code during create")
}

var respClient Client
err = json.Unmarshal(data, &respClient)
if err != nil {
return err
}

log.Println("New client_id:" + respClient.Client_id)
d.Set("client_id", respClient.Client_id)
d.Set("client_secret", respClient.Client_secret)
d.SetId(respClient.Client_id)
return nil
}

func resourceClientRead(d *schema.ResourceData, m interface{}) error {
config := m.(Config)
client := http.Client{}
req, err := http.NewRequest("GET", "https://" + config.domain + "/api/v2/clients/" + d.Id(), nil)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer" + config.accessToken)

resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
log.Println("Response JSON:" + string(data))

if(resp.StatusCode != 200) {
if(resp.StatusCode == 404) {
// Client was deleted
d.SetId("")
return nil
} else {
return errors.New("Error: Invalid status code during read")
}
}

var respClient Client
err = json.Unmarshal(data, &respClient)
if err != nil {
return err
}

return nil
}

func resourceClientUpdate(d *schema.ResourceData, m interface{}) error {
reqClient := Client{
Name: d.Get("name").(string),
Is_token_endpoint_ip_header_trusted: d.Get("is_token_endpoint_ip_header_trusted").(bool),
Is_first_party: d.Get("is_first_party").(bool),
Description: d.Get("description").(string),
Cross_origin_auth: d.Get("cross_origin_auth").(bool),
Sso: d.Get("sso").(bool),
Token_endpoint_auth_method: d.Get("token_endpoint_auth_method").(string),
Grant_types: d.Get("grant_types").([]interface{}),
App_type: d.Get("app_type").(string),
Custom_login_page_on: d.Get("custom_login_page_on").(bool),
}

jsonValue, err := json.Marshal(reqClient)
if err != nil {
return err
}
log.Println("Request JSON: " + string(jsonValue))

config := m.(Config)
client := http.Client{}
req, err := http.NewRequest("PATCH", "https://" + config.domain + "/api/v2/clients/" + d.Id(), bytes.NewBuffer(jsonValue))
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer" + config.accessToken)
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
log.Println("Response JSON:" + string(data))

if(resp.StatusCode != 200) {
return errors.New("Error: Invalid status code during update")
}

var respClient Client
err = json.Unmarshal(data, &respClient)
if err != nil {
return err
}

return nil
}

func resourceClientDelete(d *schema.ResourceData, m interface{}) error {
config := m.(Config)
client := http.Client{}
req, err := http.NewRequest("DELETE", "https://" + config.domain + "/api/v2/clients/" + d.Id(), nil)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer" + config.accessToken)

resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
log.Println("Response Status Code:" + string(resp.StatusCode))

if(resp.StatusCode != 204) {
return errors.New("Error: Invalid status code during delete")
}

return nil
}

0 comments on commit e6fd137

Please sign in to comment.