How to get username of user logged in via LDAP in my logical plugin

400 views
Skip to first unread message

Sebastian Ostrowski

unread,
Jul 17, 2018, 2:31:50 PM7/17/18
to Vault
Hi,

I am writing a plugin which generates random tokens and stores them in vault in kv for purposes of adding auth backend to NSQD.
I am looking for a way to get the username associated with the person using my plugin for auditing purposes. My workflow is as follows

- get vault token using ldap
- login to vault using token
- request token from my plugin
- plugin generates token and saves it as KV.

I know my ldap username is tracked along with the token i use because it's in audit logs:


1) LDAP Auth

{
  "time""2018-07-11T17:35:51.576117868Z",
  "type""request",
  "auth": {
    "client_token""",
    "accessor""",
    "display_name""",
    "policies"null,
    "metadata"null,
    "entity_id"""
  },
  "request": {
    "id""5ea5d12b-0e7b-a571-cc2a-34e909573aed",
    "operation""update",
    "client_token""",
    "client_token_accessor""",
    "path""auth/ldap/login/seba",
    "data": {
      "password""hmac-sha256:f3066947b57b2468ac49cf8b9fa916fa78112e60d12d317aa348c0237231ee74"
    },
    "policy_override"false,
    "remote_address""172.25.44.136",
    "wrap_ttl": 0,
    "headers": {}
  },
  "error"""
}


  "time""2018-07-11T17:35:51.953444112Z",
  "type""response",
  "auth": {
    "client_token""hmac-sha256:b4e71e110ce6268a3d7b4a983d97cbf5ad78e59b0e3def8894c2e0d85ef64577",
    "accessor""hmac-sha256:f9812acd0943f707df02fcc6c222417aaeeaf8d5c6acdb522330bab3b9aeb428",
    "display_name""ldap-seba",
    "policies": [
      "default",
      "ldap-example",
      "nsq-access",
      "platform-cassandra",
      "plugin-provisioner",
      "sre-cassandra",
      "sre-vault-provision",
      "token-creator"
    ],
    "metadata": {
      "username""seba"
    },
    "entity_id""40201dd2-8f97-f9d1-9416-b5188e86c080"
  },
  "request": {
    "id""5ea5d12b-0e7b-a571-cc2a-34e909573aed",
    "operation""update",
    "client_token""",
    "client_token_accessor""",
    "path""auth/ldap/login/seba",
    "data": {
      "password""hmac-sha256:f3066947b57b2468ac49cf8b9fa916fa78112e60d12d317aa348c0237231ee74"
    },
    "policy_override"false,
    "remote_address""172.25.44.136",
    "wrap_ttl": 0,
    "headers": {}
  },
  "response": {
    "auth": {
      "client_token""hmac-sha256:b4e71e110ce6268a3d7b4a983d97cbf5ad78e59b0e3def8894c2e0d85ef64577",
      "accessor""hmac-sha256:f9812acd0943f707df02fcc6c222417aaeeaf8d5c6acdb522330bab3b9aeb428",
      "display_name""ldap-seba",
      "policies": [
        "default",
        "ldap-example",
        "nsq-access",
        "platform-cassandra",
        "plugin-provisioner",
        "sre-cassandra",
        "sre-vault-provision",
        "token-creator"
      ],
      "metadata": {
        "username""seba"
      },
      "entity_id"""
    }
  },
  "error"""
}

2) Access my plugin at nsq/get-token so that it generates a token for me 
vault write nsq/get-token topics=topic1,topic2


  "time""2018-07-11T17:27:24.563804807Z",
  "type""request",
  "auth": {
    "client_token""hmac-sha256:f1f5d061564198deeeab296b71c1d84d3a8fc1a45c7741e286031d67d2edd01f",
    "accessor""hmac-sha256:85db794c59cf29abd7bbc4ecfd2e4e46cf07b92cc73814eca7f75e2aa0637ed9",
    "display_name""ldap-seba",
    "policies": [
      "default",
      "ldap-example",
      "nsq-access",
      "platform-cassandra",
      "plugin-provisioner",
      "sre-cassandra",
      "sre-vault-provision",
      "token-creator"
    ],
    "metadata": {
      "username""seba"
    },
    "entity_id""40201dd2-8f97-f9d1-9416-b5188e86c080"
  },
  "request": {
    "id""c495e073-cb6f-a991-49a9-4b3daf86ae29",
    "operation""update",
    "client_token""hmac-sha256:f1f5d061564198deeeab296b71c1d84d3a8fc1a45c7741e286031d67d2edd01f",
    "client_token_accessor""hmac-sha256:85db794c59cf29abd7bbc4ecfd2e4e46cf07b92cc73814eca7f75e2aa0637ed9",
    "path""nsq/get-token",
    "data": {
      "topics""hmac-sha256:1e52fa0bf5c404d488baff921a5d5accda931d69373f3a3c07768f165c713609"
    },
    "policy_override"false,
    "remote_address""172.25.44.136",
    "wrap_ttl": 0,
    "headers": {}
  },
  "error"""
}
As you see in the audit log entry above, Vault logs my ldap username (seba) in this request. So it keeps track of the user name at this stage. Is there a way for me to get access to the username (metadata/username) above from inside of the plugin?

Thanks!

Sebastian Ostrowski

unread,
Jul 17, 2018, 5:51:43 PM7/17/18
to Vault
I think I just found the answer.
I can get the request's EntityID and use that to obtain metadata via https://www.vaultproject.io/api/secret/identity/entity.html#read-entity-by-id

so if in my plugin the callback function signature is 
func (b *backend) pathGetToken(c context.Context, req *logical.Request, d *framework.FieldData) (*logical.Response, error) {
then i can access entity id as req.EntityID. I will next need to build an API call with req.EntityID and extract the user name from that

example output from testing in CLI for posterity: 
if entityid is 40201dd2-8f97-f9d1-9416-b5188e86c080 then
> curl --header "X-Vault-Token: 4552bead-e7f4-1f5e-4708-718526d147b4" https://vault/v1/identity/entity/id/40201dd2-8f97-f9d1-9416-b5188e86c080 | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   825  100   825    0     0   5722      0 --:--:-- --:--:-- --:--:--  5935
{
  "request_id": "d68eaf92-ac58-f573-0daf-5a44e18cc1c0",
  "lease_id": "",
  "renewable": false,
  "lease_duration": 0,
  "data": {
    "aliases": [
      {
        "canonical_id": "40201dd2-8f97-f9d1-9416-b5188e86c080",
        "creation_time": "2018-05-17T20:02:41.185390527Z",
        "id": "a3bcf211-2da4-5d2e-dcb8-6fc3be60ec98",
        "last_update_time": "2018-05-17T20:02:41.185390527Z",
        "merged_from_canonical_ids": null,
        "metadata": null,
        "mount_accessor": "auth_ldap_a62caab1",
        "mount_path": "auth/ldap/",
        "mount_type": "ldap",
        "name": "seba"
      }
    ],
    "creation_time": "2018-05-17T20:02:41.185385942Z",
    "direct_group_ids": [],
    "disabled": false,
    "group_ids": [],
    "id": "40201dd2-8f97-f9d1-9416-b5188e86c080",
    "inherited_group_ids": [],
    "last_update_time": "2018-05-17T20:02:41.185385942Z",
    "merged_entity_ids": null,
    "metadata": null,
    "name": "entity_48ac1e24",
    "policies": null
  },
  "wrap_info": null,
  "warnings": null,
  "auth": null
}


Jeff Mitchell

unread,
Jul 18, 2018, 11:56:12 AM7/18/18
to Vault
Hi Sebastian,

Just so I understand: your workflow is that someone authenticates to Vault, then makes a call to Vault to a custom plugin, which itself then makes another HTTPS call to Vault to a different backend to store a value?

I'm not sure what you're generating but it feels like you might have an easier time using an out-of-band process.

Best,
Jeff

Sebastian Ostrowski

unread,
Jul 18, 2018, 4:14:32 PM7/18/18
to Vault
Hi Jeff,

Thanks for responding. There's some naming overlap (Vault token / NSQ token), but generally the custom plugin generates a secret and stores it in vault. The user then uses that secret token to authenticate to NSQD configured with auth server which validates the token in Vault.

Jeff Mitchell

unread,
Jul 19, 2018, 9:01:14 AM7/19/18
to Vault
Hi Sebastian,

I'm not really understanding the plugin angle here. Plugins can't talk to each other so your custom plugin would have to be configured as a normal Vault client to talk back to itself. Given that you're likely way better off writing a simple external client that generates these secrets. In 0.11 you'll be able to put entity values as part of ACL paths which I think is the missing key there.

Best,
Jeff

--
This mailing list is governed under the HashiCorp Community Guidelines - https://www.hashicorp.com/community-guidelines.html. Behavior in violation of those guidelines may result in your removal from this mailing list.
 
GitHub Issues: https://github.com/hashicorp/vault/issues
IRC: #vault-tool on Freenode
---
You received this message because you are subscribed to the Google Groups "Vault" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vault-tool+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/vault-tool/86c7d75f-3ce8-4530-b1de-2fac2ed3de7a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Sebastian Ostrowski

unread,
Jul 24, 2018, 5:12:13 PM7/24/18
to Vault
Hi Jeff,

One of the big reasons why we've decided to build a custom Vault plugin is so we can build a uniform system for our engineers to access databases; whether it's cassandra, mysql or NSQD, they will follow the same steps to get access
- login to vault with LDAP
- request access to resource via vault CLI
- obtain cass / mysql password or NSQD token

This also means we get to benefit from reusing already developed solutions (LDAP auth, logging and log forwarding for example). There are other reasons, but this is at the core of our thinking.

For GDPR/SOC2 compliance purposes, we need to have auditing on who accesses what & when, which is why I was looking for a way to associate the Entity ID of the person using the plugin with their LDAP user name.
The implementation we arrived at does just that by making a call using client.Logical().Read("identity/entity/id/" + entityID) and extracting the user name from the provided metadata.

Thanks,
Reply all
Reply to author
Forward
0 new messages