freedomofpress / ansible-role-grsecurity

The documentation and build system for the grsecurity kernel maintained by the Freedom of the Press Foundation for SecureDrop
GNU General Public License v2.0
49 stars 13 forks source link

Automate GRUB config for install role #22

Closed conorsch closed 9 years ago

conorsch commented 9 years ago

Adds a module to the install role for handling the GRUB menu entries. The module is read-only, leaving manipulation of the GRUB config to tasks and associated handlers. The module is smart enough to handle parsing of a grub.cfg file at an arbitrary filepath, which is wonderful for debugging.

The action returns a dict of options representing GRUB menu items:

testbox | success >> {
    "ansible_facts": {
        "grub_menu_options": [
            {
                "index": 0, 
                "name": "Debian GNU/Linux", 
                "root": null
            }, 
            {
                "index": 1, 
                "name": "Debian GNU/Linux, with Linux 3.16.0-4-amd64", 
                "root": null
            }, 
            {
                "index": 2, 
                "name": "Debian GNU/Linux, with Linux 3.16.0-4-amd64 (recovery mode)", 
                "root": null
            }, 
            {
                "index": 3, 
                "name": "Debian GNU/Linux, with Linux 3.14.54-grsec", 
                "root": null
            }, 
            {
                "index": 4, 
                "name": "Debian GNU/Linux, with Linux 3.14.54-grsec (recovery mode)", 
                "root": null
            }
        ]
    }, 
    "changed": false
}

Given that vars dict, it's trivial to find a target grsec kernel with something like:

- name: Find the menu title for the grsecurity kernel in GRUB config.
  set_fact:
    grub_grsecurity_menu_entry: "{{ item }}"
  with_items: grub_menu_options
  when: "{{ item.name | match('.*-grsec$') }}"

It would be possible to return the grsec kernel from the module, but doing so seems a bit tightly coupled to me. Happy to make the change if someone convinces me it'd be useful.

conorsch commented 9 years ago

Afterthought: add a user-friendly failure message if the GRUB config file isn't found for some reason. Right now, setting the grub_config path to a non-existent location results in a stack trace. A better solution would catch the IOError and pass a helpful message back to the calling playbook via module.fail_json. Should reduce headaches when debugging on unsupported platforms.

ageis commented 9 years ago

How will that match() behave if there are multiple grsec kernel entries? We want it to grab the first occurrence.

conorsch commented 9 years ago

Added a custom fail message for missing file. Rather than stack trace, module will now display:

{
    "failed": true, 
    "msg": "Could not find GRUB config file at /path/to/fake/file . Check that 
the file exists and is readable. You can specify a custom filepath via the 
'grub_config' module parameter."
}
conorsch commented 9 years ago

@ageis The install role cautiously refuses to install grsec debs on top of each other. You're right that we need to test the match filter functionality, but first we need to compare versions of deb packages, so we can check for a specific version of the grsec kernel running, rather than just any ol' grsec kernel. Will open another issue to track.

conorsch commented 9 years ago

Rebased onto develop prior to merge.