diff --git a/README.md b/README.md index 4878c177..257a7d4a 100644 --- a/README.md +++ b/README.md @@ -47,9 +47,9 @@ To deploy the Datadog Agent on hosts, add the Datadog role and your API key to y | `datadog_disable_default_checks` | Set to `true` to remove all default checks. | | `datadog_config` | Settings for the main Agent configuration file:
- `/etc/datadog-agent/datadog.yaml` for Agent v6 and v7,
- `/etc/dd-agent/datadog.conf` for Agent v5 (under the `[Main]` section). | | `datadog_config_ex` | (Optional) Extra INI sections to go in `/etc/dd-agent/datadog.conf` (Agent v5 only). | -| `datadog_apt_repo` | Override the default Datadog `apt` repository. | +| `datadog_apt_repo` | Override the default Datadog `apt` repository. Make sure to use the `signed-by` option if repository metadata is signed using Datadog's signing keys: `deb [signed-by=/usr/share/keyrings/datadog-archive-keyring.gpg] https://yourrepo`. | | `datadog_apt_cache_valid_time` | Override the default apt cache expiration time (defaults to 1 hour). | -| `datadog_apt_key_url_new` | Override the default URL to Datadog `apt` key (key ID `382E94DE`; the deprecated `datadog_apt_key_url` variable refers to an expired key that's been removed from the role). | +| `datadog_apt_key_url_new` | Override the location from which to obtain Datadog `apt` key (the deprecated `datadog_apt_key_url` variable refers to an expired key that's been removed from the role). The URL is expected to be a GPG keyring containing keys `382E94DE` and `F14F620E`. | | `datadog_yum_repo` | Override the default Datadog `yum` repository. | | `datadog_yum_repo_gpgcheck` | Override the default `repo_gpgcheck` value (`yes`) - use `no` to turn off repodata GPG signature verification. Note that repodata signature verification is always turned off for Agent 5. | | `datadog_yum_gpgcheck` | Override the default `gpgcheck` value (`yes`) - use `no` to turn off package GPG signature verification. | @@ -64,7 +64,6 @@ To deploy the Datadog Agent on hosts, add the Datadog role and your API key to y | `datadog_zypper_gpgkey_e09422b3` | Override the default URL to the Datadog `zypper` key used to verify Agent v6.14+ packages (key ID `E09422B3`). | | `datadog_zypper_gpgkey_e09422b3_sha256sum` | Override the default checksum of the `datadog_zypper_gpgkey_e09422b3` key. | | `datadog_agent_allow_downgrade` | Set to `yes` to allow Agent downgrades on apt-based platforms (use with caution, see `defaults/main.yml` for details). **Note**: On Centos this only works with Ansible 2.4+. | -| `use_apt_backup_keyserver` | Set to `true` to use the backup keyserver instead of the default one. | | `datadog_enabled` | Set to `false` to prevent `datadog-agent` service from starting (defaults to `true`). | | `datadog_additional_groups` | Either a list, or a string containing a comma-separated list of additional groups for the `datadog_user` (Linux only). | | `datadog_windows_ddagentuser_name` | The name of Windows user to create/use, in the format `\` (Windows only). | @@ -262,6 +261,8 @@ If you previously used the Agent v5 variables, use the **new** variables below w | `datadog_agent5_yum_repo` | `datadog_yum_repo` | | `datadog_agent5_zypper_repo` | `datadog_zypper_repo` | +Since version 4.9.0, the `use_apt_backup_keyserver` variable has been removed, as APT keys are now obtained from https://keys.datadoghq.com. + #### Windows When the variable `datadog_windows_download_url` is not set, the official Windows MSI package corresponding to the `datadog_agent_major_version` is used: @@ -487,6 +488,8 @@ Alternatively, if your playbook **only runs on Windows hosts**, use the followin ### Debian stretch +**Note:** this information applies to versions of the role prior to 4.9.0. Since 4.9.0, the `apt_key` module is no longer used by the role. + On Debian Stretch, the `apt_key` module used by the role requires an additional system dependency to work correctly. The dependency (`dirmngr`) is not provided by the module. Add the following configuration to your playbooks to make use of the present role: ```yml @@ -498,7 +501,6 @@ On Debian Stretch, the `apt_key` module used by the role requires an additional apt: name: dirmngr state: present - roles: - { role: datadog.datadog, become: yes } vars: diff --git a/defaults/main.yml b/defaults/main.yml index 3c65a9de..8c51082f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -59,12 +59,8 @@ datadog_agent_flavor: "datadog-agent" # Use the datadog_apt_repo variable to override the repository used. datadog_apt_repo: "" - datadog_apt_cache_valid_time: 3600 datadog_apt_key_retries: 5 -use_apt_backup_keyserver: false -datadog_apt_keyserver: hkp://keyserver.ubuntu.com:80 -datadog_apt_backup_keyserver: hkp://pool.sks-keyservers.net:80 # Default yum repo and keys @@ -157,10 +153,23 @@ win_install_args: " " # The following variables are for internal use only, do not modify them. # +datadog_apt_trusted_d_keyring: "/etc/apt/trusted.gpg.d/datadog-archive-keyring.gpg" +datadog_apt_usr_share_keyring: "/usr/share/keyrings/datadog-archive-keyring.gpg" +datadog_apt_key_current_name: "DATADOG_APT_KEY_CURRENT" +# NOTE: we don't use URLs starting with https://keys.datadoghq.com/, as Python +# on older Debian/Ubuntu doesn't support SNI and get_url would fail on them +datadog_apt_default_keys: + - key: "{{ datadog_apt_key_current_name }}" + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_CURRENT.public + - key: A2923DFF56EDA6E76E55E492D3A80E30382E94DE + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_382E94DE.public + - key: D75CEA17048B9ACBF186794B32637D44F14F620E + value: https://s3.amazonaws.com/public-signing-keys/DATADOG_APT_KEY_F14F620E.public + # The default apt repository for each major Agent version is specified in the following variables. -datadog_agent5_apt_repo: "deb https://apt.datadoghq.com/ stable main" -datadog_agent6_apt_repo: "deb https://apt.datadoghq.com/ stable 6" -datadog_agent7_apt_repo: "deb https://apt.datadoghq.com/ stable 7" +datadog_agent5_apt_repo: "deb [signed-by={{ datadog_apt_usr_share_keyring }}] https://apt.datadoghq.com/ stable main" +datadog_agent6_apt_repo: "deb [signed-by={{ datadog_apt_usr_share_keyring }}] https://apt.datadoghq.com/ stable 6" +datadog_agent7_apt_repo: "deb [signed-by={{ datadog_apt_usr_share_keyring }}] https://apt.datadoghq.com/ stable 7" # The default yum repository for each major Agent version is specified in the following variables. datadog_agent5_yum_repo: "https://yum.datadoghq.com/rpm/{{ ansible_facts.architecture }}" diff --git a/tasks/_apt-key-import.yml b/tasks/_apt-key-import.yml new file mode 100644 index 00000000..7b3afe6d --- /dev/null +++ b/tasks/_apt-key-import.yml @@ -0,0 +1,83 @@ +# We allow users to specify a file from which to import keys, so we expect +# that to be a binary keyring; at the same time, we have ascii armored +# individual keys at keys.datadoghq.com that we import. The below procedure +# can be called for a URL pointing to a keyring or an ascii armored file +# and extract and import a specific key from it (we specialcase the +# DATADOG_APT_KEY_CURRENT value, which we always expect to be ascii +# armored individual key). + +# NOTE: we use 'noqa risky-shell-pipe' throughout this file, because Debian's +# default shell is /bin/sh which doesn't have a pipefail option and the +# presence of a different shell isn't guaranteed. + +# NOTE: in order to display Ansible's `changed: [hostname]` properly throughout +# tasks in this file, we added `changed_when: false` to a lot of them, even if +# they actually run every time (e.g. importing the CURRENT key). The reason is +# that they operate inside a temporary directory and they don't have a +# permanent effect on the host (nothing will actually change on the host +# whether these tasks run or not) except the last one - the actual import of +# the key to `datadog_apt_usr_share_keyring`. + +- name: "Set local variables for processed key {{ item.key }}" + set_fact: + key_fingerprint: "{{ item.key }}" + keyring_url: "{{ item.value }}" + +- name: "Find out whether key {{ key_fingerprint }} is already imported" + shell: "gpg --no-default-keyring --keyring {{ datadog_apt_usr_share_keyring }} --list-keys --with-fingerprint --with-colons | grep {{ key_fingerprint }}" # noqa risky-shell-pipe + register: key_exists_result + failed_when: false # we expect the command to fail when the key is not found; we never want this task to fail + changed_when: key_exists_result.rc != 0 + when: key_fingerprint != datadog_apt_key_current_name # we always want to import the CURRENT key + +- name: "Set local helper variable for determining key import (when not {{ datadog_apt_key_current_name }})" + set_fact: + key_needs_import: "{{ 'false' if key_exists_result.rc == 0 else 'true' }}" + when: key_fingerprint != datadog_apt_key_current_name + +- name: "Set local helper variable for determining key import (when {{ datadog_apt_key_current_name }})" + set_fact: + key_needs_import: "true" + when: key_fingerprint == datadog_apt_key_current_name + +- name: "Create temporary directory for key manipulation" + tempfile: + state: directory + suffix: keys + register: tempdir + when: key_needs_import + changed_when: false + +- name: "Download {{ keyring_url }} to import key {{ key_fingerprint }}" + get_url: + url: "{{ keyring_url }}" + dest: "{{ tempdir.path }}/{{ key_fingerprint }}" + force: yes + when: key_needs_import + changed_when: false + +# gpg --dearmor called on a binary keyring does nothing +- name: "Ensure downloaded file for {{ key_fingerprint }} is a binary keyring" + shell: "cat {{ tempdir.path }}/{{ key_fingerprint }} | gpg --dearmor > {{ tempdir.path }}/binary.gpg" # noqa risky-shell-pipe + when: key_needs_import + changed_when: false + +- name: "Extract the required key from the binary keyring (when not {{ datadog_apt_key_current_name }})" + shell: "gpg --no-default-keyring --keyring {{ tempdir.path }}/binary.gpg --export {{ key_fingerprint }} > {{ tempdir.path }}/single.gpg" + when: key_fingerprint != datadog_apt_key_current_name and key_needs_import + changed_when: false + +- name: "Extract the required key from the binary keyring (when {{ datadog_apt_key_current_name }})" + copy: + src: "{{ tempdir.path }}/binary.gpg" + dest: "{{ tempdir.path }}/single.gpg" + mode: "0600" + remote_src: yes + when: key_fingerprint == datadog_apt_key_current_name and key_needs_import + changed_when: false + +- name: "Import key {{ key_fingerprint }} to {{ datadog_apt_usr_share_keyring }} keyring" + shell: "cat {{ tempdir.path }}/single.gpg | gpg --no-default-keyring --keyring {{ datadog_apt_usr_share_keyring }} --import --batch" # noqa risky-shell-pipe + when: key_needs_import + register: key_import_result + changed_when: '"imported: 1" in key_import_result.stderr' diff --git a/tasks/pkg-debian.yml b/tasks/pkg-debian.yml index 7f7c6c98..5367ddcd 100644 --- a/tasks/pkg-debian.yml +++ b/tasks/pkg-debian.yml @@ -6,43 +6,44 @@ state: present when: not ansible_check_mode -- name: Install apt-key from keyserver (Expires 2022) - apt_key: - id: A2923DFF56EDA6E76E55E492D3A80E30382E94DE - keyserver: "{{ datadog_apt_backup_keyserver if use_apt_backup_keyserver else datadog_apt_keyserver }}" - state: present - # keyserver.ubuntu.com is a pool of server, we should retry if one of them is down - register: result - until: not result.failed is defined or not result.failed - retries: "{{ datadog_apt_key_retries }}" - when: datadog_apt_key_url_new is not defined +- name: "Check if {{ datadog_apt_usr_share_keyring }} exists with correct mode" + stat: + path: "{{ datadog_apt_usr_share_keyring }}" + register: apt_keyring_file -- name: Install Datadog apt-key from url (Expires 2022) - apt_key: - id: A2923DFF56EDA6E76E55E492D3A80E30382E94DE - url: "{{ datadog_apt_key_url_new }}" - state: present - when: datadog_apt_key_url_new is defined +- name: "Ensure {{ datadog_apt_usr_share_keyring }} exists" + file: + path: "{{ datadog_apt_usr_share_keyring }}" + owner: root + group: root + mode: "0644" + state: touch + when: not ansible_check_mode and (not apt_keyring_file.stat.exists or not apt_keyring_file.stat.mode == "0644") -- name: Install apt-key from keyserver (Expires 2032) - apt_key: - id: D75CEA17048B9ACBF186794B32637D44F14F620E - keyserver: "{{ datadog_apt_backup_keyserver if use_apt_backup_keyserver else datadog_apt_keyserver }}" - state: present - # keyserver.ubuntu.com is a pool of server, we should retry if one of them is down - register: result_2032 - until: not result_2032.failed is defined or not result_2032.failed - retries: "{{ datadog_apt_key_retries }}" - when: datadog_apt_key_url_new is not defined +- name: Install apt keys from default URLs + include_tasks: _apt-key-import.yml + with_items: + "{{ datadog_apt_default_keys }}" + when: datadog_apt_key_url_new is not defined and not ansible_check_mode -- name: Install Datadog apt-key from url (Expires 2032) - apt_key: - id: D75CEA17048B9ACBF186794B32637D44F14F620E - url: "{{ datadog_apt_key_url_new }}" - state: present - when: datadog_apt_key_url_new is defined +- name: Install apt keys from custom URL + include_tasks: _apt-key-import.yml + with_items: + - key: A2923DFF56EDA6E76E55E492D3A80E30382E94DE + value: "{{ datadog_apt_key_url_new }}" + - key: D75CEA17048B9ACBF186794B32637D44F14F620E + value: "{{ datadog_apt_key_url_new }}" + when: datadog_apt_key_url_new is defined and not ansible_check_mode + +- name: "Ensure {{ datadog_apt_trusted_d_keyring }} exists with same contents as {{ datadog_apt_usr_share_keyring }} for older distro versions" + copy: + src: "{{ datadog_apt_usr_share_keyring }}" + dest: "{{ datadog_apt_trusted_d_keyring }}" + mode: "0644" + remote_src: yes + when: ((ansible_distribution == 'Debian' and ansible_lsb.major_release|int < 9) or (ansible_distribution == 'Ubuntu' and ansible_lsb.major_release|int < 16)) and not ansible_check_mode -- name: Ensure Datadog non-https repositories are deprecated +- name: Ensure Datadog non-https repositories and repositories not using signed-by option are deprecated apt_repository: repo: "{{ item }}" state: "absent" @@ -51,6 +52,9 @@ - "deb http://apt.datadoghq.com/ stable main" - "deb http://apt.datadoghq.com/ stable 6" - "deb http://apt.datadoghq.com/ stable 7" + - "deb https://apt.datadoghq.com/ stable main" + - "deb https://apt.datadoghq.com/ stable 6" + - "deb https://apt.datadoghq.com/ stable 7" when: not ansible_check_mode - name: Ensure Datadog repository is up-to-date