diff --git a/.gitignore b/.gitignore index b5ea10abf..7d192ba02 100644 --- a/.gitignore +++ b/.gitignore @@ -22,7 +22,6 @@ website/node_modules .idea *.iml *.test -*.iml .vscode website/vendor diff --git a/vault/provider.go b/vault/provider.go index 800aebda6..248260c53 100644 --- a/vault/provider.go +++ b/vault/provider.go @@ -165,6 +165,7 @@ func Provider() terraform.ResourceProvider { "vault_pki_secret_backend": pkiSecretBackendResource(), "vault_pki_secret_backend_cert": pkiSecretBackendCertResource(), "vault_pki_secret_backend_config_ca": pkiSecretBackendConfigCAResource(), + "vault_pki_secret_backend_config_urls": pkiSecretBackendConfigUrlsResource(), "vault_pki_secret_backend_intermediate_cert_request": pkiSecretBackendIntermediateCertRequestResource(), "vault_pki_secret_backend_intermediate_set_signed": pkiSecretBackendIntermediateSetSignedResource(), "vault_pki_secret_backend_role": pkiSecretBackendRoleResource(), diff --git a/vault/resource_pki_secret_backend_config_urls.go b/vault/resource_pki_secret_backend_config_urls.go new file mode 100644 index 000000000..ab58a0c8e --- /dev/null +++ b/vault/resource_pki_secret_backend_config_urls.go @@ -0,0 +1,136 @@ +package vault + +import ( + "fmt" + "log" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/vault/api" +) + +func pkiSecretBackendConfigUrlsResource() *schema.Resource { + return &schema.Resource{ + Create: pkiSecretBackendConfigUrlsCreate, + Read: pkiSecretBackendConfigUrlsRead, + Update: pkiSecretBackendConfigUrlsUpdate, + Delete: pkiSecretBackendConfigUrlsDelete, + + Schema: map[string]*schema.Schema{ + "backend": { + Type: schema.TypeString, + Required: true, + Optional: false, + ForceNew: false, + Description: "The path of the PKI secret backend the resource belongs to.", + }, + "issuing_certificates": { + Type: schema.TypeString, + Required: false, + Optional: true, + Description: "Specifies the URL values for the Issuing Certificate field. This can be a comma-separated string list.", + ForceNew: false, + }, + "crl_distribution_points": { + Type: schema.TypeString, + Required: false, + Optional: true, + Description: "Specifies the URL values for the CRL Distribution Points field. This can be a comma-separated string list.", + ForceNew: false, + }, + "ocsp_servers": { + Type: schema.TypeString, + Required: false, + Optional: true, + Description: "Specifies the URL values for the OCSP Servers field. This can be a comma-separated string list.", + ForceNew: false, + }, + }, + } +} + +func pkiSecretBackendConfigUrlsCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*api.Client) + + backend := d.Get("backend").(string) + + path := pkiSecretBackendConfigUrlsPath(backend) + + issuingCertificates := d.Get("issuing_certificates").(string) + crlDistributionsPoints := d.Get("crl_distribution_points").(string) + ocspServers := d.Get("ocsp_servers").(string) + + data := map[string]interface{}{ + "issuing_certificates": issuingCertificates, + "crl_distribution_points": crlDistributionsPoints, + "ocsp_servers": ocspServers, + } + + log.Printf("[DEBUG] Creating URL config on PKI secret backend %q", backend) + _, err := client.Logical().Write(path, data) + if err != nil { + return fmt.Errorf("error creating URL config PKI secret backend %q: %s", backend, err) + } + log.Printf("[DEBUG] Created URL config on PKI secret backend %q", backend) + + d.SetId(fmt.Sprintf("%s/config/urls", backend)) + return pkiSecretBackendConfigUrlsRead(d, meta) +} + +func pkiSecretBackendConfigUrlsRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*api.Client) + + path := d.Id() + backend := pkiSecretBackendConfigUrlsPath(path) + + log.Printf("[DEBUG] Reading URL config from PKI secret backend %q", backend) + config, err := client.Logical().Read(path) + + if err != nil { + log.Printf("[WARN] Removing path %q its ID is invalid", path) + d.SetId("") + return fmt.Errorf("invalid path ID %q: %s", path, err) + } + + d.Set("issuing_certificates", config.Data["issuing_certificates"]) + d.Set("crl_distribution_points", config.Data["crl_distribution_points"]) + d.Set("ocsp_servers", config.Data["ocsp_servers"]) + + return nil +} + +func pkiSecretBackendConfigUrlsUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*api.Client) + + backend := d.Id() + + path := pkiSecretBackendConfigUrlsPath(backend) + + issuingCertificates := d.Get("issuing_certificates").(string) + crlDistributionsPoints := d.Get("crl_distribution_points").(string) + ocspServers := d.Get("ocsp_servers").(string) + + data := map[string]interface{}{ + "issuing_certificates": issuingCertificates, + "crl_distribution_points": crlDistributionsPoints, + "ocsp_servers": ocspServers, + } + + log.Printf("[DEBUG] Updating URL config on PKI secret backend %q", backend) + _, err := client.Logical().Write(path, data) + if err != nil { + return fmt.Errorf("error updating URL config for PKI secret backend %q: %s", backend, err) + } + log.Printf("[DEBUG] Updated URL config on PKI secret backend %q", backend) + + return pkiSecretBackendConfigUrlsRead(d, meta) + +} + +func pkiSecretBackendConfigUrlsDelete(d *schema.ResourceData, meta interface{}) error { + return nil +} + +func pkiSecretBackendConfigUrlsPath(backend string) string { + return strings.Trim(backend, "/") + "/config/urls" +} diff --git a/vault/resource_pki_secret_backend_config_urls_test.go b/vault/resource_pki_secret_backend_config_urls_test.go new file mode 100644 index 000000000..f45d8b5b7 --- /dev/null +++ b/vault/resource_pki_secret_backend_config_urls_test.go @@ -0,0 +1,82 @@ +package vault + +import ( + "fmt" + "strconv" + "strings" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/hashicorp/vault/api" +) + +func TestPkiSecretBackendConfigUrls_basic(t *testing.T) { + rootPath := "pki-root-" + strconv.Itoa(acctest.RandInt()) + + issuingCertificates := "http://127.0.0.1:8200/v1/pki/ca" + crlDistributionPoints := "http://127.0.0.1:8200/v1/pki/crl" + ocspServers := "http://127.0.0.1:8200/v1/pki/oscp" + + resource.Test(t, resource.TestCase{ + Providers: testProviders, + PreCheck: func() { testAccPreCheck(t) }, + CheckDestroy: testPkiSecretBackendConfigUrlsDestroy, + Steps: []resource.TestStep{ + { + Config: testPkiSecretBackendCertConfigUrlsConfig_basic(rootPath, issuingCertificates, crlDistributionPoints, ocspServers), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("vault_pki_secret_backend_config_urls.test", "issuing_certificates", issuingCertificates), + resource.TestCheckResourceAttr("vault_pki_secret_backend_config_urls.test", "crl_distribution_points", crlDistributionPoints), + resource.TestCheckResourceAttr("vault_pki_secret_backend_config_urls.test", "ocsp_servers", ocspServers), + ), + }, + }, + }) +} + +func testPkiSecretBackendConfigUrlsDestroy(s *terraform.State) error { + client := testProvider.Meta().(*api.Client) + + mounts, err := client.Sys().ListMounts() + if err != nil { + return err + } + + for _, rs := range s.RootModule().Resources { + if rs.Type != "vault_pki_secret_backend" { + continue + } + for path, mount := range mounts { + path = strings.Trim(path, "/") + rsPath := strings.Trim(rs.Primary.Attributes["path"], "/") + if mount.Type == "pki" && path == rsPath { + return fmt.Errorf("mount %q still exists", path) + } + } + } + return nil +} + +func testPkiSecretBackendCertConfigUrlsConfig_basic(rootPath string, issuingCertificates string, crlDistributionPoints string, ocspServers string) string { + return fmt.Sprintf(` +resource "vault_pki_secret_backend" "test-root" { + path = "%s" + description = "test root" + default_lease_ttl_seconds = "8640000" + max_lease_ttl_seconds = "8640000" +} + +resource "vault_pki_secret_backend_config_urls" "test" { + depends_on = [ "vault_pki_secret_backend.test-root" ] + + backend = "${vault_pki_secret_backend.test-root.path}" + + issuing_certificates = "%s" + crl_distribution_points = "%s" + ocsp_servers = "%s" +} + +`, rootPath, issuingCertificates, crlDistributionPoints, ocspServers) +} diff --git a/website/docs/r/pki_secret_backend_config_urls.html.md b/website/docs/r/pki_secret_backend_config_urls.html.md new file mode 100644 index 000000000..fce7d4be0 --- /dev/null +++ b/website/docs/r/pki_secret_backend_config_urls.html.md @@ -0,0 +1,42 @@ +--- +layout: "vault" +page_title: "Vault: vault_pki_secret_backend_config_urls resource" +sidebar_current: "docs-vault-resource-pki-secret-backend-config-urls" +description: |- + Sets the config URL's on an PKI Secret Backend for Vault. +--- + +# vault\_pki\_secret\_backend\_config\_urls + +Allows setting the issuing certificate endpoints, CRL distribution points, and OCSP server endpoints that will be encoded into issued certificates. + +## Example Usage + +```hcl +resource "vault_pki_secret_backend" "pki" { + path = "%s" + default_lease_ttl_seconds = 3600 + max_lease_ttl_seconds = 86400 +} + +resource "vault_pki_secret_backend_config_urls" "config_urls" { + backend = "${vault_pki_secret_backend.pki.path}" + issuing_certificates = "http://127.0.0.1:8200/v1/pki/ca" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `backend` - (Required) The path the PKI secret backend is mounted at, with no leading or trailing `/`s. + +* `issuing_certificates` - (Optional) Specifies the URL values for the Issuing Certificate field. Comma-separated string if multiple. + +* `crl_distribution_points` - (Optional) Specifies the URL values for the CRL Distribution Points field. Comma-separated string if multiple. + +* `ocsp_servers` - (Optional) Specifies the URL values for the OCSP Servers field. Comma-separated string if multiple. + +## Attributes Reference + +No additional attributes are exported by this resource. diff --git a/website/vault.erb b/website/vault.erb index d49e3cbb1..04ad90d7c 100644 --- a/website/vault.erb +++ b/website/vault.erb @@ -231,6 +231,10 @@ vault_pki_secret_backend_config_ca + > + vault_pki_secret_backend_config_urls + + > vault_pki_secret_backend_intermediate_cert_request