Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7285 from terraform-providers/d/kv-certificate-da…
…tasource New data source azurerm_key_vault_certificate
- Loading branch information
Showing
5 changed files
with
593 additions
and
0 deletions.
There are no files selected for viewing
382 changes: 382 additions & 0 deletions
382
azurerm/internal/services/keyvault/key_vault_certificate_data_source.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,382 @@ | ||
package keyvault | ||
|
||
import ( | ||
"encoding/base64" | ||
"encoding/hex" | ||
"fmt" | ||
"log" | ||
"strings" | ||
"time" | ||
|
||
"github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/clients" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/tags" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" | ||
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" | ||
) | ||
|
||
func dataSourceArmKeyVaultCertificate() *schema.Resource { | ||
return &schema.Resource{ | ||
Read: dataSourceArmKeyVaultCertificateRead, | ||
|
||
Timeouts: &schema.ResourceTimeout{ | ||
Read: schema.DefaultTimeout(5 * time.Minute), | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: azure.ValidateKeyVaultChildName, | ||
}, | ||
|
||
"key_vault_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: azure.ValidateResourceID, | ||
}, | ||
|
||
"version": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
}, | ||
|
||
// Computed | ||
"certificate_policy": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"issuer_parameters": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"key_properties": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"exportable": { | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
}, | ||
"key_size": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
"key_type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"reuse_key": { | ||
Type: schema.TypeBool, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"lifetime_action": { | ||
Type: schema.TypeList, | ||
Optional: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"action": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"action_type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"trigger": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"days_before_expiry": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
"lifetime_percentage": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"secret_properties": { | ||
Type: schema.TypeList, | ||
Required: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"content_type": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"x509_certificate_properties": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"extended_key_usage": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
"key_usage": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
"subject": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
"subject_alternative_names": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"emails": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
"dns_names": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
"upns": { | ||
Type: schema.TypeList, | ||
Computed: true, | ||
Elem: &schema.Schema{ | ||
Type: schema.TypeString, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"validity_in_months": { | ||
Type: schema.TypeInt, | ||
Computed: true, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
|
||
"secret_id": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"certificate_data": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"thumbprint": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"tags": tags.SchemaDataSource(), | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceArmKeyVaultCertificateRead(d *schema.ResourceData, meta interface{}) error { | ||
vaultClient := meta.(*clients.Client).KeyVault.VaultsClient | ||
client := meta.(*clients.Client).KeyVault.ManagementClient | ||
ctx, cancel := timeouts.ForRead(meta.(*clients.Client).StopContext, d) | ||
defer cancel() | ||
|
||
name := d.Get("name").(string) | ||
keyVaultId := d.Get("key_vault_id").(string) | ||
version := d.Get("version").(string) | ||
|
||
keyVaultBaseUri, err := azure.GetKeyVaultBaseUrlFromID(ctx, vaultClient, keyVaultId) | ||
if err != nil { | ||
return fmt.Errorf("Error looking up Key %q vault url from id %q: %+v", name, keyVaultId, err) | ||
} | ||
|
||
cert, err := client.GetCertificate(ctx, keyVaultBaseUri, name, version) | ||
if err != nil { | ||
if utils.ResponseWasNotFound(cert.Response) { | ||
log.Printf("[DEBUG] Certificate %q was not found in Key Vault at URI %q - removing from state", name, keyVaultBaseUri) | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
return fmt.Errorf("Error reading Key Vault Certificate: %+v", err) | ||
} | ||
|
||
if cert.ID == nil || *cert.ID == "" { | ||
return fmt.Errorf("failure reading Key Vault Certificate ID for %q", name) | ||
} | ||
|
||
d.SetId(*cert.ID) | ||
|
||
id, err := azure.ParseKeyVaultChildID(*cert.ID) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.Set("name", id.Name) | ||
|
||
certificatePolicy := flattenKeyVaultCertificatePolicyForDataSource(cert.Policy) | ||
if err := d.Set("certificate_policy", certificatePolicy); err != nil { | ||
return fmt.Errorf("Error setting Key Vault Certificate Policy: %+v", err) | ||
} | ||
|
||
d.Set("version", id.Version) | ||
d.Set("secret_id", cert.Sid) | ||
|
||
certificateData := "" | ||
if contents := cert.Cer; contents != nil { | ||
certificateData = strings.ToUpper(hex.EncodeToString(*contents)) | ||
} | ||
d.Set("certificate_data", certificateData) | ||
|
||
thumbprint := "" | ||
if v := cert.X509Thumbprint; v != nil { | ||
x509Thumbprint, err := base64.RawURLEncoding.DecodeString(*v) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
thumbprint = strings.ToUpper(hex.EncodeToString(x509Thumbprint)) | ||
} | ||
d.Set("thumbprint", thumbprint) | ||
|
||
return tags.FlattenAndSet(d, cert.Tags) | ||
} | ||
|
||
func flattenKeyVaultCertificatePolicyForDataSource(input *keyvault.CertificatePolicy) []interface{} { | ||
policy := make(map[string]interface{}) | ||
|
||
if params := input.IssuerParameters; params != nil { | ||
issuerParams := make(map[string]interface{}) | ||
issuerParams["name"] = *params.Name | ||
policy["issuer_parameters"] = []interface{}{issuerParams} | ||
} | ||
|
||
// key properties | ||
if props := input.KeyProperties; props != nil { | ||
keyProps := make(map[string]interface{}) | ||
keyProps["exportable"] = *props.Exportable | ||
keyProps["key_size"] = int(*props.KeySize) | ||
keyProps["key_type"] = *props.KeyType | ||
keyProps["reuse_key"] = *props.ReuseKey | ||
|
||
policy["key_properties"] = []interface{}{keyProps} | ||
} | ||
|
||
// lifetime actions | ||
lifetimeActions := make([]interface{}, 0) | ||
if actions := input.LifetimeActions; actions != nil { | ||
for _, action := range *actions { | ||
lifetimeAction := make(map[string]interface{}) | ||
|
||
actionOutput := make(map[string]interface{}) | ||
if act := action.Action; act != nil { | ||
actionOutput["action_type"] = string(act.ActionType) | ||
} | ||
lifetimeAction["action"] = []interface{}{actionOutput} | ||
|
||
triggerOutput := make(map[string]interface{}) | ||
if trigger := action.Trigger; trigger != nil { | ||
if days := trigger.DaysBeforeExpiry; days != nil { | ||
triggerOutput["days_before_expiry"] = int(*trigger.DaysBeforeExpiry) | ||
} | ||
|
||
if days := trigger.LifetimePercentage; days != nil { | ||
triggerOutput["lifetime_percentage"] = int(*trigger.LifetimePercentage) | ||
} | ||
} | ||
lifetimeAction["trigger"] = []interface{}{triggerOutput} | ||
lifetimeActions = append(lifetimeActions, lifetimeAction) | ||
} | ||
} | ||
policy["lifetime_action"] = lifetimeActions | ||
|
||
// secret properties | ||
if props := input.SecretProperties; props != nil { | ||
keyProps := make(map[string]interface{}) | ||
keyProps["content_type"] = *props.ContentType | ||
|
||
policy["secret_properties"] = []interface{}{keyProps} | ||
} | ||
|
||
// x509 Certificate Properties | ||
if props := input.X509CertificateProperties; props != nil { | ||
certProps := make(map[string]interface{}) | ||
|
||
usages := make([]string, 0) | ||
for _, usage := range *props.KeyUsage { | ||
usages = append(usages, string(usage)) | ||
} | ||
|
||
sanOutputs := make([]interface{}, 0) | ||
if san := props.SubjectAlternativeNames; san != nil { | ||
sanOutput := make(map[string]interface{}) | ||
if emails := san.Emails; emails != nil { | ||
sanOutput["emails"] = *emails | ||
} | ||
if dnsNames := san.DNSNames; dnsNames != nil { | ||
sanOutput["dns_names"] = *dnsNames | ||
} | ||
if upns := san.Upns; upns != nil { | ||
sanOutput["upns"] = *upns | ||
} | ||
|
||
sanOutputs = append(sanOutputs, sanOutput) | ||
} | ||
|
||
certProps["key_usage"] = usages | ||
certProps["subject"] = *props.Subject | ||
certProps["validity_in_months"] = int(*props.ValidityInMonths) | ||
if props.Ekus != nil { | ||
certProps["extended_key_usage"] = props.Ekus | ||
} | ||
certProps["subject_alternative_names"] = sanOutputs | ||
policy["x509_certificate_properties"] = []interface{}{certProps} | ||
} | ||
|
||
return []interface{}{policy} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.