diff --git a/vault/resource_cert_auth_backend_role.go b/vault/resource_cert_auth_backend_role.go index 9c0aa5132..f2209d51a 100644 --- a/vault/resource_cert_auth_backend_role.go +++ b/vault/resource_cert_auth_backend_role.go @@ -38,6 +38,46 @@ func certAuthBackendRoleResource() *schema.Resource { Optional: true, Computed: true, }, + "allowed_common_names": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Computed: true, + }, + "allowed_dns_sans": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Computed: true, + }, + "allowed_email_sans": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Computed: true, + }, + "allowed_uri_sans": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Computed: true, + }, + "allowed_organization_units": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Computed: true, + }, "required_extensions": { Type: schema.TypeSet, Elem: &schema.Schema{ @@ -83,6 +123,14 @@ func certAuthBackendRoleResource() *schema.Resource { return strings.Trim(v.(string), "/") }, }, + "bound_cidrs": { + Type: schema.TypeSet, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + Computed: true, + }, }, } } @@ -106,6 +154,22 @@ func certAuthResourceWrite(d *schema.ResourceData, meta interface{}) error { data["allowed_names"] = v.(*schema.Set).List() } + if v, ok := d.GetOk("allowed_common_names"); ok { + data["allowed_common_names"] = v.(*schema.Set).List() + } + + if v, ok := d.GetOk("allowed_dns_sans"); ok { + data["allowed_dns_sans"] = v.(*schema.Set).List() + } + + if v, ok := d.GetOk("allowed_uri_sans"); ok { + data["allowed_uri_sans"] = v.(*schema.Set).List() + } + + if v, ok := d.GetOk("allowed_organization_units"); ok { + data["allowed_organization_units"] = v.(*schema.Set).List() + } + if v, ok := d.GetOk("required_extensions"); ok { data["required_extensions"] = v.(*schema.Set).List() } @@ -130,6 +194,10 @@ func certAuthResourceWrite(d *schema.ResourceData, meta interface{}) error { data["display_name"] = v.(string) } + if v, ok := d.GetOk("bound_cidrs"); ok { + data["bound_cidrs"] = v.(*schema.Set).List() + } + log.Printf("[DEBUG] Writing %q to cert auth backend", path) d.SetId(path) _, err := client.Logical().Write(path, data) @@ -154,6 +222,22 @@ func certAuthResourceUpdate(d *schema.ResourceData, meta interface{}) error { data["allowed_names"] = v.(*schema.Set).List() } + if v, ok := d.GetOk("allowed_common_names"); ok { + data["allowed_common_names"] = v.(*schema.Set).List() + } + + if v, ok := d.GetOk("allowed_dns_sans"); ok { + data["allowed_dns_sans"] = v.(*schema.Set).List() + } + + if v, ok := d.GetOk("allowed_uri_sans"); ok { + data["allowed_uri_sans"] = v.(*schema.Set).List() + } + + if v, ok := d.GetOk("allowed_organization_units"); ok { + data["allowed_organization_units"] = v.(*schema.Set).List() + } + if v, ok := d.GetOk("required_extensions"); ok { data["required_extensions"] = v.(*schema.Set).List() } @@ -178,6 +262,10 @@ func certAuthResourceUpdate(d *schema.ResourceData, meta interface{}) error { data["display_name"] = v.(string) } + if v, ok := d.GetOk("bound_cidrs"); ok { + data["bound_cidrs"] = v.(*schema.Set).List() + } + log.Printf("[DEBUG] Updating %q in cert auth backend", path) _, err := client.Logical().Write(path, data) if err != nil { @@ -222,6 +310,50 @@ func certAuthResourceRead(d *schema.ResourceData, meta interface{}) error { schema.HashString, []interface{}{})) } + // Vault sometimes returns these as null instead of an empty list. + if resp.Data["allowed_dns_sans"] != nil { + d.Set("allowed_dns_sans", + schema.NewSet( + schema.HashString, resp.Data["allowed_dns_sans"].([]interface{}))) + } else { + d.Set("allowed_dns_sans", + schema.NewSet( + schema.HashString, []interface{}{})) + } + + // Vault sometimes returns these as null instead of an empty list. + if resp.Data["allowed_email_sans"] != nil { + d.Set("allowed_email_sans", + schema.NewSet( + schema.HashString, resp.Data["allowed_email_sans"].([]interface{}))) + } else { + d.Set("allowed_email_sans", + schema.NewSet( + schema.HashString, []interface{}{})) + } + + // Vault sometimes returns these as null instead of an empty list. + if resp.Data["allowed_uri_sans"] != nil { + d.Set("allowed_uri_sans", + schema.NewSet( + schema.HashString, resp.Data["allowed_uri_sans"].([]interface{}))) + } else { + d.Set("allowed_uri_sans", + schema.NewSet( + schema.HashString, []interface{}{})) + } + + // Vault sometimes returns these as null instead of an empty list. + if resp.Data["allowed_organization_units"] != nil { + d.Set("allowed_organization_units", + schema.NewSet( + schema.HashString, resp.Data["allowed_organization_units"].([]interface{}))) + } else { + d.Set("allowed_organization_units", + schema.NewSet( + schema.HashString, []interface{}{})) + } + // Vault sometimes returns these as null instead of an empty list. if resp.Data["policies"] != nil { d.Set("policies", @@ -244,6 +376,17 @@ func certAuthResourceRead(d *schema.ResourceData, meta interface{}) error { schema.HashString, []interface{}{})) } + // Vault sometimes returns these as null instead of an empty list. + if resp.Data["bound_cidrs"] != nil { + d.Set("bound_cidrs", + schema.NewSet( + schema.HashString, resp.Data["bound_cidrs"].([]interface{}))) + } else { + d.Set("bound_cidrs", + schema.NewSet( + schema.HashString, []interface{}{})) + } + return nil } diff --git a/vault/resource_cert_auth_backend_role_test.go b/vault/resource_cert_auth_backend_role_test.go index ff5d73e1e..8d5d43048 100644 --- a/vault/resource_cert_auth_backend_role_test.go +++ b/vault/resource_cert_auth_backend_role_test.go @@ -142,14 +142,19 @@ func testCertAuthBackendCheck_attrs(backend, name string) resource.TestCheckFunc } attrs := map[string]string{ - "name": "display_name", - "allowed_names": "allowed_names", - "required_extensions": "required_extensions", - "period": "period", - "policies": "policies", - "certificate": "certificate", - "ttl": "ttl", - "max_ttl": "max_ttl", + "name": "display_name", + "allowed_names": "allowed_names", + "allowed_dns_sans": "allowed_dns_sans", + "allowed_email_sans": "allowed_email_sans", + "allowed_uri_sans": "allowed_uri_sans", + "allowed_organization_units": "allowed_organization_units", + "required_extensions": "required_extensions", + "period": "period", + "policies": "policies", + "certificate": "certificate", + "ttl": "ttl", + "max_ttl": "max_ttl", + "bound_cidrs": "bound_cidrs", } for stateAttr, apiAttr := range attrs { diff --git a/website/docs/r/cert_auth_backend_role.html.md b/website/docs/r/cert_auth_backend_role.html.md index 60fae7515..fd40a168f 100644 --- a/website/docs/r/cert_auth_backend_role.html.md +++ b/website/docs/r/cert_auth_backend_role.html.md @@ -39,6 +39,16 @@ The following arguments are supported: * `allowed_names` - (Optional) Allowed subject names for authenticated client certificates +* `allowed_common_names` - (Optional) Allowed the common names for authenticated client certificates + +* `allowed_dns_sans` - (Optional) Allowed alternative dns names for authenticated client certificates + +* `allowed_email_sans` - (Optional) Allowed emails for authenticated client certificates + +* `allowed_uri_sans` - (Optional) Allowed URIs for authenticated client certificates + +* `allowed_organization_units` - (Optional) Allowed organization units for authenticated client certificates + * `required_exwtensions` - (Optional) TLS extensions required on client certificates * `ttl` - (Optional) Default TTL of tokens issued by the backend @@ -51,6 +61,8 @@ The following arguments are supported: * `display_name` - (Optional) The name to display on tokens issued under this role. +* `bound_cidrs` - (Optional) Restriction usage of the certificates to client IPs falling within the range of the specified CIDRs + * `backend` - (Optional) Path to the mounted Cert auth backend For more details on the usage of each argument consult the [Vault Cert API documentation](https://www.vaultproject.io/api/auth/cert/index.html).