diff --git a/.changelog/19728.txt b/.changelog/19728.txt new file mode 100644 index 000000000000..53c61bc5e0e8 --- /dev/null +++ b/.changelog/19728.txt @@ -0,0 +1,3 @@ +```release-note:improvement +acl: add api-gateway templated policy +``` \ No newline at end of file diff --git a/agent/acl_endpoint_test.go b/agent/acl_endpoint_test.go index b8a607ec0518..1296731dc783 100644 --- a/agent/acl_endpoint_test.go +++ b/agent/acl_endpoint_test.go @@ -1407,7 +1407,7 @@ func TestACL_HTTP(t *testing.T) { var list map[string]api.ACLTemplatedPolicyResponse require.NoError(t, json.NewDecoder(resp.Body).Decode(&list)) - require.Len(t, list, 5) + require.Len(t, list, 6) require.Equal(t, api.ACLTemplatedPolicyResponse{ TemplateName: api.ACLTemplatedPolicyServiceName, diff --git a/agent/structs/acl_templated_policy.go b/agent/structs/acl_templated_policy.go index 999e0f0d7d10..ce2af67888f9 100644 --- a/agent/structs/acl_templated_policy.go +++ b/agent/structs/acl_templated_policy.go @@ -29,6 +29,9 @@ var ACLTemplatedPolicyServiceSchema string //go:embed acltemplatedpolicy/schemas/workload-identity.json var ACLTemplatedPolicyWorkloadIdentitySchema string +//go:embed acltemplatedpolicy/schemas/api-gateway.json +var ACLTemplatedPolicyAPIGatewaySchema string + type ACLTemplatedPolicies []*ACLTemplatedPolicy const ( @@ -37,6 +40,7 @@ const ( ACLTemplatedPolicyDNSID = "00000000-0000-0000-0000-000000000005" ACLTemplatedPolicyNomadServerID = "00000000-0000-0000-0000-000000000006" ACLTemplatedPolicyWorkloadIdentityID = "00000000-0000-0000-0000-000000000007" + ACLTemplatedPolicyAPIGatewayID = "00000000-0000-0000-0000-000000000008" ACLTemplatedPolicyNoRequiredVariablesSchema = "" // catch-all schema for all templated policy that don't require a schema ) @@ -84,6 +88,12 @@ var ( Schema: ACLTemplatedPolicyWorkloadIdentitySchema, Template: ACLTemplatedPolicyWorkloadIdentity, }, + api.ACLTemplatedPolicyAPIGatewayName: { + TemplateID: ACLTemplatedPolicyAPIGatewayID, + TemplateName: api.ACLTemplatedPolicyAPIGatewayName, + Schema: ACLTemplatedPolicyAPIGatewaySchema, + Template: ACLTemplatedPolicyAPIGateway, + }, } ) diff --git a/agent/structs/acl_templated_policy_ce.go b/agent/structs/acl_templated_policy_ce.go index cd9a52248a98..1465a324b616 100644 --- a/agent/structs/acl_templated_policy_ce.go +++ b/agent/structs/acl_templated_policy_ce.go @@ -22,6 +22,9 @@ var ACLTemplatedPolicyNomadServer string //go:embed acltemplatedpolicy/policies/ce/workload-identity.hcl var ACLTemplatedPolicyWorkloadIdentity string +//go:embed acltemplatedpolicy/policies/ce/api-gateway.hcl +var ACLTemplatedPolicyAPIGateway string + func (t *ACLToken) TemplatedPolicyList() []*ACLTemplatedPolicy { if len(t.TemplatedPolicies) == 0 { return nil diff --git a/agent/structs/acl_templated_policy_ce_test.go b/agent/structs/acl_templated_policy_ce_test.go index e160a911cb89..f21292806283 100644 --- a/agent/structs/acl_templated_policy_ce_test.go +++ b/agent/structs/acl_templated_policy_ce_test.go @@ -95,6 +95,28 @@ query_prefix "" { Description: "synthetic policy generated from templated policy: builtin/workload-identity", Rules: `identity "api" { policy = "write" +}`, + }, + }, + "api-gateway-template": { + templatedPolicy: &ACLTemplatedPolicy{ + TemplateID: ACLTemplatedPolicyAPIGatewayID, + TemplateName: api.ACLTemplatedPolicyAPIGatewayName, + TemplateVariables: &ACLTemplatedPolicyVariables{ + Name: "api-gateway", + }, + }, + expectedPolicy: &ACLPolicy{ + Description: "synthetic policy generated from templated policy: builtin/api-gateway", + Rules: `mesh = "read" +node_prefix "" { + policy = "read" +} +service_prefix "" { + policy = "read" +} +service "api-gateway" { + policy = "write" }`, }, }, diff --git a/agent/structs/acltemplatedpolicy/policies/ce/api-gateway.hcl b/agent/structs/acltemplatedpolicy/policies/ce/api-gateway.hcl new file mode 100644 index 000000000000..7bb2e4908130 --- /dev/null +++ b/agent/structs/acltemplatedpolicy/policies/ce/api-gateway.hcl @@ -0,0 +1,10 @@ +mesh = "read" +node_prefix "" { + policy = "read" +} +service_prefix "" { + policy = "read" +} +service "{{.Name}}" { + policy = "write" +} \ No newline at end of file diff --git a/agent/structs/acltemplatedpolicy/schemas/api-gateway.json b/agent/structs/acltemplatedpolicy/schemas/api-gateway.json new file mode 100644 index 000000000000..8a3d19326821 --- /dev/null +++ b/agent/structs/acltemplatedpolicy/schemas/api-gateway.json @@ -0,0 +1,13 @@ +{ + "type": "object", + "properties": { + "name": { "type": "string", "$ref": "#/definitions/min-length-one" } + }, + "required": ["name"], + "definitions": { + "min-length-one": { + "type": "string", + "minLength": 1 + } + } +} \ No newline at end of file diff --git a/api/acl.go b/api/acl.go index 47b38eb6ca62..5f4033a84d6c 100644 --- a/api/acl.go +++ b/api/acl.go @@ -26,6 +26,7 @@ const ( ACLTemplatedPolicyDNSName = "builtin/dns" ACLTemplatedPolicyNomadServerName = "builtin/nomad-server" ACLTemplatedPolicyWorkloadIdentityName = "builtin/workload-identity" + ACLTemplatedPolicyAPIGatewayName = "builtin/api-gateway" ) type ACLLink struct { diff --git a/command/acl/templatedpolicy/formatter.go b/command/acl/templatedpolicy/formatter.go index dec8378bcc5f..736d4f48c1ac 100644 --- a/command/acl/templatedpolicy/formatter.go +++ b/command/acl/templatedpolicy/formatter.go @@ -69,13 +69,13 @@ func (f *prettyFormatter) FormatTemplatedPolicy(templatedPolicy api.ACLTemplated buffer.WriteString("Input variables:") switch templatedPolicy.TemplateName { case api.ACLTemplatedPolicyServiceName: - buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - The name of the service.\n", WhitespaceIndent)) - buffer.WriteString("Example usage:\n") - buffer.WriteString(WhitespaceIndent + "consul acl token create -templated-policy builtin/service -var name:api\n") + nameRequiredVariableOutput(&buffer, templatedPolicy.TemplateName, "The name of the service", "api") case api.ACLTemplatedPolicyNodeName: - buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - The node name.\n", WhitespaceIndent)) - buffer.WriteString("Example usage:\n") - buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy builtin/node -var name:node-1\n", WhitespaceIndent)) + nameRequiredVariableOutput(&buffer, templatedPolicy.TemplateName, "The node name", "node-1") + case api.ACLTemplatedPolicyWorkloadIdentityName: + nameRequiredVariableOutput(&buffer, templatedPolicy.TemplateName, "The workload name", "api") + case api.ACLTemplatedPolicyAPIGatewayName: + nameRequiredVariableOutput(&buffer, templatedPolicy.TemplateName, "The api gateway service name", "api-gateway") case api.ACLTemplatedPolicyDNSName, api.ACLTemplatedPolicyNomadServerName: noRequiredVariablesOutput(&buffer, templatedPolicy.TemplateName) default: @@ -98,6 +98,12 @@ func noRequiredVariablesOutput(buffer *bytes.Buffer, templateName string) { buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy %s\n", WhitespaceIndent, templateName)) } +func nameRequiredVariableOutput(buffer *bytes.Buffer, templateName, description, exampleName string) { + buffer.WriteString(fmt.Sprintf("\n%sName: String - Required - %s.\n", WhitespaceIndent, description)) + buffer.WriteString("Example usage:\n") + buffer.WriteString(fmt.Sprintf("%sconsul acl token create -templated-policy %s -var name:%s\n", WhitespaceIndent, templateName, exampleName)) +} + func (f *prettyFormatter) FormatTemplatedPolicyList(policies map[string]api.ACLTemplatedPolicyResponse) (string, error) { var buffer bytes.Buffer