From d4e1a346103ed0eb5d60e311da79f2ed315b716b Mon Sep 17 00:00:00 2001 From: Andreas Ntaflos Date: Mon, 30 Apr 2018 18:05:30 +0200 Subject: [PATCH] Support managing login configurations in /etc/apt/auth.conf APT 1.5 formally introduced support for specifying login configuration settings (like username and password) for APT sources or proxies that require authentication in the file `/etc/apt/auth.conf`. This file follows a netrc-like format (like ftp or curl) and has restrictive permissions. This is preferable to embedding login information directly in sources.list entries (which are usually world-readable). See https://manpages.debian.org/testing/apt/apt_auth.conf.5.en.html for details. This change adds a new, optional class parameter `apt::auth_conf_entries` which expects an array of hashes (defined by a new abstract data type `Apt::Auth_conf_entry`) that represent sets of login configuration settings to record in `/etc/apt/auth.conf`. The file's contents are rendered using a simple EPP template. Contains updated spec tests and documentation. --- README.md | 36 +++++++++++++++++++++++++++++- manifests/init.pp | 18 +++++++++++++++ manifests/params.pp | 1 + spec/classes/apt_spec.rb | 48 ++++++++++++++++++++++++++++++++++++++++ templates/auth_conf.epp | 5 +++++ types/auth_conf_entry.pp | 1 + 6 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 templates/auth_conf.epp create mode 100644 types/auth_conf_entry.pp diff --git a/README.md b/README.md index 73272c2..9ece72b 100644 --- a/README.md +++ b/README.md @@ -226,6 +226,38 @@ apt::source { "archive.ubuntu.com-${lsbdistcodename}-backports": } ``` +### Manage login configuration settings for an APT source or proxy in `/etc/apt/auth.conf` + +Starting with APT version 1.5 you can define login configuration settings (like +username and password) for APT sources or proxies that require authentication +in the file `/etc/apt/auth.conf`. This is preferable to embedding login +information directly in `source.list` entries which are usually world-readable. + +The file `/etc/apt/auth.conf` follows the format of netrc (as used by ftp or +curl) and has restrictive file permissions. See +https://manpages.debian.org/testing/apt/apt_auth.conf.5.en.html for details. + +Use the optional `apt::auth_conf_entries` parameter to specify an array of +hashes containing login configuration settings. These hashes may only contain +the keys `machine`, `login` and `password`. + +```puppet +class { 'apt': + auth_conf_entries => [ + { + 'machine' => 'apt-proxy.example.net', + 'login' => 'proxylogin', + 'password' => 'proxypassword', + }, + { + 'machine' => 'apt.example.com/ubuntu', + 'login' => 'reader', + 'password' => 'supersecret', + }, + ], +} +``` + ## Reference ### Classes @@ -298,7 +330,7 @@ All parameters are optional unless specified. * `https`: Specifies whether to enable https proxies. Valid options: `true` and `false`. Default: `false`. * `ensure`: Optional parameter. Valid options: 'file', 'present', and 'absent'. Default: `undef`. Prefer 'file' over 'present'. - + * `direct`: Specifies whether or not to use a 'DIRECT' https proxy if http proxy is used but https is not. Valid options: `true` and `false`. Default: `false`. * `purge`: Specifies whether to purge any existing settings that aren't managed by Puppet. Valid options: a hash made up from the following keys: @@ -313,6 +345,8 @@ All parameters are optional unless specified. * `settings`: Creates new `apt::setting` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}. +* `auth_conf_entries`: An optional array of login configuration settings (hashes) that will be recorded in the file `/etc/apt/auth.conf`. This file has a netrc-like format (similar to what curl uses) and contains the login configuration for APT sources and proxies that require authentication. See https://manpages.debian.org/testing/apt/apt_auth.conf.5.en.html for details. If specified each hash must contain the keys `machine`, `login` and `password` and no others. Default: []. + * `sources`: Creates new `apt::source` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}. * `pins`: Creates new `apt::pin` resources. Valid options: a hash to be passed to the [`create_resources` function](https://docs.puppetlabs.com/references/latest/function.html#createresources). Default: {}. diff --git a/manifests/init.pp b/manifests/init.pp index aa61986..6b69ecc 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -21,6 +21,8 @@ class apt ( Hash $ppas = $apt::params::ppas, Hash $pins = $apt::params::pins, Hash $settings = $apt::params::settings, + Array[Apt::Auth_conf_entry] + $auth_conf_entries = $apt::params::auth_conf_entries, String $root = $apt::params::root, String $sources_list = $apt::params::sources_list, String $sources_list_d = $apt::params::sources_list_d, @@ -178,6 +180,22 @@ class apt ( create_resources('apt::setting', $settings) } + $auth_conf_ensure = $auth_conf_entries ? { + [] => 'absent', + default => 'present', + } + + $auth_conf_tmp = epp('apt/auth_conf.epp') + + file { '/etc/apt/auth.conf': + ensure => $auth_conf_ensure, + owner => 'root', + group => 'root', + mode => '0600', + content => "${confheadertmp}${auth_conf_tmp}", + notify => Class['apt::update'], + } + # manage pins if present if $pins { create_resources('apt::pin', $pins) diff --git a/manifests/params.pp b/manifests/params.pp index c11deba..901340b 100644 --- a/manifests/params.pp +++ b/manifests/params.pp @@ -22,6 +22,7 @@ class apt::params { $ppas = {} $pins = {} $settings = {} + $auth_conf_entries = [] $config_files = { 'conf' => { diff --git a/spec/classes/apt_spec.rb b/spec/classes/apt_spec.rb index 0c6333b..654af4e 100644 --- a/spec/classes/apt_spec.rb +++ b/spec/classes/apt_spec.rb @@ -60,6 +60,8 @@ describe 'apt' do is_expected.to contain_file('preferences.d').that_notifies('Class[Apt::Update]').only_with(preferences_d) } + it { is_expected.to contain_file('/etc/apt/auth.conf').with_ensure('absent') } + it 'lays down /etc/apt/apt.conf.d/15update-stamp' do is_expected.to contain_file('/etc/apt/apt.conf.d/15update-stamp').with(group: 'root', mode: '0644', @@ -186,6 +188,52 @@ describe 'apt' do } end + context 'with entries for /etc/apt/auth.conf' do + let(:params) do + { + auth_conf_entries: [ + { machine: 'deb.example.net', + login: 'foologin', + password: 'secret' }, + { machine: 'apt.example.com', + login: 'aptlogin', + password: 'supersecret' }, + ], + } + end + + auth_conf_content = "// This file is managed by Puppet. DO NOT EDIT. +machine deb.example.net login foologin password secret +machine apt.example.com login aptlogin password supersecret +" + + it { + is_expected.to contain_file('/etc/apt/auth.conf').with(ensure: 'present', + owner: 'root', + group: 'root', + mode: '0600', + notify: 'Class[Apt::Update]', + content: auth_conf_content) + } + end + + context 'with improperly specified entries for /etc/apt/auth.conf' do + let(:params) do + { + auth_conf_entries: [ + { machinn: 'deb.example.net', + username: 'foologin', + password: 'secret' }, + { machine: 'apt.example.com', + login: 'aptlogin', + password: 'supersecret' }, + ], + } + end + + it { is_expected.to raise_error(Puppet::Error) } + end + context 'with sources defined on valid osfamily' do let :facts do { os: { family: 'Debian', name: 'Ubuntu', release: { major: '12', full: '12.04' } }, diff --git a/templates/auth_conf.epp b/templates/auth_conf.epp new file mode 100644 index 0000000..5b3000f --- /dev/null +++ b/templates/auth_conf.epp @@ -0,0 +1,5 @@ +<% if $apt::auth_conf_entries != [] { -%> +<% $apt::auth_conf_entries.each | $auth_conf_entry | { -%> +machine <%= $auth_conf_entry['machine'] %> login <%= $auth_conf_entry['login'] %> password <%= $auth_conf_entry['password'] %> +<% } -%> +<% } -%> diff --git a/types/auth_conf_entry.pp b/types/auth_conf_entry.pp new file mode 100644 index 0000000..40648d1 --- /dev/null +++ b/types/auth_conf_entry.pp @@ -0,0 +1 @@ +type Apt::Auth_conf_entry = Struct[{ machine => String[1], login => String, password => String }] -- 2.32.3