forked from christianbumann/terraform-provider-azuredevops
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathresource_serviceendpoint_azurerm.go
144 lines (125 loc) · 5.77 KB
/
resource_serviceendpoint_azurerm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package azuredevops
import (
"fmt"
"strings"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/microsoft/azure-devops-go-api/azuredevops/serviceendpoint"
crud "github.com/microsoft/terraform-provider-azuredevops/azuredevops/crud/serviceendpoint"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/converter"
"github.com/microsoft/terraform-provider-azuredevops/azuredevops/utils/tfhelper"
)
func resourceServiceEndpointAzureRM() *schema.Resource {
r := crud.GenBaseServiceEndpointResource(flattenServiceEndpointAzureRM, expandServiceEndpointAzureRM, parseImportedProjectIDAndServiceEndpointID)
crud.MakeUnprotectedSchema(r, "azurerm_spn_tenantid", "ARM_TENANT_ID", "The service principal tenant id which should be used.")
crud.MakeUnprotectedSchema(r, "azurerm_subscription_id", "ARM_SUBSCRIPTION_ID", "The Azure subscription Id which should be used.")
crud.MakeUnprotectedSchema(r, "azurerm_subscription_name", "ARM_SUBSCRIPTION_NAME", "The Azure subscription name which should be used.")
r.Schema["resource_group"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Description: "Scope Resource Group",
ConflictsWith: []string{"credentials"},
}
secretHashKey, secretHashSchema := tfhelper.GenerateSecreteMemoSchema("serviceprincipalkey")
r.Schema["credentials"] = &schema.Schema{
Type: schema.TypeList,
Optional: true,
MaxItems: 1,
ForceNew: true,
ConflictsWith: []string{"resource_group"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"serviceprincipalid": {
Type: schema.TypeString,
Required: true,
Description: "The service principal id which should be used.",
},
"serviceprincipalkey": {
Type: schema.TypeString,
Required: true,
Description: "The service principal secret which should be used.",
Sensitive: true,
DiffSuppressFunc: tfhelper.DiffFuncSuppressSecretChanged,
},
secretHashKey: secretHashSchema,
},
},
}
return r
}
// Convert internal Terraform data structure to an AzDO data structure
func expandServiceEndpointAzureRM(d *schema.ResourceData) (*serviceendpoint.ServiceEndpoint, *string, error) {
serviceEndpoint, projectID := crud.DoBaseExpansion(d)
scope := fmt.Sprintf("/subscriptions/%s", d.Get("azurerm_subscription_id"))
scopeLevel := "Subscription"
if _, ok := d.GetOk("resource_group"); ok {
scope += fmt.Sprintf("/resourcegroups/%s", d.Get("resource_group"))
scopeLevel = "ResourceGroup"
}
serviceEndpoint.Authorization = &serviceendpoint.EndpointAuthorization{
Parameters: &map[string]string{
"authenticationType": "spnKey",
"serviceprincipalid": "",
"serviceprincipalkey": "",
"tenantid": d.Get("azurerm_spn_tenantid").(string),
},
Scheme: converter.String("ServicePrincipal"),
}
serviceEndpoint.Data = &map[string]string{
"creationMode": "Automatic",
"environment": "AzureCloud",
"scopeLevel": "Subscription",
"subscriptionId": d.Get("azurerm_subscription_id").(string),
"subscriptionName": d.Get("azurerm_subscription_name").(string),
}
if scopeLevel == "ResourceGroup" {
(*serviceEndpoint.Authorization.Parameters)["scope"] = scope
}
if _, ok := d.GetOk("credentials"); ok {
credentials := d.Get("credentials").([]interface{})[0].(map[string]interface{})
(*serviceEndpoint.Authorization.Parameters)["serviceprincipalid"] = credentials["serviceprincipalid"].(string)
(*serviceEndpoint.Authorization.Parameters)["serviceprincipalkey"] = expandSpnKey(credentials)
(*serviceEndpoint.Data)["creationMode"] = "Manual"
}
serviceEndpoint.Type = converter.String("azurerm")
serviceEndpoint.Url = converter.String("https://management.azure.com/")
return serviceEndpoint, projectID, nil
}
func expandSpnKey(credentials map[string]interface{}) string {
// Note: if this is an update for a field other than `serviceprincipalkey`, the `serviceprincipalkey` will be
// set to `""`. Without catching this case and setting the value to `"null"`, the `serviceprincipalkey` will
// actually be set to `""` by the Azure DevOps service.
//
// This step is critical in order to ensure that the service connection can update without loosing its password!
//
// This behavior is unfortunately not documented in the API documentation.
spnKey, ok := credentials["serviceprincipalkey"]
if !ok || spnKey.(string) == "" {
return "null"
}
return spnKey.(string)
}
func flattenCredentials(serviceEndpoint *serviceendpoint.ServiceEndpoint, hashKey string, hashValue string) interface{} {
return []map[string]interface{}{{
"serviceprincipalid": (*serviceEndpoint.Authorization.Parameters)["serviceprincipalid"],
"serviceprincipalkey": (*serviceEndpoint.Authorization.Parameters)["serviceprincipalkey"],
hashKey: hashValue,
}}
}
// Convert AzDO data structure to internal Terraform data structure
func flattenServiceEndpointAzureRM(d *schema.ResourceData, serviceEndpoint *serviceendpoint.ServiceEndpoint, projectID *string) {
crud.DoBaseFlattening(d, serviceEndpoint, projectID)
scope := (*serviceEndpoint.Authorization.Parameters)["scope"]
if (*serviceEndpoint.Data)["creationMode"] == "Manual" {
newHash, hashKey := tfhelper.HelpFlattenSecretNested(d, "credentials", d.Get("credentials.0").(map[string]interface{}), "serviceprincipalkey")
credentials := flattenCredentials(serviceEndpoint, hashKey, newHash)
d.Set("credentials", credentials)
}
s := strings.SplitN(scope, "/", -1)
if len(s) == 5 {
d.Set("resource_group", s[4])
}
d.Set("azurerm_spn_tenantid", (*serviceEndpoint.Authorization.Parameters)["tenantid"])
d.Set("azurerm_subscription_id", (*serviceEndpoint.Data)["subscriptionId"])
d.Set("azurerm_subscription_name", (*serviceEndpoint.Data)["subscriptionName"])
}