Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add certificate support for Azure Batch #3097

Merged
merged 21 commits into from
Apr 12, 2019
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ type ArmClient struct {
autoscaleSettingsClient insights.AutoscaleSettingsClient

// Batch
batchAccountClient batch.AccountClient
batchPoolClient batch.PoolClient
batchAccountClient batch.AccountClient
batchCertificateClient batch.CertificateClient
batchPoolClient batch.PoolClient

// CDN
cdnCustomDomainsClient cdn.CustomDomainsClient
Expand Down Expand Up @@ -634,6 +635,10 @@ func (c *ArmClient) registerBatchClients(endpoint, subscriptionId string, auth a
c.configureClient(&batchAccount.Client, auth)
c.batchAccountClient = batchAccount

batchCertificateClient := batch.NewCertificateClientWithBaseURI(endpoint, subscriptionId)
c.configureClient(&batchCertificateClient.Client, auth)
c.batchCertificateClient = batchCertificateClient

batchPool := batch.NewPoolClientWithBaseURI(endpoint, subscriptionId)
c.configureClient(&batchPool.Client, auth)
c.batchPoolClient = batchPool
Expand Down
86 changes: 86 additions & 0 deletions azurerm/data_source_batch_certificate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package azurerm

import (
"fmt"
"regexp"

"github.com/hashicorp/terraform/helper/schema"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func dataSourceArmBatchCertificate() *schema.Resource {
return &schema.Resource{
Read: dataSourceArmBatchCertificateRead,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateAzureRMBatchCertificateName,
},
"account_name": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validateAzureRMBatchAccountName,
},
"resource_group_name": resourceGroupNameForDataSourceSchema(),
"public_data": {
Type: schema.TypeString,
Computed: true,
},
"format": {
Type: schema.TypeString,
Computed: true,
},
"thumbprint": {
Type: schema.TypeString,
Computed: true,
},
"thumbprint_algorithm": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceArmBatchCertificateRead(d *schema.ResourceData, meta interface{}) error {
ctx := meta.(*ArmClient).StopContext
client := meta.(*ArmClient).batchCertificateClient

resourceGroupName := d.Get("resource_group_name").(string)
accountName := d.Get("account_name").(string)
name := d.Get("name").(string)

resp, err := client.Get(ctx, resourceGroupName, accountName, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return fmt.Errorf("Error: Batch certificate %q (Account %q / Resource Group %q) was not found", name, accountName, resourceGroupName)
}
return fmt.Errorf("Error making Read request on AzureRM Batch certificate %q: %+v", name, err)
}

d.SetId(*resp.ID)

d.Set("name", resp.Name)
d.Set("account_name", accountName)
d.Set("resource_group_name", resourceGroupName)

if props := resp.CertificateProperties; props != nil {
d.Set("format", props.Format)
d.Set("public_data", props.PublicData)
d.Set("thumbprint", props.Thumbprint)
d.Set("thumbprint_algorithm", props.ThumbprintAlgorithm)
}
stuartleeks marked this conversation as resolved.
Show resolved Hide resolved

return nil
}
func validateAzureRMBatchCertificateName(v interface{}, k string) (warnings []string, errors []error) {
value := v.(string)
if !regexp.MustCompile(`^[\w]+-[\w]+$`).MatchString(value) {
errors = append(errors, fmt.Errorf(
"must be made up of algorithm and thumbprint separated by a dash in %q: %q", k, value))
}

return warnings, errors
}
69 changes: 69 additions & 0 deletions azurerm/data_source_batch_certificate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package azurerm

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf"
)

func TestAccDataSourceAzureRMBatchCertificate(t *testing.T) {
dataSourceName := "data.azurerm_batch_certificate.test"
ri := tf.AccRandTimeInt()
rs := acctest.RandString(4)
location := testLocation()
config := testAccDataSourceAzureRMBatchCertificate(ri, rs, location)

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "name", "SHA1-42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"),
resource.TestCheckResourceAttr(dataSourceName, "account_name", fmt.Sprintf("testaccbatch%s", rs)),
resource.TestCheckResourceAttr(dataSourceName, "format", "Pfx"),
resource.TestCheckResourceAttr(dataSourceName, "public_data", "MIIFqzCCA5OgAwIBAgIJAMs4jwMPq7T1MA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApTb21lLVN0YXRlMRgwFgYDVQQKDA9UZXJyYWZvcm0gVGVzdHMxDjAMBgNVBAsMBUF6dXJlMR4wHAYDVQQDDBVUZXJyYWZvcm0gQXBwIEdhdGV3YXkwHhcNMTYxMTAxMTcxOTEyWhcNMjYxMDMwMTcxOTEyWjBsMQswCQYDVQQGEwJVUzETMBEGA1UECAwKU29tZS1TdGF0ZTEYMBYGA1UECgwPVGVycmFmb3JtIFRlc3RzMQ4wDAYDVQQLDAVBenVyZTEeMBwGA1UEAwwVVGVycmFmb3JtIEFwcCBHYXRld2F5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA49HW2pYIlW/mlaadLA1AsXiV48xVhXAvGVk3DEl1ffjp5bN8rap5WV1D83uMg1Ii7CJM8yNHkRkvN8n5WXFng4R5V1jPxGOTAj+xLybvEASi++GZelWdpOuMk8/nAoKPMbQ5NyKFy5WzlOduMldR7Awt2pwdId3akqm1i9ITG9Js+4P4nYXM8vfJCajILqi4YfhEoCNvS1EUgvlpSFE7pfNhc2W+zsfUWxWmB2SpWwX9MgQ1D4OmdKp+Eo+b6vzst3XArKMHMadPTUAk8H+ZgAnlX9yO+3vQ6z86vma/WgrG2LH6GCGXBjmKlhxVCPMLA5LeRUwEGc/Q7X/ClitGWY9umPN1XVj5e5Di1K2M082Y14mgbTTRTpv/nx7Xlph+MHnVhEWvaGMpqCHuM1W1y7wIS1IREYQ2q+K54xxZSPKYJMSnmj6A0hR/LBV0rL1uVhedEpdviduuO76qCyZrGG4HwBlW4hnIaahLzgqlvlmbDUQonAVPDgi3brVdXJgLv2zi7/ZHFW3IHgDylUVIdig0ccbzxKymlkGQ0RsLBjWOyxak2J8bN5JNVyxSwX43NZqxJ8yOv5xjB+rVMri9SX3Dl5NbFzOjynov601Pmwvb7zYnyttG2Hl5EKrkahjijGRjGy3EWEiBiArLkdTKCDHBlHxykTEvY6ZH5B9waP0CAwEAAaNQME4wHQYDVR0OBBYEFD2/Hq3IivZ5RMOKrPsM7ijIFHmMMB8GA1UdIwQYMBaAFD2/Hq3IivZ5RMOKrPsM7ijIFHmMMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAKxHWO/Q4labjnCVxYi+kaMRCPJUdHj7lga8yi8EGHaL+CbwynkaiyTfPvtmcqiuaZM9BaXsuNMRcHMtXM0EHBsjViwAHk6SrqLXd/opFvMI2QbG93koFUCpczrpyO9GvnRN4iOIYbSPXAdGOB6bkpMbm/XajORoDrua+/ET/X/1FP0GZBTmEFwojuCfOI/VuJXj0OW8XzkLmsXiLpOiakjU1obBup/1lz9DtOEBsiB9Ury+f5gZ+FnZuqhgQxeDxlZ69P6YYAfkzhcfbf7HO+nMKhppAj1BFeR4SBb+F/fLchCGO5yohwkxWz3i2q9gTDhBgo31416viyCKFWSVW3Vn7jbsjZ+Q9MK1jVSOSxC7qoQkRoNy9SKpqylunXZb+K6F3HfBkDQvn3OwsxYiSOcX9JaWpQAInNIZVg+WrJ1PXm8PFIaVPJfMgP3GOdm9vRAMjOM5Bc9iqGr2spimFd5h0GmgLvh35B3jHHWF4i3NupJQ6hUvHQZtYZOxfwxnY0/LVBTyLTVlniFA7dGSI+5Uexm+Pjh7IMGI532jTONlfNm9Bz/jdf1o0FlOclzG6Eif22gml3GM3xCUVlaElylYNAjO2lfvZuRVo5GKdMwtV9acNl0OwSx+0zbMYY2Ni3jQCI4kOL5Csctryf0rHXTlCCvnzBYVDPKmFJPna61T"),
resource.TestCheckResourceAttr(dataSourceName, "thumbprint", "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"),
resource.TestCheckResourceAttr(dataSourceName, "thumbprint_algorithm", "SHA1"),
),
},
},
})
}

func testAccDataSourceAzureRMBatchCertificate(rInt int, rString string, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "testaccbatch%d"
location = "%s"
}

resource "azurerm_batch_account" "test" {
name = "testaccbatch%s"
resource_group_name = "${azurerm_resource_group.test.name}"
location = "${azurerm_resource_group.test.location}"
pool_allocation_mode = "BatchService"
}

resource "azurerm_batch_certificate" "test" {
resource_group_name = "${azurerm_resource_group.test.name}"
account_name = "${azurerm_batch_account.test.name}"
certificate = "${base64encode(file("testdata/batch_certificate.pfx"))}"
format = "Pfx"
password = "terraform"
thumbprint = "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"
thumbprint_algorithm = "SHA1"
}

data "azurerm_batch_certificate" "test" {
name = "${azurerm_batch_certificate.test.name}"
account_name = "${azurerm_batch_account.test.name}"
resource_group_name = "${azurerm_resource_group.test.name}"
}

`, rInt, location, rString)
}
39 changes: 39 additions & 0 deletions azurerm/data_source_batch_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"fmt"

"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

Expand Down Expand Up @@ -108,6 +110,39 @@ func dataSourceArmBatchPool() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"certificate": {
Type: schema.TypeList,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Required: true,
ValidateFunc: azure.ValidateResourceID,
},
"store_location": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"CurrentUser",
"LocalMachine",
}, false),
},
"store_name": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validate.NoEmptyStrings,
},
"visibility": {
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{
Type: schema.TypeString,
},
},
},
},
},
"start_task": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -216,6 +251,10 @@ func dataSourceArmBatchPoolRead(d *schema.ResourceData, meta interface{}) error
d.Set("node_agent_sku_id", props.DeploymentConfiguration.VirtualMachineConfiguration.NodeAgentSkuID)
}

if err := d.Set("certificate", azure.FlattenBatchPoolCertificateReferences(props.Certificates)); err != nil {
return fmt.Errorf("error setting `certificate`: %v", err)
}

d.Set("start_task", azure.FlattenBatchPoolStartTask(props.StartTask))
}

Expand Down
23 changes: 23 additions & 0 deletions azurerm/data_source_batch_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ func TestAccDataSourceAzureRMBatchPool_complete(t *testing.T) {
resource.TestCheckResourceAttr(dataSourceName, "start_task.0.user_identity.0.auto_user.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "start_task.0.user_identity.0.auto_user.0.scope", "Task"),
resource.TestCheckResourceAttr(dataSourceName, "start_task.0.user_identity.0.auto_user.0.elevation_level", "NonAdmin"),
resource.TestCheckResourceAttr(dataSourceName, "certificate.#", "1"),
resource.TestCheckResourceAttrSet(dataSourceName, "certificate.0.id"),
resource.TestCheckResourceAttr(dataSourceName, "certificate.0.store_location", "CurrentUser"),
resource.TestCheckResourceAttr(dataSourceName, "certificate.0.store_name", ""),
resource.TestCheckResourceAttr(dataSourceName, "certificate.0.visibility.#", "2"),
resource.TestCheckResourceAttr(dataSourceName, "certificate.0.visibility.3294600504", "StartTask"),
resource.TestCheckResourceAttr(dataSourceName, "certificate.0.visibility.4077195354", "RemoteUser"),
),
},
},
Expand Down Expand Up @@ -78,6 +85,16 @@ resource "azurerm_batch_account" "test" {
env = "test"
}
}
resource "azurerm_batch_certificate" "test" {
resource_group_name = "${azurerm_resource_group.test.name}"
account_name = "${azurerm_batch_account.test.name}"
certificate = "${base64encode(file("testdata/batch_certificate.pfx"))}"
format = "Pfx"
password = "terraform"
thumbprint = "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"
thumbprint_algorithm = "SHA1"
}


resource "azurerm_batch_pool" "test" {
name = "testaccpool%s"
Expand All @@ -100,6 +117,12 @@ resource "azurerm_batch_pool" "test" {
version = "latest"
}

certificate = {
id = "${azurerm_batch_certificate.test.id}"
store_location = "CurrentUser"
visibility = [ "StartTask", "RemoteUser" ]
}

start_task {
command_line = "echo 'Hello World from $env'"
max_task_retry_count = 1
Expand Down
69 changes: 69 additions & 0 deletions azurerm/helpers/azure/batch_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"regexp"

"github.com/Azure/azure-sdk-for-go/services/batch/mgmt/2017-09-01/batch"
"github.com/hashicorp/terraform/helper/schema"
)

// FlattenBatchPoolAutoScaleSettings flattens the auto scale settings for a Batch pool
Expand Down Expand Up @@ -135,6 +136,34 @@ func FlattenBatchPoolStartTask(startTask *batch.StartTask) []interface{} {
return append(results, result)
}

// FlattenBatchPoolCertificateReferences flattens a Batch pool certificate reference
func FlattenBatchPoolCertificateReferences(armCertificates *[]batch.CertificateReference) []interface{} {
if armCertificates == nil {
return []interface{}{}
}
output := make([]interface{}, 0)

for _, armCertificate := range *armCertificates {
stuartleeks marked this conversation as resolved.
Show resolved Hide resolved
certificate := map[string]interface{}{}
if armCertificate.ID != nil {
certificate["id"] = *armCertificate.ID
}
certificate["store_location"] = string(armCertificate.StoreLocation)
if armCertificate.StoreName != nil {
certificate["store_name"] = *armCertificate.StoreName
}
visibility := &schema.Set{F: schema.HashString}
if armCertificate.Visibility != nil {
for _, armVisibility := range *armCertificate.Visibility {
visibility.Add(string(armVisibility))
}
}
certificate["visibility"] = visibility
output = append(output, certificate)
}
return output
}

// ExpandBatchPoolImageReference expands Batch pool image reference
func ExpandBatchPoolImageReference(list []interface{}) (*batch.ImageReference, error) {
if len(list) == 0 {
Expand All @@ -158,6 +187,46 @@ func ExpandBatchPoolImageReference(list []interface{}) (*batch.ImageReference, e
return imageRef, nil
}

// ExpandBatchPoolCertificateReferences expands Batch pool certificate references
func ExpandBatchPoolCertificateReferences(list []interface{}) (*[]batch.CertificateReference, error) {
result := []batch.CertificateReference{}

for _, tempItem := range list {
item := tempItem.(map[string]interface{})
certificateReference, err := expandBatchPoolCertificateReference(item)
if err != nil {
return nil, err
}
result = append(result, *certificateReference)
}
return &result, nil
}

func expandBatchPoolCertificateReference(ref map[string]interface{}) (*batch.CertificateReference, error) {
if len(ref) == 0 {
return nil, fmt.Errorf("Error: storage image reference should be defined")
}

id := ref["id"].(string)
storeLocation := ref["store_location"].(string)
storeName := ref["store_name"].(string)
visibilityRefs := ref["visibility"].(*schema.Set)
visibility := []batch.CertificateVisibility{}
if visibilityRefs != nil {
for _, visibilityRef := range visibilityRefs.List() {
visibility = append(visibility, batch.CertificateVisibility(visibilityRef.(string)))
}
}

certificateReference := &batch.CertificateReference{
ID: &id,
StoreLocation: batch.CertificateStoreLocation(storeLocation),
StoreName: &storeName,
Visibility: &visibility,
}
return certificateReference, nil
}

// ExpandBatchPoolStartTask expands Batch pool start task
func ExpandBatchPoolStartTask(list []interface{}) (*batch.StartTask, error) {
if len(list) == 0 {
Expand Down
2 changes: 2 additions & 0 deletions azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_azuread_application": dataSourceArmAzureADApplication(),
"azurerm_azuread_service_principal": dataSourceArmActiveDirectoryServicePrincipal(),
"azurerm_batch_account": dataSourceArmBatchAccount(),
"azurerm_batch_certificate": dataSourceArmBatchCertificate(),
"azurerm_batch_pool": dataSourceArmBatchPool(),
"azurerm_builtin_role_definition": dataSourceArmBuiltInRoleDefinition(),
"azurerm_cdn_profile": dataSourceArmCdnProfile(),
Expand Down Expand Up @@ -205,6 +206,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_azuread_service_principal_password": resourceArmActiveDirectoryServicePrincipalPassword(),
"azurerm_azuread_service_principal": resourceArmActiveDirectoryServicePrincipal(),
"azurerm_batch_account": resourceArmBatchAccount(),
"azurerm_batch_certificate": resourceArmBatchCertificate(),
"azurerm_batch_pool": resourceArmBatchPool(),
"azurerm_cdn_endpoint": resourceArmCdnEndpoint(),
"azurerm_cdn_profile": resourceArmCdnProfile(),
Expand Down
Loading