Hi,I'm working in an environment where certain parameters need to be enforced per security requirements..The ways we've identified to do this are:
1) Put the specific settings in the profile:
Advantages: Utilize stock roles and profiles pattern, plenty of documentation and guides online.Disadvantage: The settings are part of the profile and thus two groups need to share ownership of the same module. Reduces flexibility or speed due to additional enforcement needed by shared ownership.2) Modify the modules themselves.Advantages: Configuration is part of the module.Disadvantages: We are now maintaining all custom modules.3) Extend roles and profiles to add an additional layer between existing profiles and the modules.The workflow would be:
Role (business layer) > Profile (technology layer) > Security (security layer) > Module.Advantages: Engineering configuration and security configuration are seperated, with security configuration enforced.Disadvantages: Need a way to present most options up to the profiles layer for parameterization, while enforcing a few options.We'd prefer to go with option 3. Does this make sense?
If so, some tips on how to go about this would be appreciated. Does it make sense for the security module to inherit the base module in this case? It would look something like this (but actually work :) )
class sec_profile::ssh inherits ::ssh {$server_options = { 'Protocol' => '2', 'Ciphers' => 'aes128-ctr,aes192-ctr,aes256-ctr', 'PermitRootLogin' => 'no', 'ClientAliveInterval' => '900', 'PermitEmptyPasswords' => 'no', 'PasswordAuthentication' => 'no', 'Port' => [22], } }
If not, can you suggest a good approach to present the base module options to the profile? We'd like to to allow parameterization / hiera lookups at the profile layer, preferrably without having to reimplement each option in the security layer.
You might be interested in this thread:
https://groups.google.com/forum/#!topic/puppet-users/nmVQQA6G-f8
On Thursday, April 2, 2015 at 4:02:30 PM UTC-5, Scott Jaffa wrote:Hi,I'm working in an environment where certain parameters need to be enforced per security requirements..The ways we've identified to do this are:
1) Put the specific settings in the profile:
Advantages: Utilize stock roles and profiles pattern, plenty of documentation and guides online.Disadvantage: The settings are part of the profile and thus two groups need to share ownership of the same module. Reduces flexibility or speed due to additional enforcement needed by shared ownership.2) Modify the modules themselves.Advantages: Configuration is part of the module.Disadvantages: We are now maintaining all custom modules.3) Extend roles and profiles to add an additional layer between existing profiles and the modules.The workflow would be:
Role (business layer) > Profile (technology layer) > Security (security layer) > Module.Advantages: Engineering configuration and security configuration are seperated, with security configuration enforced.Disadvantages: Need a way to present most options up to the profiles layer for parameterization, while enforcing a few options.We'd prefer to go with option 3. Does this make sense?
I'm having trouble understanding how you propose to factor out security considerations from the technology to which they apply. Is this just about ownership of data, or do there need to be bona fide security-specific resources? If the former, then what do you need that you cannot achieve via a security-specific level in your Hiera hierarchy? If the latter, then how would making the security classes responsible for declaring component-level classes (per option 3) achieve the separation of concerns you claim as an advantage?
If so, some tips on how to go about this would be appreciated. Does it make sense for the security module to inherit the base module in this case? It would look something like this (but actually work :) )
class sec_profile::ssh inherits ::ssh {$server_options = { 'Protocol' => '2', 'Ciphers' => 'aes128-ctr,aes192-ctr,aes256-ctr', 'PermitRootLogin' => 'no', 'ClientAliveInterval' => '900', 'PermitEmptyPasswords' => 'no', 'PasswordAuthentication' => 'no', 'Port' => [22], } }
If you are contemplating class inheritance for the purpose of greater freedom in applying resource property overrides, then maybe they would be useful to you. If you have an idea that they would do anything else for you, then put it out of your mind -- class inheritance doesn't work that way (whatever way that happens to be). Note, however, that often you can perform resource overrides without class inheritance, that often it is better to modify the external data from which modules draw property values than to override property values after the fact, and that class inheritance creates a very tight coupling that is probably better avoided if it crosses module boundaries.
If not, can you suggest a good approach to present the base module options to the profile? We'd like to to allow parameterization / hiera lookups at the profile layer, preferrably without having to reimplement each option in the security layer.
It would help if you presented a representative example of what you're trying to configure, and explained the challenge you face with respect to that. What you've presented so far is too abstract for me to offer any specific advice.
John
This wrapper module would provide an expose the specific configuration options required for security hardening, while allowing the calling profile to pass through environment parameters, as is done today.
To continue with the SSH example (pardon the mix of pseudocode and bad puppet code, my puppet code is very rusty):
Today, the profile declares SSH as a needed class:class profile::base {class { '::ssh': }}This uses the ssh class (saz-ssh in my instance) with default options. However, the security configuration requires some options be set.What we'd do is call:class { 'sec_profile::ssh':security_hardening => 'true' (or via hiera lookup) }
This class would, via inheritance or another method, expose all of the existing parameters of the saz-ssh module which we downloaded from the forge.
However, within this class, it would specifically set the needed security options. Logic would be added to identify if security hardening is enabled, and if so, set the appropriate parameters as required. This would not modify any of the inherited module logic. As above, sec_profile would then inherit saz-ssh, adding the needed parameters, but allow a profile to set any other parameters. In this way, the only code which needs writing is the specific security options, and the rest is exposed as is. This would obviously link the wrapper module to a specific base module, but that's ok:class { 'sec_profile::ssh':security_hardening => 'true',non_security_parameter => 'value' }
...The obvious question is: why not put the security options into the profiles themselves and be done with it? 1) As mentioned above, we could have multiple profiles calling the same module, requiring maintainance of settings in multiple places.
2) Engineering and security would have to share the profile classes, which breaks some of the role separation and makes auditing (slightly) more complicated.
3) The goal is to release the security modules publicly, and wrapping them into the site specific profiles makes that impossible.
John,
Thanks for the detailed reply. While we aren't in agreement on some of the finer points, it is moot as you've made it quite clear that the listed approaches won't work at a technical level.
Stepping back, can you suggest a good method by which one could separate out cross organizational (in this case security hardening) parameters in a way that they could be shared across organizations?
Assuming the answer, shared or not, for the security layer is hiera, I need to put more thought into the structure.