saltstack / salt

Software to automate the management and configuration of any infrastructure or application at scale. Get access to the Salt software package repository here:
https://repo.saltproject.io/
Apache License 2.0
14.09k stars 5.47k forks source link

Trusted grains (Having the salt-master add a signature to the grain) #31109

Open mrueg opened 8 years ago

mrueg commented 8 years ago

This is a feature request to improve the security on (e.g., role-based) grains. A possible scenario could have a production and development environment. The pillar's top.sls is using grains to decide which secrets (e.g. a tls priv key) are provided to each environment. As described in [1], a developer who has access to the development environment could add the production grains and get full access to the production secrets stored in the pillar.

Trusted grains could solve this issue by having the master issuing a signature on that grain, that is attached to the grain in some way and evaluated when hitting a grain during execution.

A possible signature for a single master setup (or multimaster sharing the same keys) could be a HMAC like HMAC(K,m) with m being a concatenation of the trusted grain variable name and the minion id, that is attached to the grain. A trusted grain renderer could then validate that the salt-master has issued that grain.

[1] https://docs.saltstack.com/en/latest/faq.html#is-targeting-using-grain-data-secure

jfindlay commented 8 years ago

@mrueg, thanks for reporting. This seems like a great idea.

damon-atkins commented 8 years ago

Register an OID for an SSL Cert with isot @ ansi.org Add values to the SSL certificate. i.e. if you sign it your accept the values as well.

stale[bot] commented 6 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.

eliasp commented 6 years ago

Should be kept open IMHO

stale[bot] commented 6 years ago

Thank you for updating this issue. It is no longer marked as stale.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.

mchugh19 commented 5 years ago

Still needed

stale[bot] commented 5 years ago

Thank you for updating this issue. It is no longer marked as stale.

dkfsalt commented 5 years ago

If I look past the implementation specifics of this request, the issue is that we can't trust grains to not be compromised (because they are stored on the endpoint and any salt command can run grains.set()), and so we must assume that either a brute force or inside attack can compromise the pillar data.

I see three possible responses to this:

  1. Don't associate pillar data with minions based on grain-based targets (thereby requiring either glob or list-based target for pillar files); this carries considerable management overhead (really big top or pillar files that can no longer be dynamic).

  2. Prevent tampering with the grain data (what this method is proposing), which comes with its own set of issues:

    • How do you set these secure grains? grains.set_secure()? grains_secure.set()?
    • Given that the module will be running on the minion, the minion must also be aware of the value of K (from the HMAC(K,m) example) which completely defeats the purpose of the suggested implementation
    • What happens if the data is tampered with? Does the minion silently refuse to run the job? Does it run, but return a "failure" simply because it's data has been tampered with? How would end users validate what the values should be and/or recover the correct values to the minion?
  3. Externalize the role data (don't store it on the minion) in a database or cmdb, which cannot be modified as part of a state run and that wraps an RBAC model around it such that some privileged users can change the values of these role "grains".

    • this requires a method to manage this data externally in such a way as to be more efficient than the first option, above - this is actually easy with a CMDB as a data-backed pillar
    • pillars must be loadable in "layers" such that any given pillar can create associations to minions based on the results of previously loaded pillars (ie - pillars are loaded in the order in which they appear in the config files, to make the loading behavior deterministic).
    • these pillar "roles" must be read-only to the minions (and the ext_pillar endpoint must either be unreachable to minions or must not offer any API capability to the minions) or they must only be settable via an orchestration from a known endpoint (ie - the API is only reachable from the master) or, better still, a non-salt orchestration engine that, once requested in the Service Catalogue (assuming provisioning of infrastructure and/or apps centrally), creates the CMDB record and sets the value of the record's "role" metadata.
  4. (okay, I lied, I can imagine four possibilities) Separate the environment using masters where "dev" masters only have "Dev" pillar data attached and "Prod" masters only have "prod" pillar data attached. This only solves the OPs supposition that a "developer could add production grains to a test server to steal production secrets". By separating the pillar data by master, this becomes impossible... but it doesn't prevent a similar attack such that a "production user" could create grains for other roles to siphon off the secrets from those other roles (but, again, this requires a-priori knowledge of what those roles would be - which could be done with a simple brute-force attack).

So I guess the question is, what is the OP trying to achieve? Protection from tampering of /etc/salt/grains using an editor, protecting production secrets from developers or enforcing "separation of duty"?

The-Loeki commented 5 years ago

I really have no idea how this is supposed to work. The OP calls for 'master-issued grains' which IMHO is exactly what Pillar does.

But not before he laments that the (his?) Pillars' top.sls is using grains to determine which secrets get sent out where, together with an article pointing out exactly why this is such a bad idea by design.

As grains are by definition locally administered and configured, nothing will ever solve that. Want a salt-master to sign a received grain? All it can vouch for is what it received the first time, establishing 'trust' based on an insecure, locally administered config, rendering it total snake-oil IMHO. You want the salt master to provide grains? That's exactly what Pillar data already does. You want the CMDB to feed trustworthy info? As @dkfsalt notes, again, that's exactly what you can and should be doing with Pillar.

So I'm convinced that the current implementation is actually clean & clear-cut:

All that's apparently missing is documentation making that point way more clear.

mrueg commented 5 years ago

Thanks for providing feedback, unfortunately this issue has seen its third birthday and I don't remember exactly what my original issue was. I don't use saltstack at the moment for state enforcement, so I would leave re-defining this issue to other interested users (as a few kept this issue open for quite a while).

jfindlay commented 5 years ago

My opinion is that if you want secure data use pillar or sdb or some external secret store (with a pillar driver). Grains were never designed to be secure in this manner. If you can't trust your minions to be honest or benign with their grains, you should just not trust them and instead use something that you can trust.

jfindlay commented 5 years ago

My perspective is that it would be better for salt core features to have more concrete roles so that, much like the zen of python there is more common guidance on how to apply salty principles to a given use case. If your goal is secure targeting and using pillar/sdb is not immediately obvious as the solution, then pillar/sdb (documentation) needs to be updated to work in (explain) more cases.

damon-atkins commented 5 years ago

The idea is the minion certificate contains the roles/facts. As minion certificate is signed and therefore has integrity the roles can be trusted information within the certificate. Its part of an auto sign solution. You kick off a build of a server and provide it with a minion certificate already signed with the embedded role. Because you can trust this information from the minion, you can use it for targeting. Salt Master does not have to be the server signing the certificates.

The aim is not having to update to top file every time you build a new server, or having to add or maintain entries in pillar.

Register an OID for an SSL Cert with isot @ ansi.org Add values to the SSL certificate. i.e. if you sign it your accept the values as well.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

If this issue is closed prematurely, please leave a comment and we will gladly reopen the issue.

mchugh19 commented 4 years ago

Not stale

stale[bot] commented 4 years ago

Thank you for updating this issue. It is no longer marked as stale.

Oloremo commented 3 years ago

Would be very helpful to have