diff --git a/howto/puppet.md b/howto/puppet.md index 6927360d4d4e6f1219358194c9cf81ed635238b7..26b13eff22c8775ba5c2a87ef4b2e66ce3d6437d 100644 --- a/howto/puppet.md +++ b/howto/puppet.md @@ -587,7 +587,10 @@ general, it's safe to use `trocla create` as it will reuse existing password. It's actually how the `trocla()` function behaves in Puppet as well. -## Exported resources + +## Getting information from other nodes + +### Exported resources Our Puppet configuration supports [exported resources](https://puppet.com/docs/puppet/latest/lang_exported.html), a key component of complex Puppet deployments. Exported resources allow one @@ -610,13 +613,30 @@ line). This rule doesn't take effect on the host applying the `roles::puppetmaster` class, but only on the LDAP server, through this rather exotic syntax: - Ferm::Rule::Simple <<| tag == 'roles::puppetmaster' |>> + Ferm::Rule::Simple <<| tag == 'roles::puppetmaster' |>> This tells the LDAP server to apply whatever rule was exported with the `@@` syntax and the specified `tag`. Any Puppet resource can be exported and realized that way. -## Getting facts from other hosts +Note that there are security implications with collecting exported +resources: it delegates the resource specification of a node to +another. So, in the above scenario, the Puppet master could decide to +open *other* ports on the LDAP server (say, the SSH port), because it +exports the port number and the LDAP server just blindly applies the +directive. A more secure specification would explicitly specify the +sensitive information, like so: + + Ferm::Rule::Simple <<| tag == 'roles::puppetmaster' |>> { + port => ['ldap'], + } + +But then a compromised server could send a different `saddr` and +there's nothing the LDAP server could do here: it cannot override the +address because it's exactly the information we need from the other +server... + +### PuppetDB lookups A common pattern in Puppet is to extract information from host A and use it on host B. The above "exported resources" pattern can do this @@ -644,10 +664,25 @@ like this: deny all; <% } -%> -This would be technically possible with a `concat` resource, but much -harder because you would need some special case when no resource is -exported (to avoid adding the `deny`) and take into account that other -configuratinos might also be needed in the file. +Note that there is a potential security issue with that approach. The +same way that exported resources trust the exporter, we trust that the +node exported the right fact. So it's in theory possible that a +compromised Puppet node exports an evil IP address in the above +example, granting access to an attacker instead of the proper node. + +Also note that this will eventually fail when the node goes down: +after a while, resources are expired from the PuppetDB server and the +above query will return an empty list. This seems reasonable: we do +want to eventually revoke access to nodes that go away, but it's still +something to keep in mind. + +Note that this could also be implemented with a `concat` exported +resource, but much harder because you would need some special case +when no resource is exported (to avoid adding the `deny`) and take +into account that other configuratinos might also be needed in the +file. It would have the same security and expiry issues anyways. + +### Puppet query language Note that there's also a way to do those queries without a Forge module, through the [Puppet query language](https://puppet.com/docs/puppetdb/5.2/api/query/tutorial-pql.html) and the