KV storage - get data only if authenticated

Hi all,
I’ve read through man . And did not figure out if it is possible to use authentication mechanism to deny api requests without valid token in http header.
For example, I want to get a key by requesting /kv/:key(as it stipulated in the man) But how can I filter such kind of requests for those only who gives valid jet? Or maybe it needs to put private keys on server side and validate these requests with the keys. What is the good practice to protect key-value consul storage?

Hi @rituzy,

Have a look at the Consul ACLs. Using ACLs you will be able to set permissions against Consul KV entries. Sharing some links to the documentation below.

Hi @Ranjandas
Thank you for prompt reply. But all these documentations are about ACL. But what if I want to authenticate with keycloack server or validate JWT token came with incoming request? Maybe there is a way to use JWT authentication through ACL mechanism?

@rituzy, Yes you can authenticate external users using Consul Auth Methods and the users can be mapped to custom ACL roles using binding rules. - ACL Auth Methods | Consul by HashiCorp

This guide shows how OIDC is configured with Auth0 as the backend - Authenticate Users with Single Sign-On (SSO) and Auth0 | Consul - HashiCorp Learn.

Please note that the OIDC auth-method type is an Enterprise feature.

Hi @rituzy,

As @Ranjandas mentioned, Consul’s ACL system is the appropriate way to secure access to resources like KV entries, services, etc.

Consul’s JWT auth method allows a user to authenticate with Consul using a valid JWT and obtain an ACL token based on information contained within the JWT claims. The permissions granted to this token are defined by the operator via ACL binding rules.

Its important to note that this authentication via JWT should only happen for the initial login. All subsequent API requests from the client should utilize the issued ACL token until it expires, at which point the client and login again using another valid JWT so that they can obtain an updated ACL token.

1 Like

Hi @Blake ,
thanks for you reply. Let me sum up this info and show the example.

Purpose : client wants to get data from consul storage.

  1. Client sends PUT request to consul <consul-address>/acl/auth-method with payload :
    {
    “Name”: “client-name”,
    “Type”: “jet”,
    “Description”: “client connection”,
    “Config”: {
    " JWKSURL": “https://my-corp-jwks-url.example.com/
    }
    }

  2. Client gets response with token (JWT or ACL token?)

  3. Client gets data with this token in http header : GET request <consul-address>/kv/:key
    (Prior it needs to add role, identity and bind them with binding.)

  4. Client sends request logout requuest: DELETE <consul-address>/acl/auth-method/:name with this token to make this token invalid

Is this algorithm correct or maybe we need to take something else into the picture?
And how this interaction with JWKSURL is set? At which step we use our keyclock auth provider here?

P.S. and it’s not clear for me, what I reached by auth-method PUT method (from here) What should I use to get key-value data with all this staff in reply

{
    "Name": "client-name",
    "Type": "jwt",
    "Description": "client connection",
    "Config": {
        "JWKSURL": "https://my-corp-jwks-url.example.com/"
    },
    "CreateIndex": 130123,
    "ModifyIndex": 130123
}

Hi @rituzy,

This auth method should be pre-created by the cluster operator.

{
  “Name”: “jwt-auth-method”,
  “Type”: “jwt”,
  “Description”: “Auth method for logging into Consul using JWT tokens”,
  “Config”: {
    "JWKSURL": “https://my-corp-jwks-url.example.com/”
  }
}

It will be referenced by clients when they send a POST request to /v1/acl/login in order to login to the API using the auth method.

{
  "AuthMethod": "jwt-auth-method",
  "BearerToken": "<jwt token>"
}

The client would receive a Consul ACL token in the response. See the auth method login sample response for an example of this output.

The client then provides the SecretID in the X-Consul-Token or Authorization header when making requests to Consul. See HTTP API authentication for more detail.

When the client is ready to logout, it can send a POST request to /v1/acl/logout in order to destroy the API token.

If you want to obtain KV data, you will need to use the /v1/kv API endpoint.

I hope this helps. Let me know if you have any additional questions.

Hi @blake,
thank you so much for such a big explanation with quick example. But I failed to pass second step with calling /v1/acl/login method

I send this put request /v1/acl/auth-method

    {
        "Name": "ja9",
        "Type": "jwt",
        "Description": "client connection",
        "Config": {
            "JWKSURL": "https://my-corp-jwks-url.example.com/protocol/openid-connect/certs",
            "BoundAudiences": [
                "acc"
            ]
        }
    }

(I need to put BoundAudiences as JWT contains thisaud claim. Otherwise on the next step(see below) consul complains that aud is found in the token and neither audience names were given to consul)
I receive success result of creating the method

    {
    "Name": "ja9",
    "Type": "jwt",
    "Description": "client connection",
    "Config": {
        "BoundAudiences": [
            "account"
        ],
        "JWKSURL": "https://my-corp-jwks-url.example.com/protocol/openid-connect/certs"
    },
    "CreateIndex": 153540,
    "ModifyIndex": 153540
    }

then on the step 2 I send a post request /v1/acl/login:

    {
      "AuthMethod": "ja9",
      "BearerToken": "<long string token goes here>"
    }

and receive response with 403 code
rpc error making call: Permission denied
Consul logs do not provide any more information about this error(only this string “Permition denied”)

If I try to decode the token I would find the KID field which can be met in the JWKS page. (that says that token is issued by correct issuer)

As a workaround for this problem I thought about placing RSA key in auth-method call. But I do have x5c field (this seems to be the same open part of the key but of cause not RSA with content like “===BEGIIN CERTIFICATE…”) And while trying to create auth method v1/acl/auth-method:

    {
        "Name": "ja10",
        "Type": "jwt",
        "Description": "client connection",
        "Config": {
            "JWTValidationPubKeys": [
                "<x5c field from jwks page goes here>"
            ],
            "BoundAudiences": [
                "acc"
            ]
        }
    }

consul responses:
rpc error making call: Invalid Auth Method: error parsing public key JWTValidationPubKeys[0]: data does not contain any valid RSA, ECDSA, or ED25519 public keys

Could you please help me to make my way further as per your instructions above?

Thank you in advance!

bump!
Btw could you please advise how can I get verbose security logs for authentication process?

The things needs to do for working process are:

  1. create policy for accessing kv storage
  2. create role and link to the policy above
  3. create acl binding-rule to auth method created earlier(see previous replies here)
    Than it will be working as described earlier.
    Thanks guys, the topic is closed.