-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Canonical solution for securely transferring data between minions #45882
Comments
Have you looked at vault + sdb? I would generate the certificate, and store it in sdb, and then put it under a role so that only certain minions can directly access it. You can also use something like https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.sdb.html#salt.modules.sdb.get_or_set_hash to generate a shared password between a bunch of minions, so they can all access it. Another option would be to store the certificate in an external data base pillar, and then use regular salt states to set the pillar data by controlling the database directly. I think both of those options fulfill your need to move it securely, and that is how I would do it so that it does not get put somewhere where other minions can't see it when it is being set. Vault + SDB is probably my perferred, because there is already an sdb.set () function where you can just put the certificate there, instead of having to try and write custom states to query a database and insert data. I also know that there are people out there right now using vault for this purpose with sdb. |
I've looked at Vault, and it definitely is the direction I'd go if you needed to manage lots of credentials, but that's another piece of third-party software to manage. The goal was to do this all with Salt. If you have to manage separate credentials and ACLs, that defeats the purpose, and you might as well just run a secure file host (like git) on the first minion.
Again, third-party software, and another ACL.
But the whole point is that we want to put it somewhere where other minions can't see it. |
That is the point of sdb though, to be able to put secure data where other minions can see and access it. If you have to use a salt system, you could use publish.publish and allow only specific minions to run commands on the first minion to get the data back, but that puts a lot more load on the salt master server. This is one of the usecases that sdb was created for. |
Perhaps I'm missing the point then. I dug into the SDB documentation, and I see that I can use (for example) a YAML file stored on the master, which I feel would meet my "do this all with Salt" criteria. However, I'm not sure how to manage the permissions/ACLs for this data. The documentation for SDB does not indicate any means of setting any kind of limits on access.
Publish also uses the |
The vault sdb uses the vault execution module can have acls to allow only certain minions access to the data. https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.vault.html
And then in vault you would only allow each minions role access to whatever data, and then only allow them to read it, and then your minion that generates the variable would have access to pull the data. There are several other modules that could be used but vault is by far the most used, specifically because it is meant as a secret store. |
Is it therefore correct to say that there is no built-in method to securely transfer data from a minion to the master (such that no other minion can snoop on this data)? Obviously, Salt has built-in methods to securely transfer files via third-party tools/services. With this in mind, I'm trying to understand the Vault solution, since it sounds like that's the easiest solution that will work for me. However, I'm struggling with the "policies" part. If I wanted to create a policy that allows all minions access to read a path of the form |
@Nick2253 there is a Also, can you show me how it other minions would be able to see the information that is sent to the salt master to would be able to be seen by other minions? Pillars especially, because no other minion should be able to see that data, except for the minion it is sent to. |
The grammar is kinda broken in this sentence, so I'm not exactly sure what you're asking. I'm assuming you're asking "how can other minions see the data that a first salt minion sends to the master?". To answer that, I'd refer you to the Salt documentation on the request channel:
By diving into the code for the different methods, you can see that they ultimately use the relatively insecure I'm not suggesting that the data from the master to the minions (including any pillar data) is insecure. |
I have local patches to the salt mine to allow for minion-pushed ACL, where the |
Hey @github-abcde - that sounds interesting. Would you mind sharing your code (and eventually submit a PR?). Cheers! |
@github-abcde @mirceaulinic I am also interested in this change. If I am not mistaken this could be this branch: Looking forward to this change 👍 |
If the goal is to get LE certs from one minion to many others, that seems relatively easy to do within salt.
For added fun, the reactor could, after putting data into sdb, run an orchestration that tells specific minions they need to refresh pillar and run a set of states. |
Another option, partially suggested by someone on IRC...
This is a lot less steps, but also less flexible. I suspect it would still require use of the event, reactor, and orchestrate systems. Their suggestion also mentioned that the minions could leverage existing key pairs that the minions already use for communication with the master. |
Hi, Apologize for posting my clarification here. |
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. |
Description of Question
I've been trying to determine the canonical solution to the following problem:
An example of this process is generating a Let's Encrypt certificate from a web-accessible client (first minion) for a web-inaccessible client (second minion), and passing the certificate and key to the second minion. This particular example will become even more important once Let's Encrypt allows wildcard certs at the end of February.
Another example of this process is generating an Icinga2 client ticket. When a new minion (the second minion) is added to the network, the Icinga2 master (the first minion) generates a ticket, and the second minion needs that ticket to complete client setup.
A further example of this process is a username/password. Many legacy services are only accessible via usernames/passwords, and they have requirements for regular password changes (usually for regulatory reasons). These services can be configured to automatically generate a new password (on the first minion), and these passwords need to be send to clients that need them (the second minion).
Possible Solutions, and Problems
I have seen a few possible solutions discussed on the internet, but no solution seems to provide all these features:
Generally speaking, the first part of the problem is easily done in Salt. Whether with a custom method, a command, etc, it's fairly easy to either create a file, or even a pillar file, containing the secure data on the first minion. The challenge is the second part: moving the file securely using Salt.
I'm assuming that the best way to handle this is transfer the file from the first minion to the master, and then from the master to the second minion. This assumption is also shared with some of the solutions I've seen below.
cp.push
As suggested in #31863
The general workflow is to use
cp.push
to send the file from the first minion to the master. However,cp.push
usessalt.transport.Channel.send()
, which is not guaranteed to be confidential.If we could add a "secure" flag to the
cp.push
method to use thecrypted_transfer_decode_dictentry
, that would enable a means to securely pass the files to the master.event.send
As suggested in #27156
The general workflow is to generate the secure data on the first minion, and then trigger an event, passing the secure data from the first minion to the master. A reactor is triggered on the event, and applies the data to the second minion.
However, this method has the same problems as
cp.push
. All data passed in events, including pillar data, uses the.send()
transport.Salt Mine
As suggested in #27156, #44564
The general workflow is to create a mine function that takes the secure data from the first minion. Then, the data can be used by the second minion.
However (other then the general inapplicability of a salt mine for rarely changing data), the Salt Mine's permission schemes do not support the ability for one minion's data to be selectively parsed out to other minions.
Concluding Thoughts
I've been trying to research these options, diving into the Salt code for the last couple weeks. However, I've come up empty handed. Looking at how this is handled in other configuration management systems, to me, is straightforward. I can't imagine that this task is impossible in Salt, since everything else I've seen tells me that Salt is very powerful. I can only assume that I'm making some deep-seated assumption that is creating an implied solution, and forcing me into a narrow box.
My goal here is to either (1) learn what I'm missing, and help produce documentation for other new users in my shoes, or (2) bring this issue to the attention of the Salt team, and hopefully contribute to a solution to this problem.
The text was updated successfully, but these errors were encountered: