Skip to content

Commit a3dd86f

Browse files
authored
added auth0 token data source (#11)
* added auth0 token data source * fix example
1 parent 4048257 commit a3dd86f

File tree

11 files changed

+378
-16
lines changed

11 files changed

+378
-16
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ terraform {
2525
required_providers {
2626
curl2 = {
2727
source = "mehulgohil/curl2"
28-
version = "1.5.0"
28+
version = "1.6.0"
2929
}
3030
}
3131
}

curl2/data_sorce_auth0_token.go

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
package curl2
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/json"
7+
"github.com/hashicorp/terraform-plugin-framework/attr"
8+
"github.com/hashicorp/terraform-plugin-framework/datasource"
9+
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
10+
"github.com/hashicorp/terraform-plugin-framework/path"
11+
"github.com/hashicorp/terraform-plugin-framework/types"
12+
"io"
13+
"net/http"
14+
"os"
15+
)
16+
17+
var (
18+
_ datasource.DataSource = &auth0TokenDataSource{}
19+
_ datasource.DataSourceWithConfigure = &auth0TokenDataSource{}
20+
)
21+
22+
func NewAuth0TokenDataSource() datasource.DataSource {
23+
return &auth0TokenDataSource{}
24+
}
25+
26+
type auth0TokenDataModelRequest struct {
27+
Audience types.String `tfsdk:"audience"`
28+
Response types.Object `tfsdk:"response"`
29+
}
30+
31+
type tokenRequestBody struct {
32+
ClientID string `json:"client_id"`
33+
ClientSecret string `json:"client_secret"`
34+
Audience string `json:"audience"`
35+
GrantType string `json:"grant_type"`
36+
}
37+
38+
type tokenResponseBody struct {
39+
AccessToken string `json:"access_token"`
40+
TokenType string `json:"token_type"`
41+
}
42+
type auth0TokenDataSource struct{}
43+
44+
func (a *auth0TokenDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
45+
if req.ProviderData == nil {
46+
return
47+
}
48+
}
49+
50+
func (a *auth0TokenDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
51+
resp.TypeName = req.ProviderTypeName + "_auth0_token"
52+
}
53+
54+
func (a *auth0TokenDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
55+
resp.Schema = schema.Schema{
56+
Description: "Fetches Auth0 Token",
57+
Attributes: map[string]schema.Attribute{
58+
"audience": schema.StringAttribute{
59+
Description: "The audience for the token, which is your API. Example: \"https://xyz.com\"",
60+
Required: true,
61+
},
62+
"response": schema.ObjectAttribute{
63+
AttributeTypes: map[string]attr.Type{
64+
"token": types.StringType,
65+
},
66+
Description: "Token response.",
67+
Computed: true,
68+
},
69+
},
70+
}
71+
}
72+
73+
func (a *auth0TokenDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
74+
var config auth0TokenDataModelRequest
75+
76+
diags := req.Config.Get(ctx, &config)
77+
resp.Diagnostics.Append(diags...)
78+
if resp.Diagnostics.HasError() {
79+
return
80+
}
81+
82+
clientID := os.Getenv("AUTH0_CLIENT_ID")
83+
clientSecret := os.Getenv("AUTH0_CLIENT_SECRET")
84+
domain := os.Getenv("AUTH0_DOMAIN")
85+
86+
if clientID == "" {
87+
resp.Diagnostics.AddAttributeError(
88+
path.Root("client_id"),
89+
"Missing Auth0 Client ID",
90+
"The data source cannot get the token as client id is missing in provider auth0 block",
91+
)
92+
}
93+
94+
if clientSecret == "" {
95+
resp.Diagnostics.AddAttributeError(
96+
path.Root("client_secret"),
97+
"Missing Auth0 Client Secret",
98+
"The data source cannot get the token as client secret is missing in provider auth0 block",
99+
)
100+
}
101+
102+
if domain == "" {
103+
resp.Diagnostics.AddAttributeError(
104+
path.Root("domain"),
105+
"Missing Auth0 Domain",
106+
"The data source cannot get the token as domain is missing in provider auth0 block",
107+
)
108+
}
109+
110+
if config.Audience.ValueString() == "" {
111+
resp.Diagnostics.AddAttributeError(
112+
path.Root("audience"),
113+
"Missing Auth0 Audience",
114+
"The data source cannot get the token as audience is missing",
115+
)
116+
}
117+
118+
if resp.Diagnostics.HasError() {
119+
return
120+
}
121+
122+
url := domain + "/oauth/token"
123+
124+
payload, err := json.Marshal(tokenRequestBody{
125+
ClientID: clientID,
126+
ClientSecret: clientSecret,
127+
Audience: config.Audience.ValueString(),
128+
GrantType: "client_credentials",
129+
})
130+
if err != nil {
131+
resp.Diagnostics.AddError(
132+
"Error marshalling json to get auth0 token",
133+
err.Error(),
134+
)
135+
return
136+
}
137+
138+
request, err := http.NewRequest("POST", url, bytes.NewReader(payload))
139+
if err != nil {
140+
resp.Diagnostics.AddError(
141+
"Error generating new request auth0 token",
142+
err.Error(),
143+
)
144+
return
145+
}
146+
request.Header.Add("content-type", "application/json")
147+
148+
res, err := http.DefaultClient.Do(request)
149+
if err != nil {
150+
resp.Diagnostics.AddError(
151+
"Error sending HTTP request to get auth0 token",
152+
err.Error(),
153+
)
154+
return
155+
}
156+
157+
defer res.Body.Close()
158+
body, err := io.ReadAll(res.Body)
159+
if err != nil {
160+
resp.Diagnostics.AddError(
161+
"Error reading body of response from auth0",
162+
err.Error(),
163+
)
164+
return
165+
}
166+
167+
var response tokenResponseBody
168+
err = json.Unmarshal(body, &response)
169+
if err != nil {
170+
resp.Diagnostics.AddError(
171+
"Error unmarshalling body of response from auth0",
172+
err.Error(),
173+
)
174+
return
175+
}
176+
177+
config.Response, diags = types.ObjectValue(
178+
map[string]attr.Type{
179+
"token": types.StringType,
180+
},
181+
map[string]attr.Value{
182+
"token": types.StringValue(response.AccessToken),
183+
},
184+
)
185+
resp.Diagnostics.Append(diags...)
186+
if resp.Diagnostics.HasError() {
187+
return
188+
}
189+
190+
diags = resp.State.Set(ctx, &config)
191+
resp.Diagnostics.Append(diags...)
192+
if resp.Diagnostics.HasError() {
193+
return
194+
}
195+
}

curl2/provider.go

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ type curl2ProviderModel struct {
2828
TimeoutMS types.Int64 `tfsdk:"timeout_ms"`
2929
Retry types.Object `tfsdk:"retry"`
3030
AzureAD types.Object `tfsdk:"azure_ad"`
31+
Auth0 types.Object `tfsdk:"auth0"`
3132
}
3233

3334
type retryModel struct {
@@ -42,6 +43,12 @@ type azureADModel struct {
4243
TenantID types.String `tfsdk:"tenant_id"`
4344
}
4445

46+
type auth0Model struct {
47+
ClientID types.String `tfsdk:"client_id"`
48+
ClientSecret types.String `tfsdk:"client_secret"`
49+
Domain types.String `tfsdk:"domain"`
50+
}
51+
4552
func (c *curl2Provider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
4653
resp.TypeName = "curl2"
4754
}
@@ -95,6 +102,23 @@ func (c *curl2Provider) Schema(_ context.Context, _ provider.SchemaRequest, resp
95102
},
96103
},
97104
},
105+
"auth0": schema.SingleNestedBlock{
106+
Description: "Auth0 Configuration which is required if you are using `curl2_auth0_token` data",
107+
Attributes: map[string]schema.Attribute{
108+
"client_id": schema.StringAttribute{
109+
Description: "Application's Client ID. You can also set is as ENV variable `AUTH0_CLIENT_ID`",
110+
Optional: true,
111+
},
112+
"client_secret": schema.StringAttribute{
113+
Description: "Application's Client Secret. You can also set is as ENV variable `AUTH0_CLIENT_SECRET`",
114+
Optional: true,
115+
},
116+
"domain": schema.StringAttribute{
117+
Description: "Auth0 domain URL in the format `https://<your-tenant-name>.auth0.com`. You can also set is as ENV variable `AUTH0_DOMAIN`",
118+
Optional: true,
119+
},
120+
},
121+
},
98122
},
99123
}
100124
}
@@ -143,8 +167,41 @@ func (c *curl2Provider) Configure(ctx context.Context, req provider.ConfigureReq
143167
}
144168
}
145169

146-
var retry retryModel
170+
var auth0Config auth0Model
171+
if !config.Auth0.IsNull() && !config.Auth0.IsUnknown() {
172+
diags = config.Auth0.As(ctx, &auth0Config, basetypes.ObjectAsOptions{})
173+
resp.Diagnostics.Append(diags...)
174+
if resp.Diagnostics.HasError() {
175+
return
176+
}
147177

178+
err := os.Setenv("AUTH0_CLIENT_ID", auth0Config.ClientID.ValueString())
179+
if err != nil {
180+
resp.Diagnostics.AddError(
181+
"Unable to set AUTH0_CLIENT_ID Env Variables",
182+
err.Error(),
183+
)
184+
return
185+
}
186+
err = os.Setenv("AUTH0_CLIENT_SECRET", auth0Config.ClientSecret.ValueString())
187+
if err != nil {
188+
resp.Diagnostics.AddError(
189+
"Unable to set AUTH0_CLIENT_SECRET Env Variables",
190+
err.Error(),
191+
)
192+
return
193+
}
194+
err = os.Setenv("AUTH0_DOMAIN", auth0Config.Domain.ValueString())
195+
if err != nil {
196+
resp.Diagnostics.AddError(
197+
"Unable to set AUTH0_DOMAIN Env Variables",
198+
err.Error(),
199+
)
200+
return
201+
}
202+
}
203+
204+
var retry retryModel
148205
if !config.Retry.IsNull() && !config.Retry.IsUnknown() {
149206
diags = config.Retry.As(ctx, &retry, basetypes.ObjectAsOptions{})
150207
resp.Diagnostics.Append(diags...)
@@ -169,6 +226,7 @@ func (c *curl2Provider) DataSources(ctx context.Context) []func() datasource.Dat
169226
return []func() datasource.DataSource{
170227
NewCurl2DataSource,
171228
NewAzureADTokenDataSource,
229+
NewAuth0TokenDataSource,
172230
}
173231
}
174232

docs/data-sources/auth0_token.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "curl2_auth0_token Data Source - terraform-provider-curl2"
4+
subcategory: ""
5+
description: |-
6+
Fetches Auth0 Token
7+
---
8+
9+
# curl2_auth0_token (Data Source)
10+
11+
Fetches Auth0 Token
12+
13+
## Example Usage
14+
15+
```terraform
16+
terraform {
17+
required_providers {
18+
curl2 = {
19+
source = "mehulgohil/curl2"
20+
version = "1.6.0"
21+
}
22+
}
23+
}
24+
25+
provider "curl2" {
26+
auth0 {
27+
client_id = "<AUTH0_CLIENT_ID>" //You can also set ENV AUTH0_CLIENT_ID
28+
client_secret = "<AUTH0_CLIENT_SECRET>" //You can also set ENV AUTH0_CLIENT_SECRET
29+
domain = "<AUTH0_DOMAIN>" //You can also set ENV AUTH0_DOMAIN
30+
}
31+
}
32+
33+
data "curl2_auth0_token" auth0Token {
34+
audience = "https://xyx.fy"
35+
}
36+
37+
output "auth_token" {
38+
value = data.curl2_auth0_token.auth0Token.response
39+
}
40+
```
41+
42+
<!-- schema generated by tfplugindocs -->
43+
## Schema
44+
45+
### Required
46+
47+
- `audience` (String) The audience for the token, which is your API. Example: "https://xyz.com"
48+
49+
### Read-Only
50+
51+
- `response` (Object) Token response. (see [below for nested schema](#nestedatt--response))
52+
53+
<a id="nestedatt--response"></a>
54+
### Nested Schema for `response`
55+
56+
Read-Only:
57+
58+
- `token` (String)
59+
60+

docs/data-sources/azuread_token.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ terraform {
2323
}
2424
2525
provider "curl2" {
26-
azure_ad {
27-
client_id = "<AZURE_CLIENT_ID>" //You can also set ENV AZURE_CLIENT_ID
28-
client_secret = "<AZURE_CLIENT_SECRET>" //You can also set ENV AZURE_CLIENT_SECRET
29-
tenant_id = "<AZURE_TENANT_ID>" //You can also set ENV AZURE_TENANT_ID
30-
}
26+
azure_ad {
27+
client_id = "<AZURE_CLIENT_ID>" //You can also set ENV AZURE_CLIENT_ID
28+
client_secret = "<AZURE_CLIENT_SECRET>" //You can also set ENV AZURE_CLIENT_SECRET
29+
tenant_id = "<AZURE_TENANT_ID>" //You can also set ENV AZURE_TENANT_ID
30+
}
3131
}
3232
3333
data "curl2_azuread_token" azureADToken {

docs/data-sources/curl2.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ terraform {
1717
required_providers {
1818
curl2 = {
1919
source = "mehulgohil/curl2"
20-
version = "1.5.0"
20+
version = "1.6.0"
2121
}
2222
}
2323
}

0 commit comments

Comments
 (0)