diff --git a/LICENSE b/LICENSE index 8dada3e..d645695 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,4 @@ + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -178,7 +179,7 @@ APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" + boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a @@ -186,7 +187,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright {yyyy} {name of copyright owner} + Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/NOTICE b/NOTICE new file mode 100755 index 0000000..65cd66b --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Ansible role - Tripwire.te_agent + +Copyright 2017 Tripwire, Inc. diff --git a/README.md b/README.md index cf2aacf..ddec21a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,94 @@ -# ansible-te_agent -Ansible Role for installing the Tripwire Enterprise Agent +Role Name +========= + +The te_agent role installs, configures, and manages the services of the +Tripwire Enterprise Agent. + +Requirements +------------ + +The Tripwire Enterprise Agent needs a Tripwire Enterprise Console server +to connect to. The server hostname and services passphrase are needed +to configure the Agent. + +The installer file for the Agent must also be available on the Ansible +control machine, for copying to the remote host for installation. + +Role Variables +-------------- + +```yaml +# REQUIRED variables (no default defined) +######################################### + +# Must be set to the path to the agent installer. Is copied to a +# temporary directory on the remote host for installation +te_agent_package_source: ~ +# Must be set to the hostname or IP address of the Tripwire Enterprise console +te_agent_te_server_host: ~ +# Must be set to the service passphrase for the Tripwire Enterprise console +te_agent_te_services_passphrase: ~ + +# OPTIONAL variables (no default) +################################# + +# If set, used to determine if the package needs to be upgraded +te_agent_package_version: ~ +# If set, is written to the agent tags file for initial registration +te_agent_tags: ~ + + +# from defaults/main.yml +te_agent_package_state: present +te_agent_package_install_path: '/usr/local/tripwire/te/agent' +te_agent_te_services_port: 9898 +te_agent_te_server_http_port: 8080 +te_agent_local_port: 9898 +te_agent_install_rtm: true +te_agent_proxy_port: 1080 +te_agent_rtm_port: 1169 +te_agent_enable_fips: false +te_agent_service_state: started +te_agent_service_enabled: true +# only makes sense if te_agent_install_rtm = true +te_agent_service_rtm_state: started +te_agent_service_rtm_enabled: true + +# from vars/defaults.yml (should not be changed) +te_agent_package_name: te_agent +te_agent_service_name: twdaemon +te_agent_service_rtm_name: twrtmd + +# from vars/Windows.yml (should not be changed) +te_agent_package_name: '{CBE84CA6-F8E9-4D79-B8CE-CF936013DA82}' +te_agent_service_name: teagent +te_agent_service_rtm_name: tesvc +``` + +Example Playbook +---------------- + +```yaml +- hosts: servers + roles: + - role: te_agent + te_agent_package_source: /mnt/data/te_agent/linux/x86_64/te_agent.bin + te_agent_te_server_host: tw-testcon.example.com + te_agent_te_services_passphrase: correct horse battery staple + te_agent_package_version: 8.5.6 + te_agent_tags: + foo: bar + tags2: [taga, tagb] +``` + +License +------- + +Licensed under the Apache 2.0 license. See the LICENSE and NOTICE files for details. + +Author Information +------------------ + +Copyright 2017 Tripwire, Inc. + +https://www.tripwire.com/ diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..4df9312 --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,15 @@ +--- +te_agent_package_state: present +te_agent_package_install_path: '/usr/local/tripwire/te/agent' +te_agent_te_services_port: 9898 +te_agent_te_server_http_port: 8080 +te_agent_local_port: 9898 +te_agent_install_rtm: true +te_agent_proxy_port: 1080 +te_agent_rtm_port: 1169 +te_agent_enable_fips: false +te_agent_service_state: started +te_agent_service_enabled: true +# only makes sense if te_agent_install_rtm = true +te_agent_service_rtm_state: started +te_agent_service_rtm_enabled: true diff --git a/handlers/main.yml b/handlers/main.yml new file mode 100644 index 0000000..ad69779 --- /dev/null +++ b/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- include: service.yml + +- include: win_service.yml diff --git a/handlers/service.yml b/handlers/service.yml new file mode 100644 index 0000000..d8d2ca0 --- /dev/null +++ b/handlers/service.yml @@ -0,0 +1,12 @@ +--- + +- name: Restart agent service + service: + name: "{{ te_agent_service_name }}" + state: restarted + +- name: Restart event generator service + service: + name: "{{ te_agent_service_rtm_name }}" + state: restarted + when: te_agent_install_rtm diff --git a/handlers/win_service.yml b/handlers/win_service.yml new file mode 100644 index 0000000..fde591a --- /dev/null +++ b/handlers/win_service.yml @@ -0,0 +1,12 @@ +--- + +- name: Restart Windows agent service + win_service: + name: "{{ te_agent_service_name }}" + state: restarted + +- name: Restart Windows event generator service + win_service: + name: "{{ te_agent_service_rtm_name }}" + state: restarted + when: te_agent_install_rtm diff --git a/meta/main.yml b/meta/main.yml new file mode 100644 index 0000000..ce62f09 --- /dev/null +++ b/meta/main.yml @@ -0,0 +1,31 @@ +galaxy_info: + author: Bob Thomas + description: Role to install and configure the Tripwire Enterprise agent + company: Tripwire, Inc + + license: Apache 2.0 + + # this is mainly for Windows support. the Linux portion likely works on + # (untested) older versions + min_ansible_version: 2.3 + + # + # platforms is a list of platforms, and each platform has a name and a list of versions. + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: + - security + - monitoring + +dependencies: [] diff --git a/tasks/check_vars.yml b/tasks/check_vars.yml new file mode 100644 index 0000000..56d3883 --- /dev/null +++ b/tasks/check_vars.yml @@ -0,0 +1,13 @@ +--- + +- name: Check for te_agent_package_source + fail: msg='te_agent_package_source is not defined' + when: te_agent_package_source is not defined + +- name: Check for te_agent_te_server_host + fail: msg='te_agent_te_server_host is not defined' + when: te_agent_te_server_host is not defined + +- name: Check for te_agent_te_services_passphrase + fail: msg='te_agent_te_services_passphrase is not defined' + when: te_agent_te_services_passphrase is not defined diff --git a/tasks/config.yml b/tasks/config.yml new file mode 100644 index 0000000..40d38ea --- /dev/null +++ b/tasks/config.yml @@ -0,0 +1,66 @@ +--- + +- name: Write agent.tags.conf + template: + src: agent.tags.conf.j2 + dest: "{{ te_agent_package_install_path }}/data/config/agent.tags.conf" + when: te_agent_tags is defined + +- name: webserver.http.port + lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^webserver\.http\.port=' + line: 'webserver.http.port={{ te_agent_te_server_http_port }}' + notify: + - Restart agent service + +- name: tw.server.host + lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.server\.host=' + line: 'tw.server.host={{ te_agent_te_server_host }}' + notify: + - Restart agent service + +- name: tw.server.port + lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.server\.port=' + line: 'tw.server.port={{ te_agent_te_services_port }}' + notify: + - Restart agent service + +- name: tw.agent.generator.port + lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.agent\.generator\.port=' + line: 'tw.agent.generator.port={{ te_agent_rtm_port }}' + notify: + - Restart agent service + - Restart event generator service + +- name: tw.local.port + lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.local\.port=' + line: 'tw.local.port={{ te_agent_local_port }}' + notify: + - Restart agent service + +- name: tw.proxy.host + lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.proxy\.host=' + line: 'tw.proxy.host={{ te_agent_proxy_host }}' + when: te_agent_proxy_host is defined + notify: + - Restart agent service + +- name: tw.proxy.port + lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.proxy\.port=' + line: 'tw.proxy.port={{ te_agent_proxy_port }}' + when: te_agent_proxy_host is defined + notify: + - Restart agent service diff --git a/tasks/install.yml b/tasks/install.yml new file mode 100644 index 0000000..9aa84e5 --- /dev/null +++ b/tasks/install.yml @@ -0,0 +1,52 @@ +--- + +- name: Create staging path + tempfile: + state: directory + suffix: te_agent + register: staging + +- name: Stage te_agent.bin + copy: + src: "{{ te_agent_package_source }}" + dest: "{{ staging.path }}/te_agent.bin" + mode: 0700 + +- name: Run agent installer .bin + command: >- + {{ staging.path }}/te_agent.bin --silent --eula accept + --server-host "{{ te_agent_te_server_host }}" + --server-port "{{ te_agent_te_services_port }}" + --passphrase "{{ te_agent_te_services_passphrase }}" + --install-rtm "{{ te_agent_install_rtm }}" + --install-dir "{{ te_agent_package_install_path }}" + {% if te_agent_proxy_host|default('') %} + --proxy-host "{{ te_agent_proxy_host }}" + --proxy-port "{{ te_agent_proxy_port }}" + {% endif %} + {% if te_agent_install_rtm %} + --rtmport "{{ te_agent_rtm_port }}" + {% endif %} + {% if te_agent_enable_fips %} + --enable-fips + --http-port "{{ te_agent_te_server_http_port }}" + {% endif %} + args: + creates: "{{ te_agent_package_install_path }}/bin/twdaemon" + +- name: Cleanup staging path + file: + path: "{{ staging.path }}" + state: absent + +- name: Create Ansible custom facts directory + file: + path: /etc/ansible/facts.d + state: directory + recurse: yes + +- name: Write custom fact + template: + src: te_agent.fact.j2 + dest: /etc/ansible/facts.d/te_agent.fact + mode: 0700 diff --git a/tasks/main.yml b/tasks/main.yml new file mode 100644 index 0000000..7e28dd5 --- /dev/null +++ b/tasks/main.yml @@ -0,0 +1,72 @@ +--- + +- name: Gather OS Specific Variables + include_vars: "{{ item }}" + with_first_found: + - "{{ ansible_distribution }}-{{ ansible_distribution_version }}.yml" + - "{{ ansible_distribution }}.yml" + - "{{ ansible_os_family }}.yml" + - "defaults.yml" + tags: [always] + +# Awkward way to make a different OS default value while still allowing override +- name: Fix Windows default install path + set_fact: + te_agent_package_install_path: 'C:\Program Files\Tripwire\TE\Agent' + when: + - ansible_os_family == 'Windows' + - te_agent_package_install_path == '/usr/local/tripwire/te/agent' + tags: [always] + +- include: check_vars.yml + tags: [always] + +- include: win_check_version.yml + when: ansible_os_family == 'Windows' + tags: [always] + +- include: uninstall.yml + when: + - ansible_os_family != 'Windows' + - te_agent_package_state == 'absent' or + (te_agent_package_version is defined and ansible_local is defined and ansible_local.te_agent is defined and te_agent_package_version != ansible_local.te_agent.version) + tags: [package] + +- include: win_uninstall.yml + when: + - ansible_os_family == 'Windows' + - te_agent_package_state == 'absent' or + (te_agent_package_version is defined and te_agent_package_installed_version is defined and te_agent_package_version != te_agent_package_installed_version) + tags: [package] + +- include: install.yml + when: + - ansible_os_family != 'Windows' + - te_agent_package_state == 'present' + - ansible_local is not defined or ansible_local.te_agent is not defined or + (te_agent_package_version is defined and te_agent_package_version != ansible_local.te_agent.version) + tags: [package] + +- include: win_install.yml + when: + - ansible_os_family == 'Windows' + - te_agent_package_state == 'present' + - te_agent_package_installed_version is not defined or + (te_agent_package_version is defined and te_agent_package_version != te_agent_package_installed_version) + tags: [package] + +- include: config.yml + when: ansible_os_family != 'Windows' + tags: [configure] + +- include: win_config.yml + when: ansible_os_family == 'Windows' + tags: [configure] + +- include: service.yml + when: ansible_os_family != 'Windows' + tags: [service] + +- include: win_service.yml + when: ansible_os_family == 'Windows' + tags: [service] diff --git a/tasks/service.yml b/tasks/service.yml new file mode 100644 index 0000000..ad7fbe9 --- /dev/null +++ b/tasks/service.yml @@ -0,0 +1,19 @@ +--- + +- name: Agent service state + service: + name: "{{ te_agent_service_name }}" + state: "{{ te_agent_service_state }}" + +- name: Agent service enabled + service: + name: "{{ te_agent_service_name }}" + enabled: "{{ te_agent_service_enabled|ternary('yes', 'no') }}" + when: ansible_os_family != 'RedHat' + +- name: Event Generator service + service: + name: "{{ te_agent_service_rtm_name }}" + state: "{{ te_agent_service_rtm_state }}" + enabled: "{{ te_agent_service_rtm_enabled|ternary('yes', 'no') }}" + when: te_agent_install_rtm diff --git a/tasks/uninstall.yml b/tasks/uninstall.yml new file mode 100644 index 0000000..12aeb3b --- /dev/null +++ b/tasks/uninstall.yml @@ -0,0 +1,6 @@ +--- + +- name: Uninstall agent + command: "{{ te_agent_package_install_path }}/bin/uninstall.sh" + args: + removes: "{{ te_agent_package_install_path }}/bin/twdaemon" diff --git a/tasks/win_check_version.yml b/tasks/win_check_version.yml new file mode 100644 index 0000000..486f4c0 --- /dev/null +++ b/tasks/win_check_version.yml @@ -0,0 +1,12 @@ +--- + +- name: Get version from registry + win_reg_stat: + path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{{ te_agent_package_name }} + name: DisplayVersion + register: win_display_version + +- name: Set Windows installed version + set_fact: + te_agent_package_installed_version: "{{ win_display_version.value }}" + when: win_display_version.exists diff --git a/tasks/win_config.yml b/tasks/win_config.yml new file mode 100644 index 0000000..ca11744 --- /dev/null +++ b/tasks/win_config.yml @@ -0,0 +1,67 @@ +--- +# this is identical to config.yml, except s/module/win_module/ + +- name: (win) Write agent.tags.conf + win_template: + src: agent.tags.conf.j2 + dest: "{{ te_agent_package_install_path }}/data/config/agent.tags.conf" + when: te_agent_tags is defined + +- name: (win) webserver.http.port + win_lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^webserver\.http\.port=' + line: 'webserver.http.port={{ te_agent_te_server_http_port }}' + notify: + - Restart Windows agent service + +- name: (win) tw.server.host + win_lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.server\.host=' + line: 'tw.server.host={{ te_agent_te_server_host }}' + notify: + - Restart Windows agent service + +- name: (win) tw.server.port + win_lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.server\.port=' + line: 'tw.server.port={{ te_agent_te_services_port }}' + notify: + - Restart Windows agent service + +- name: (win) tw.agent.generator.port + win_lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.agent\.generator\.port=' + line: 'tw.agent.generator.port={{ te_agent_rtm_port }}' + notify: + - Restart Windows agent service + - Restart Windows event generator service + +- name: (win) tw.local.port + win_lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.local\.port=' + line: 'tw.local.port={{ te_agent_local_port }}' + notify: + - Restart Windows agent service + +- name: (win) tw.proxy.host + win_lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.proxy\.host=' + line: 'tw.proxy.host={{ te_agent_proxy_host }}' + when: te_agent_proxy_host is defined + notify: + - Restart Windows agent service + +- name: (win) tw.proxy.port + win_lineinfile: + path: "{{ te_agent_package_install_path }}/data/config/agent.properties" + regexp: '^tw\.proxy\.port=' + line: 'tw.proxy.port={{ te_agent_proxy_port }}' + when: te_agent_proxy_host is defined + notify: + - Restart Windows agent service diff --git a/tasks/win_install.yml b/tasks/win_install.yml new file mode 100644 index 0000000..7dad67d --- /dev/null +++ b/tasks/win_install.yml @@ -0,0 +1,43 @@ +--- + +- name: Create MSI staging path + win_tempfile: + state: directory + suffix: te_agent + register: staging + +- name: Stage te_agent.msi + win_copy: + src: "{{ te_agent_package_source }}" + dest: '{{ staging.path }}\te_agent.msi' + +- name: Install agent MSI package + win_package: + path: '{{ staging.path }}\te_agent.msi' + product_id: "{{ te_agent_package_name }}" + state: "{{ te_agent_package_state }}" + creates_path: '{{ te_agent_package_install_path }}\bin\twdaemon.cmd' + arguments: >- + ACCEPT_EULA=true + TE_SERVER_HOSTNAME="{{ te_agent_te_server_host }}" + TE_SERVER_PORT="{{ te_agent_te_services_port }}" + SERVICES_PASSWORD="{{ te_agent_te_services_passphrase }}" + INSTALL_RTM="{{ te_agent_install_rtm }}" + INSTALLDIR="{{ te_agent_package_install_path }}" + START_AGENT=false + {% if te_agent_proxy_host|default('') %} + TE_PROXY_HOSTNAME="{{ te_agent_proxy_host }}" + TE_PROXY_PORT="{{ te_agent_proxy_port }}" + {% endif %} + {% if te_agent_install_rtm %} + RTMPORT="{{ te_agent_rtm_port }}" + {% endif %} + {% if te_agent_enable_fips %} + INSTALL_FIPS=true + TE_SERVER_HTTP_PORT="{{ te_agent_te_server_http_port }}" + {% endif %} + +- name: Cleanup MSI staging path + win_file: + path: "{{ staging.path }}" + state: absent diff --git a/tasks/win_service.yml b/tasks/win_service.yml new file mode 100644 index 0000000..e215621 --- /dev/null +++ b/tasks/win_service.yml @@ -0,0 +1,14 @@ +--- + +- name: Agent Windows service + win_service: + name: "{{ te_agent_service_name }}" + state: "{{ te_agent_service_state }}" + start_mode: "{{ te_agent_service_enabled|ternary('auto', 'manual') }}" + +- name: Event Generator Windows service + win_service: + name: "{{ te_agent_service_rtm_name }}" + state: "{{ te_agent_service_rtm_state }}" + start_mode: "{{ te_agent_service_rtm_enabled|ternary('auto', 'manual') }}" + when: te_agent_install_rtm diff --git a/tasks/win_uninstall.yml b/tasks/win_uninstall.yml new file mode 100644 index 0000000..26de0b7 --- /dev/null +++ b/tasks/win_uninstall.yml @@ -0,0 +1,8 @@ +--- + +- name: Uninstall agent MSI package + win_package: + # fake path. not actually used, but required in ansible < 2.4 + path: 'c:\temp\te_agent.msi' + product_id: "{{ te_agent_package_name }}" + state: absent diff --git a/templates/agent.tags.conf.j2 b/templates/agent.tags.conf.j2 new file mode 100644 index 0000000..34a5663 --- /dev/null +++ b/templates/agent.tags.conf.j2 @@ -0,0 +1,9 @@ +{% for k,v in te_agent_tags.items() %} +{% if v is string %} +{{ k }}:{{ v }} +{% else %} +{% for l in v %} +{{ k }}:{{ l }} +{% endfor %} +{% endif %} +{% endfor %} diff --git a/templates/te_agent.fact.j2 b/templates/te_agent.fact.j2 new file mode 100644 index 0000000..8f452a3 --- /dev/null +++ b/templates/te_agent.fact.j2 @@ -0,0 +1,10 @@ +#!/bin/env python + +import json + +with open('{{ te_agent_package_install_path }}/data/version') as f: + version = f.read() + +print json.dumps({ + 'version': '.'.join(version.split('=')[1].split('.')[:3]) +}) diff --git a/tests/inventory b/tests/inventory new file mode 100644 index 0000000..878877b --- /dev/null +++ b/tests/inventory @@ -0,0 +1,2 @@ +localhost + diff --git a/tests/test.yml b/tests/test.yml new file mode 100644 index 0000000..3ca6519 --- /dev/null +++ b/tests/test.yml @@ -0,0 +1,12 @@ +--- +- hosts: localhost + remote_user: root + roles: + - role: te_agent + te_agent_package_source: /mnt/data/te_agent/linux/x86_64/te_agent.bin + te_agent_te_server_host: tw-testcon.example.com + te_agent_te_services_passphrase: correct horse battery staple + te_agent_package_version: 8.5.6 + te_agent_tags: + foo: bar + tags2: [taga, tagb] diff --git a/vars/Windows.yml b/vars/Windows.yml new file mode 100644 index 0000000..fb2f512 --- /dev/null +++ b/vars/Windows.yml @@ -0,0 +1,4 @@ +--- +te_agent_package_name: '{CBE84CA6-F8E9-4D79-B8CE-CF936013DA82}' +te_agent_service_name: teagent +te_agent_service_rtm_name: tesvc diff --git a/vars/defaults.yml b/vars/defaults.yml new file mode 100644 index 0000000..1e99d47 --- /dev/null +++ b/vars/defaults.yml @@ -0,0 +1,4 @@ +--- +te_agent_package_name: te_agent +te_agent_service_name: twdaemon +te_agent_service_rtm_name: twrtmd