Newbie: Service Registration Blocked by ACL

Hi again,
I have a consul cluster running as the orchestrator for Postgresql. (Patroni)
I followed these instructions on one consul instance and it worked as described. Secure Consul with access control lists (ACLs) | Consul | HashiCorp Developer

Adding a second consul node gets this on the first consul node:

[ERROR] agent.http: Request error: method=PUT url=/v1/agent/service/register from=192.168.2.5:42336 error="Permission denied: token with AccessorID '2696e7d3-cb6a-6004-55fe-0c514ba1b7e3' lacks permission 'service:write' on \"postgres\""
2023-10-11T21:32:33.606-0700 [WARN]  agent: Service registration blocked by ACLs: service=47e7ed89-5c11-b681-29e4-6ef6b2c6d490 accessorID=47e7ed89-5c11-b681-29e4-6ef6b2c6d490

How do I construct an acl to allow .5 to register on .7?

Do I reapply the same acl I used on .7 on .5? (using .5ā€™s token???)

Hi @marquis.of.sandwiche,

Are you not using service-identity tokens as described in this link: Secure Consul with access control lists (ACLs) | Consul | HashiCorp Developer

From the error, it looks like your tokens policy doesnā€™t allow write for the service named postgres.

What do you mean by .5 and .7 in this context? If they are different VM instances, yes, you can use the same token on both servers.

But from a security best practice point of view, it is better you repeat that service-identity command and create different tokens for each server. It all depends on your preference.

Thanks for the reply. .5 and .7 are the suffixes to a couple of VMs. I deleted everything in /opt/consul and started from scratch for the following:
config.hcl has

acl {
  enabled = true
  default_policy = "allow"
  enable_token_persistence = true
}
  1. created bootstrap token.
  2. create agent token on each host. (.5 and .7 VMs)
  3. create service token. (I assume this is global???)
    I confirmed they are there using the global token
    export CONSUL_HTTP_TOKEN="global-uuid" ; consul acl token list
  4. Switch to agentā€™s token.
    export CONSUL_HTTP_TOKEN=".5-uuid" ; consul acl token list
    As expected, access is denied.
  5. export CONSUL_HTTP_TOKEN=ā€œ.7-tokenā€ ; consul acl policy create -name ā€œdot-seven-serviceā€ -description ā€œallow .7 serviceā€ -rules @consul-acl-policy.hcl
    Access denied which, makes sense. Then using the global uuid, it works as expected.
    This is whatā€™s in consul-acl-policy.hcl
service_prefix "" {
   policy = "write"
}

session_prefix "" {
  policy = "write"
}

key_prefix "" {
  policy = "write"
}

node_prefix "" {
  policy = "read"
}

agent_prefix "" {
  policy = "read"
}


service "postgres" {
 policy = "write"
}
  1. Reload each node just in case thereā€™s something to be had doing so.
  2. Start patroni (itā€™s running/logging to stdout on another shell.)
    Error:
    [ERROR] agent.http: Request error: method=PUT url=/v1/agent/service/register from=192.168.2.5:52268 error=ā€œPermission denied: token with AccessorID ā€˜9f43f7d6-ac59-fadf-9975-4f3ece8096beā€™ lacks permission ā€˜service:writeā€™ on "postgres"ā€

uuid ending in be is .7

.7 still doesnā€™t have access despite the acl applied with the global secret.

Not sure where to go from here.

Thereā€™s no obvious directions in the documentation once you apply the ACL.

The next step is to create a role that marries the ACL policy(ies) , service identities, and node-identities.
CONSUL_HTTP_TOKEN=ā€œglobal-keyā€ consul acl role create -name ā€œregisterā€ -description ā€œservice register roleā€ -policy-name ā€œbarā€ -policy-name ā€œrooā€ -service-identity ā€œpostgresā€ -datacenter ā€œbatcaveā€ -node-identity ā€œzebra:batcaveā€ -node-identity ā€œgiraffe:batcaveā€ -node-identity ā€œokapi:batcaveā€

But, this still doesnā€™t permit the service from registering. My gut feeling is, something about the URL needs an acl. But, no idea what.

[ERROR] agent.http: Request error: method=PUT url=/v1/agent/service/register from=192.168.2.5:59038 error="Permission denied: token with AccessorID ā€˜.5-uuidā€™ la
cks permission ā€˜service:writeā€™ on "postgres""

Hi @marquis.of.sandwiche,

Could you share the output of the following command?

consul acl token read -id <.5-uuid> -token <privileged-token> -expanded

The errors says that the token you are using to register the postgres service doesnā€™t have the required permissions.

1 Like

Hi, thanks so much for your help.

AccessorID:       postgres-uuid
SecretID:        foo
Description:      Token for postgres
Local:            false
Create Time:      2023-10-15 14:42:57.220490726 -0700 PDT
Service Identities:
        Name: postgresql (Datacenters: all)
                Description: synthetic policy for service identity "postgresql"
                Rules:
                        service "postgresql" {
                                policy = "write"
                        }
                        service "postgresql-sidecar-proxy" {
                                policy = "write"
                        }
                        service_prefix "" {
                                policy = "read"
                        }
                        node_prefix "" {
                                policy = "read"
                        }

=== End of Authorizer Layer 0: Token ===
=== Start of Authorizer Layer 2: Agent Configuration Defaults (Inherited) ===
Description: Defined at request-time by the agent that resolves the ACL token; other agents may have different configuration defaults
Resolved By Agent: ".7-host"

Default Policy: allow
        Description: Backstop rule used if no preceding layer has a matching rule (refer to default_policy option in agent configuration)

Down Policy: extend-cache
        Description: Defines what to do if this Token's information cannot be read from the primary_datacenter (refer to down_policy option in agent configuration)

And then, hereā€™s the same info for the .7 token

AccessorID:       .7-token-id
SecretID:         bar
Description:      Token for zebra
Local:            false
Create Time:      2023-10-15 14:45:59.339792967 -0700 PDT
Node Identities:
        Name: zebra (Datacenter: batcave)
                Description: synthetic policy for node identity "zebra"
                Rules:
                        node "zebra" {
                                policy = "write"
                        }
                        service_prefix "" {
                                policy = "read"
                        }

=== End of Authorizer Layer 0: Token ===
=== Start of Authorizer Layer 2: Agent Configuration Defaults (Inherited) ===
Description: Defined at request-time by the agent that resolves the ACL token; other agents may have different configuration defaults
Resolved By Agent: "zebra"

Default Policy: allow
        Description: Backstop rule used if no preceding layer has a matching rule (refer to default_policy option in agent configuration)

Down Policy: extend-cache
        Description: Defines what to do if this Token's information cannot be read from the primary_datacenter (refer to down_policy option in agent configuration)

Hi @marquis.of.sandwiche,

Thank you for sharing the output. If you compare the error log and the policy, you will see that, you are trying to register the service with the name postgres, but your policy only allows for the service named postgresql.

With the token you shared, you will be able to register the service with the name postgresql. So to fix the issue, either change the service name to postgresql, or create and use a token with service-identity for service named postgres.

I hope this helps.

I now have a service token for postgresql. Same results.
[ERROR] agent.http: Request error: method=PUT url=/v1/agent/service/register from=192.168.2.176:37474 error=ā€œPermission denied: token with AccessorID ā€˜099c6009-ceb1-94b7-7cfb-6a5efcee43e5ā€™ lacks permission ā€˜service:writeā€™ on "postgres"ā€

Patroni still, apparently is trying to use the name postgres and is denied. No amount of permissive settings seems to work.

Can you share the output of:

consul acl token read -id 099c6009-ceb1-94b7-7cfb-6a5efcee43e5 -token <privileged-token> -expanded

Please only mask the secretid so that I can see the output is from the token with the correct accessor-id.

You should have a service-identity token for postgres, as whoever is trying to register the service is using the name postgres.

In addition, I think your local agent has a default_policy of ā€œdenyā€, which is why it is denying the request. I would say keep the default_policy as deny, and get the policy fixed.

Thank you for your continued patience with this.

You got me moving in the right direction. For reasons I have yet to sort out, despite granting postgres the exact same rights as postgresql, I changed the configuration on patroni to use the service name postgresql, and it worked.

I still get this error, but overall it actually seems to work right.
agent.http: Request error: method=GET url=/v1/agent/service/deregister/postgres/police-van from=192.168.2.176:34470 error=ā€œmethod GET not allowedā€
I am guessing that an acl like agent ā€œhttpā€ { policy = ā€œwriteā€ } fixes that??

Hi @marquis.of.sandwiche,

I am glad that you got it working.

This error has nothing to do with the ACL permissions. It just says that HTTP Method GET is not allowed. To deregister a service it should be HTTP PUT.

ref:

I hope this helps.