diff --git a/consul/resource_consul_acl_token.go b/consul/resource_consul_acl_token.go index 7b6f70f9..da8a998b 100644 --- a/consul/resource_consul_acl_token.go +++ b/consul/resource_consul_acl_token.go @@ -94,6 +94,43 @@ func resourceConsulACLToken() *schema.Resource { }, }, }, + "templated_policies": { + Type: schema.TypeList, + Optional: true, + Description: "The list of templated policies that should be applied to the token.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "template_name": { + Type: schema.TypeString, + Required: true, + Description: "The name of the templated policies.", + }, + "template_variables": { + Type: schema.TypeList, + MaxItems: 1, + Description: "The templated policy variables.", + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Optional: true, + Description: "The name of node, workload identity or service.", + }, + }, + }, + }, + "datacenters": { + Type: schema.TypeList, + Optional: true, + Description: "Specifies the datacenters the effective policy is valid within.", + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, "local": { Type: schema.TypeBool, ForceNew: true, @@ -189,6 +226,15 @@ func resourceConsulACLTokenRead(d *schema.ResourceData, meta interface{}) error } } + templatedPolicies := make([]interface{}, len(aclToken.TemplatedPolicies)) + for i, tp := range aclToken.TemplatedPolicies { + templatedPolicies[i] = map[string]interface{}{ + "template_name": tp.TemplateName, + "datacenters": tp.Datacenters, + "template_variables": getTemplateVariables(tp), + } + } + sw := newStateWriter(d) sw.set("accessor_id", aclToken.AccessorID) sw.set("description", aclToken.Description) @@ -196,6 +242,7 @@ func resourceConsulACLTokenRead(d *schema.ResourceData, meta interface{}) error sw.set("roles", roles) sw.set("service_identities", serviceIdentities) sw.set("node_identities", nodeIdentities) + sw.set("templated_policies", templatedPolicies) sw.set("local", aclToken.Local) sw.set("expiration_time", expirationTime) sw.set("namespace", aclToken.Namespace) @@ -204,6 +251,16 @@ func resourceConsulACLTokenRead(d *schema.ResourceData, meta interface{}) error return sw.error() } +func getTemplateVariables(templatedPolicy *consulapi.ACLTemplatedPolicy) []map[string]interface{} { + if templatedPolicy == nil || templatedPolicy.TemplateVariables == nil { + return nil + } + + return []map[string]interface{}{ + {"name": templatedPolicy.TemplateVariables.Name}, + } +} + func resourceConsulACLTokenUpdate(d *schema.ResourceData, meta interface{}) error { client, _, wOpts := getClient(d, meta) @@ -289,6 +346,30 @@ func getToken(d *schema.ResourceData) *consulapi.ACLToken { } aclToken.NodeIdentities = nodeIdentities + templatedPolicies := []*consulapi.ACLTemplatedPolicy{} + for key, tp := range d.Get("templated_policies").([]interface{}) { + t := tp.(map[string]interface{}) + + datacenters := []string{} + for _, d := range t["datacenters"].([]interface{}) { + datacenters = append(datacenters, d.(string)) + } + + templatedPolicy := &consulapi.ACLTemplatedPolicy{ + Datacenters: datacenters, + TemplateName: t["template_name"].(string), + } + + if templatedVariables, ok := d.GetOk(fmt.Sprint("templated_policies.", key, ".template_variables.0")); ok { + tv := templatedVariables.(map[string]interface{}) + templatedPolicy.TemplateVariables = &consulapi.ACLTemplatedPolicyVariables{ + Name: tv["name"].(string), + } + } + templatedPolicies = append(templatedPolicies, templatedPolicy) + } + aclToken.TemplatedPolicies = templatedPolicies + expirationTime := d.Get("expiration_time").(string) if expirationTime != "" { // the string has already been validated so there is no need to check diff --git a/consul/resource_consul_acl_token_test.go b/consul/resource_consul_acl_token_test.go index 2014b5e4..a10dd809 100644 --- a/consul/resource_consul_acl_token_test.go +++ b/consul/resource_consul_acl_token_test.go @@ -45,6 +45,7 @@ func TestAccConsulACLToken_basic(t *testing.T) { resource.TestCheckResourceAttr("consul_acl_token.test", "node_identities.#", "0"), resource.TestCheckResourceAttrSet("consul_acl_token.test", "policies.#"), resource.TestCheckResourceAttr("consul_acl_token.test", "service_identities.#", "0"), + resource.TestCheckResourceAttr("consul_acl_token.test", "templated_policies.#", "0"), ), }, { @@ -64,6 +65,12 @@ func TestAccConsulACLToken_basic(t *testing.T) { resource.TestCheckResourceAttr("consul_acl_token.test", "service_identities.0.datacenters.#", "1"), resource.TestCheckResourceAttr("consul_acl_token.test", "service_identities.0.datacenters.0", "world"), resource.TestCheckResourceAttr("consul_acl_token.test", "service_identities.0.service_name", "hello"), + resource.TestCheckResourceAttr("consul_acl_token.test", "templated_policies.#", "1"), + resource.TestCheckResourceAttr("consul_acl_token.test", "templated_policies.0.datacenters.#", "1"), + resource.TestCheckResourceAttr("consul_acl_token.test", "templated_policies.0.datacenters.0", "world"), + resource.TestCheckResourceAttr("consul_acl_token.test", "templated_policies.0.template_variables.#", "1"), + resource.TestCheckResourceAttr("consul_acl_token.test", "templated_policies.0.template_variables.0.name", "web"), + resource.TestCheckResourceAttr("consul_acl_token.test", "templated_policies.0.template_name", "builtin/service"), ), }, { @@ -189,6 +196,14 @@ resource "consul_acl_token" "test" { node_name = "foo" datacenter = "bar" } + + templated_policies { + template_name = "builtin/service" + datacenters = ["world"] + template_variables { + name = "web" + } + } }` const testResourceACLTokenConfigRole = ` diff --git a/go.mod b/go.mod index df391ba3..b56e7108 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/hashicorp/terraform-provider-consul require ( - github.com/hashicorp/consul/api v1.23.0 + github.com/hashicorp/consul/api v1.26.1-rc1 github.com/hashicorp/errwrap v1.1.0 github.com/hashicorp/terraform-plugin-sdk v1.17.2 github.com/mitchellh/mapstructure v1.5.0 @@ -12,7 +12,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v0.12.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect ) require ( @@ -39,7 +39,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.0 // indirect github.com/googleapis/gax-go/v2 v2.7.1 // indirect - github.com/hashicorp/consul/sdk v0.14.0 + github.com/hashicorp/consul/sdk v0.14.3-rc1 github.com/hashicorp/go-checkpoint v0.5.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-getter v1.7.0 // indirect @@ -88,9 +88,9 @@ require ( github.com/zclconf/go-cty-yaml v1.0.2 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/crypto v0.11.0 // indirect - golang.org/x/net v0.12.0 // indirect + golang.org/x/net v0.13.0 // indirect golang.org/x/oauth2 v0.6.0 // indirect - golang.org/x/sys v0.10.0 // indirect + golang.org/x/sys v0.11.0 // indirect golang.org/x/text v0.11.0 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect google.golang.org/api v0.114.0 // indirect diff --git a/go.sum b/go.sum index f704096c..7580fbb3 100644 --- a/go.sum +++ b/go.sum @@ -406,10 +406,10 @@ github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6c github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.23.0 h1:L6e4v1AfoumqAHq/Rrsmuulev+nd7vltM3k8H329tyI= -github.com/hashicorp/consul/api v1.23.0/go.mod h1:SfvUIT74b0EplDuNgAJQ/FVqSO6KyK2ia80UI39/Ye8= -github.com/hashicorp/consul/sdk v0.14.0 h1:Hly+BMNMssVzoWddbBnBFi3W+Fzytvm0haSkihhj3GU= -github.com/hashicorp/consul/sdk v0.14.0/go.mod h1:gHYeuDa0+0qRAD6Wwr6yznMBvBwHKoxSBoW5l73+saE= +github.com/hashicorp/consul/api v1.26.1-rc1 h1:eO+53vwWxEV2TMbTVrJbXp2TJjJNv+Nxij8j+xi3yOc= +github.com/hashicorp/consul/api v1.26.1-rc1/go.mod h1:ZKnaWXL2r23i+SPmEj1H5YsRNUS/uUzB2uhmD2QY4IY= +github.com/hashicorp/consul/sdk v0.14.3-rc1 h1:kE0dLXXTnvm67PNRE527XpSwqi5vwWoP+VkNHdBBR7o= +github.com/hashicorp/consul/sdk v0.14.3-rc1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -712,8 +712,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= +golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -795,8 +795,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY= +golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -916,8 +916,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=