More complex KV/ACL examples

942 views
Skip to first unread message

Daniel Silverman

unread,
Dec 15, 2014, 9:54:54 AM12/15/14
to consu...@googlegroups.com
Hi, I'm trying to structure a KV store + ACL policy that will work for a reasonably large collection of services and am having a bit of trouble working it out.  The documentation for ACLs is fairly sparse so I'm hoping there may be more options that I'm seeing.

Are there any wildcards or other operators that add more flexibility to the longest prefix matching?  For example, trying to separate public and private node data:

/kv/node/server1/role = worker
/kv/node/server1/private/password = abc123

Ideally the "private" path of *every* node would have a default "deny" policy.  Is something like this possible?  Or is there a better approach?

My first thought was just using "private" as the prefix and then selectively opening access, but this breaks down with more complex hierarchies.  For example, this structure wouldn't work because all production nodes should be able to read the LDAP credentials but only production *database* nodes should be able to read the DB password:

/kv/private/production/ldap_user = svc_ldap
/kv/private/production/database/password = abc123

Any ideas?  Do these examples make sense?

Thanks,
~Danny

Pete Emerson

unread,
Dec 16, 2014, 1:10:35 PM12/16/14
to consu...@googlegroups.com
The approach that I've taken is to encrypt sensitive data and store
the decryption key in consul. Then I set ACLs on the decryption key. I
can then see all keys, all unencrypted values (role = "worker"), and
if I don't have permissions on the decryption key, then I can see the
encrypted form of the config variable (private/password =
"encrypted:$ENCRYPTED_STRING". The nice thing about this for me is
that I'm versioning configs inside consul, and the developers can
*copy* encrypted data to make a new version of their configs, but they
still can't see the secret, because they don't have read permission on
the decryption key. I then decrypt the string on application startup,
setting environment variables for the application to use.

Here's the structure I'm using:

/keys/$environment/$application = "$DECRYPTION_KEY"
/configs/$environment/$application/$version/$key = "$plaintext_value"
/configs/$environment/$application/$version/$key = "encrypted:$encrypted_value"

Pete
> --
> You received this message because you are subscribed to the Google Groups
> "Consul" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to consul-tool...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Armon Dadgar

unread,
Dec 17, 2014, 1:30:49 AM12/17/14
to Pete Emerson, consu...@googlegroups.com
I think Pete's implementation is super interesting, and rather novel! I haven't seen that done before, very neat way to handle it.
However, I do think it is rather "invasive" in the sense that clients need to be aware of this and handle the decryption properly.

In the current implementation, there are no other operators or wildcards available to change the longest-prefix matching.
However, I can certainly see the case for wildcard matching to do things like handling a ".../private/" directory. Typically,
we see people organize it by service:

service/foo/...
service/bar/...

Then usually the ACL system is used to gate access to anything within a service boundary. However, there are certainly
more subtle cases like the ones you pointed out. Usually it just devolves into a complex ACL policy.


Best Regards,

Armon Dadgar

Ryan Breen

unread,
Dec 17, 2014, 4:52:20 PM12/17/14
to Armon Dadgar, consu...@googlegroups.com
An alternative approach we've taken is to store our configuration files in Git as a mix of plaintext and ciphertext as needed.  We use git2consul to transform those config files into KVs, and we use fsconsul (which in turn uses something we wrote called gosecret) to put a decrypted version on the filesystem of the target hosts.  Our security model is that only certain people (our ops team members, typically) have access to production systems, and they are responsible for placing the decryption keys at a particular location on disk.  They are also responsible for creating the type of data that tends to need encryption (DB passwords and the like), so a symmetric encryption model works nicely for us.

Clean and simple KVs that match a single key to a single value are cool and all, but our real-world use cases involve a lot of preexisting configuration files like redis.conf.  We want those files to live in source control so we can easily track changes, we want to use Consul to move them around the network, and we only want to encrypt the small pieces of those files that are private (like the master password in a redis.conf file).  git2consul solves the problem of turning these config files into KVs, and the token-based approach in gosecret lets us encrypt only those subsets of the files that really need it.

This also lets us keep our ACL policy simple because we don't really care who can read what.  Anyone can read anything from the KV because anything worth protecting will be encrypted gibberish that is only decryptable on the appropriate systems.  And only the servers running git2consul are given write access to the KV.

Not sure if that maps to anyone's use-case, but it's a really good fit for us.  The cool thing about Consul is that it enables such a variety of approaches to similar problems, and you can really tailor your approach to fit your organization's needs.

Ryan


Reply all
Reply to author
Forward
0 new messages