Skip to content

Commit e266267

Browse files
author
maxime.hubert
committed
feat: create resource to manage oauth2 clients
1 parent f7667c2 commit e266267

11 files changed

+635
-0
lines changed

ovh/data_me_api_oauth2_client.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package ovh
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
9+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
10+
"github.com/ovh/terraform-provider-ovh/ovh/helpers"
11+
)
12+
13+
func dataSourceMeApiOauth2Client() *schema.Resource {
14+
return &schema.Resource{
15+
ReadContext: dataSourceMeApiOauth2ClientRead,
16+
Schema: map[string]*schema.Schema{
17+
"callback_urls": {
18+
Type: schema.TypeList,
19+
Description: "Callback URLs of the applications using this oauth2 client. Required if using the AUTHORIZATION_CODE flow.",
20+
Elem: &schema.Schema{
21+
Type: schema.TypeString,
22+
},
23+
Computed: true,
24+
},
25+
"client_id": {
26+
Type: schema.TypeString,
27+
Description: "Client ID for the oauth2 client, generated during the resource creation.",
28+
Required: true,
29+
},
30+
"client_secret": {
31+
Type: schema.TypeString,
32+
Description: "Secret for the oauth2 client, generated during the oauth2 client creation. Can be specified in the data resource.",
33+
Optional: true,
34+
Sensitive: true,
35+
},
36+
"description": {
37+
Type: schema.TypeString,
38+
Description: "A description of your oauth2 client.",
39+
Computed: true,
40+
},
41+
"identity": {
42+
Type: schema.TypeString,
43+
Description: "URN that will allow you to associate this oauth2 client with an access policy.",
44+
Computed: true,
45+
},
46+
"flow": {
47+
Type: schema.TypeString,
48+
Description: "OAuth2 flow type implemented for this oauth2 client. Can be either AUTHORIZATION_CODE or CLIENT_CREDENTIALS",
49+
Computed: true,
50+
},
51+
"name": {
52+
Type: schema.TypeString,
53+
Computed: true,
54+
},
55+
},
56+
}
57+
}
58+
59+
func dataSourceMeApiOauth2ClientRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
60+
config := meta.(*Config)
61+
62+
serviceAccount := &ApiOauth2ClientReadResponse{}
63+
64+
// Query the oauth2 client using its client ID
65+
endpoint := fmt.Sprintf("/me/api/oauth2/client/%s", d.Get("client_id").(string))
66+
if err := config.OVHClient.GetWithContext(ctx, endpoint, serviceAccount); err != nil {
67+
return diag.FromErr(helpers.CheckDeleted(d, err, endpoint))
68+
}
69+
70+
log.Printf("[DEBUG] Read oauth2 client: %s", endpoint)
71+
72+
// Populate the state with the response body parameters
73+
d.SetId(serviceAccount.ClientId)
74+
d.Set("callback_urls", serviceAccount.CallbackUrls)
75+
d.Set("client_id", serviceAccount.ClientId)
76+
d.Set("description", serviceAccount.Description)
77+
d.Set("flow", serviceAccount.Flow)
78+
d.Set("identity", serviceAccount.Identity)
79+
d.Set("name", serviceAccount.Name)
80+
81+
return nil
82+
}

ovh/data_me_api_oauth2_client_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package ovh
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
7+
)
8+
9+
// Tests valid configurations to create oauth2 clients
10+
func TestAccMeApiOauth2Client_data(t *testing.T) {
11+
const resourceName = "ovh_me_api_oauth2_client.service_account_1"
12+
13+
// Successful test with app required parameters,
14+
// that validates the use of the data instruction
15+
const okConfigClientCredentials = `
16+
resource "ovh_me_api_oauth2_client" "service_account_1" {
17+
description = "tf acc test client credentials"
18+
name = "tf acc test client credentials"
19+
flow = "CLIENT_CREDENTIALS"
20+
}
21+
data "ovh_me_api_oauth2_client" "service_account_1" {
22+
client_id = ovh_me_api_oauth2_client.service_account_1.client_id
23+
depends_on = [ovh_me_api_oauth2_client.service_account_1]
24+
}
25+
output "oauth2_client_name" {
26+
value = data.ovh_me_api_oauth2_client.service_account_1.name
27+
28+
}`
29+
resource.Test(t, resource.TestCase{
30+
PreCheck: func() { testAccPreCheckCredentials(t) },
31+
Providers: testAccProviders,
32+
Steps: []resource.TestStep{
33+
// Create the object, check that the client secret is not empty after creation
34+
{
35+
Config: okConfigClientCredentials,
36+
Check: resource.ComposeTestCheckFunc(
37+
resource.TestCheckResourceAttrWith(resourceName, "client_id", apiOauth2ClientStringNotEmpty),
38+
resource.TestCheckResourceAttrWith(resourceName, "client_secret", apiOauth2ClientStringNotEmpty),
39+
resource.TestCheckOutput(
40+
"oauth2_client_name", "tf acc test client credentials",
41+
),
42+
),
43+
},
44+
},
45+
})
46+
}

ovh/data_me_api_oauth2_clients.go

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package ovh
2+
3+
import (
4+
"context"
5+
"sort"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
8+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
9+
"github.com/ovh/terraform-provider-ovh/ovh/helpers/hashcode"
10+
)
11+
12+
func dataSourceMeApiOauth2Clients() *schema.Resource {
13+
return &schema.Resource{
14+
ReadContext: dataSourceMeApiOauth2ClientsRead,
15+
Schema: map[string]*schema.Schema{
16+
"client_ids": {
17+
Type: schema.TypeSet,
18+
Elem: &schema.Schema{Type: schema.TypeString},
19+
Computed: true,
20+
},
21+
},
22+
}
23+
}
24+
25+
func dataSourceMeApiOauth2ClientsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
26+
config := meta.(*Config)
27+
28+
var oAuth2ClientsIds []string
29+
err := config.OVHClient.GetWithContext(ctx, "/me/api/oauth2/client", &oAuth2ClientsIds)
30+
if err != nil {
31+
return diag.FromErr(err)
32+
}
33+
34+
d.Set("client_ids", oAuth2ClientsIds)
35+
36+
sort.Strings(oAuth2ClientsIds)
37+
d.SetId(hashcode.Strings(oAuth2ClientsIds))
38+
return nil
39+
}
+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package ovh
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
8+
)
9+
10+
// Returns an error if an array of strings is empty,
11+
// Used in the calls to resource.TestCheckResourceAttrWith() below
12+
func ApiOauth2ClientArrayNotEmpty(a []string) error {
13+
if len(a) > 0 {
14+
return nil
15+
}
16+
return fmt.Errorf("Array is empty")
17+
}
18+
19+
// Tests valid configurations to read all oauth2 clients
20+
func TestAccMeApiOauth2Clients_data(t *testing.T) {
21+
// Successful test with app required parameters,
22+
// that validates the use of the data instruction
23+
// We create a resource beforehand, to make sure that at least one service account exists
24+
const okConfigClientCredentials = `
25+
resource "ovh_me_api_oauth2_client" "service_account_1" {
26+
description = "tf acc test client credentials"
27+
name = "tf acc test client credentials"
28+
flow = "CLIENT_CREDENTIALS"
29+
}
30+
# A data source listing all the client ids in the account
31+
data "ovh_me_api_oauth2_clients" "all_clients_ref" {
32+
depends_on = [ovh_me_api_oauth2_client.service_account_1]
33+
}
34+
35+
output "is_array_length_gt_0" {
36+
value = length(data.ovh_me_api_oauth2_clients.all_clients_ref.client_ids) > 0
37+
}
38+
`
39+
resource.Test(t, resource.TestCase{
40+
PreCheck: func() { testAccPreCheckCredentials(t) },
41+
Providers: testAccProviders,
42+
Steps: []resource.TestStep{
43+
// Create the object, check that the client secret is not empty after creation
44+
{
45+
Config: okConfigClientCredentials,
46+
Check: resource.ComposeTestCheckFunc(
47+
resource.TestCheckOutput(
48+
"is_array_length_gt_0", "true",
49+
),
50+
),
51+
},
52+
},
53+
})
54+
}

ovh/provider.go

+3
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ func Provider() *schema.Provider {
118118
"ovh_iploadbalancing_vrack_network": dataSourceIpLoadbalancingVrackNetwork(),
119119
"ovh_iploadbalancing_vrack_networks": dataSourceIpLoadbalancingVrackNetworks(),
120120
"ovh_me": dataSourceMe(),
121+
"ovh_me_api_oauth2_client": dataSourceMeApiOauth2Client(),
122+
"ovh_me_api_oauth2_clients": dataSourceMeApiOauth2Clients(),
121123
"ovh_me_identity_group": dataSourceMeIdentityGroup(),
122124
"ovh_me_identity_groups": dataSourceMeIdentityGroups(),
123125
"ovh_me_identity_user": dataSourceMeIdentityUser(),
@@ -208,6 +210,7 @@ func Provider() *schema.Provider {
208210
"ovh_iploadbalancing_tcp_route_rule": resourceIPLoadbalancingTcpRouteRule(),
209211
"ovh_iploadbalancing_vrack_network": resourceIPLoadbalancingVrackNetwork(),
210212
"ovh_me_identity_group": resourceMeIdentityGroup(),
213+
"ovh_me_api_oauth2_client": resourceApiOauth2Client(),
211214
"ovh_me_identity_user": resourceMeIdentityUser(),
212215
"ovh_me_installation_template": resourceMeInstallationTemplate(),
213216
"ovh_me_installation_template_partition_scheme": resourceMeInstallationTemplatePartitionScheme(),

0 commit comments

Comments
 (0)