Installing foreman proxy via puppet

Using puppet 7 and foreman 3.7. The aim is to create foreman smart proxies, managed by puppet. Initially I am only planning to use these for TFTP (for pxeboot), pointed to by the DHCP already set up on our routers, but perhaps I will later enable more smart proxy features.

Right now, though, I tried the simple approach of adding to my Puppetfile:

mod 'theforeman-foreman_proxy', '25.1.0'

And updating the role applicable to my new foreman proxies like so:

class role::foreman_proxy {
  include profile::base
  class { '::foreman_proxy':
    tftp     => true,
    # Disable everything else
    puppet   => false,
    puppetca => false,
    dhcp     => false,
    dns      => false,
    bmc      => false,
    realm    => false,
  }
}

However, this gives errors:

Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: Unknown function: 'extlib::random_password'. (file: /etc/puppetlabs/code/environments/production/modules/foreman_proxy/manifests/params.pp, line: 175, column: 91) on node myforemanproxy.example.com

I’m using r10k to manage environments, and to manage puppetfile modules.

I found a “.fixtures” file in the foreman proxy repo: https://github.com/theforeman/puppet-foreman_proxy/blob/master/.fixtures.yml which mentions extlib among other things, apparently modules? I’m not familiar with .fixtures; is this similar to a puppetfile in function?

How can I get my installation to work?

(And side question, is the double colon before foreman_proxy necessary? Other examples in the documentation omit it (GitHub - theforeman/puppet-foreman_proxy: Puppet module for Foreman Smart Proxy) so I wasn’t sure.)

I figured out I need to list out all dependencies, recursively, in the Puppetfile. I added them one at a time based on errors I got.

Finally I got down to where the catalog would compile, but would run with failures. I found I needed to add the apt sources so I wrote:

  exec { "get-foreman-apt-key":
    command => "/usr/bin/wget https://deb.theforeman.org/foreman.asc -O /etc/apt/trusted.gpg.d/foreman.asc",
    creates => "/etc/apt/trusted.gpg.d/foreman.asc",
    before  => Exec['apt-get-update'],
  }

  file { "/etc/apt/sources.list.d/foreman.list":
    source => "puppet:///modules/profile/foreman_proxy/foreman.list",
    notify => Exec['apt-get-update'],
  }

(The apt-get update command is elsewhere, with a refreshonly attribute.)

This allows foreman-proxy package installation, but still failing to install puppet-agent-oauth.

Got it; I was missing the deb http://deb.theforeman.org/ plugins 3.7 line in my foreman.list file.

Now I am getting:

Error: /Stage[main]/Foreman_proxy::Register/Foreman_host[foreman-proxy-myforemanproxy.example.com]: Could not evaluate: Exception Failed to open TCP connection to myforemanproxy.example.com:443 (Connection refused - connect(2) for "myforemanproxy.example.com" port 443) in get request to: https://myforemanproxy.example.com/api/v2/hosts?search=name%3D%22myforemanproxy.example.com%22
Wrapped exception:
Failed to open TCP connection to myforemanproxy.example.com:443 (Connection refused - connect(2) for "myforemanproxy.example.com" port 443)
Error: /Stage[main]/Foreman_proxy::Register/Foreman_smartproxy[myforemanproxy.example.com]: Could not evaluate: Exception Failed to open TCP connection to myforemanproxy.example.com:443 (Connection refused - connect(2) for "myforemanproxy.example.com" port 443) in get request to: https://myforemanproxy.example.com/api/v2/smart_proxies?search=name%3D%22myforemanproxy.example.com%22
Wrapped exception:
Failed to open TCP connection to myforemanproxy.example.com:443 (Connection refused - connect(2) for "myforemanproxy.example.com" port 443)

I’m documenting my journey here because there is really a lack of documentation on how to install foreman proxy through puppet. I found Installing via foreman-installer vs. installing via theforeman/foreman Puppet module? which indicates this is a supported path (from the author of the installer), but it isn’t clearly documented or debugged for clear step-by-step approach, so hopefully this thread will improve that situation even if I don’t get replies from anyone else.

There are parameters that look possibly relevant:

# $puppet_url::                 URL of the Puppet master itself for API requests
# $foreman_base_url::           Base Foreman URL used for REST interaction

But, I can’t tell if these are the right ones to set or not. The puppet_url parameter MIGHT be only relevant if the “puppet” parameter is set to “true.” Or, it might be used by the foreman proxy class for other purposes as well.

My main foreman installation and puppetserver shall be called “puppet7.example.com” for purposes of this forum. I’m trying to install a smartproxy, but I need it to correctly register with the main foreman instance.

How to do this? Any help, please?

Setting foreman_base_url to https://puppet7.example.com in my instantiation of the ::foreman_proxy class seems to do something; now I get the error:

Error: /Stage[main]/Foreman_proxy::Register/Foreman_host[foreman-proxy-myforemanproxy.example.com]: Could not evaluate: Error making GET request to Foreman at https://puppet7.example.com/api/v2/hosts: Response: 401 Unauthorized: Often this is caused by invalid Oauth credentials sent to Foreman at puppet7.example.com

I wonder if there is a change needed on the main foreman server to allow this host to be registered?

Or maybe I should just give up on the idea of automated creation of a foreman proxy, and instead just manually go through the foreman UI for every new proxy?

Some advice or input would be very welcome. (Or documentation improvements.)

This is probably not the “right” way but I found the oauth_consumer_key and oauth_consumer_secret on my foreman server in /opt/puppetlabs/puppet/cache/foreman_cache_data/. By defining those as oauth_consumer_key and oauth_consumer_secret parameters to the foreman_proxy class resource, I was able to get past that particular error message to another error message:

Error: Error making POST request to Foreman at https://puppet7.example.com/api/v2/smart_proxies: Unable to communicate with the proxy: ERF12-2530 [ProxyAPI::ProxyException]: Unable to detect features ([RestClient::Forbidden]: 403 Forbidden) for proxy https://myforemanproxy.example.com:8443/v2/features Please check the proxy is configured and running on the host.

Error: /Stage[main]/Foreman_proxy::Register/Foreman_smartproxy[myforemanproxy.example.com]/ensure: change from 'absent' to 'present' failed: Error making POST request to Foreman at https://puppet7.example.com/api/v2/smart_proxies: Unable to communicate with the proxy: ERF12-2530 [ProxyAPI::ProxyException]: Unable to detect features ([RestClient::Forbidden]: 403 Forbidden) for proxy https://myforemanproxy.example.com:8443/v2/features Please check the proxy is configured and running on the host.

systemctl status foreman-proxy shows that it’s running. But nothing is listening on port 443 on the proxy.

I figured that out as well; the missing point was having the “trusted_hosts” parameter defined to include the foreman server.

The final code is:

  exec { 'apt-get-update':
    command     => '/usr/bin/apt-get update',
    refreshonly => true,
  }

  exec { "get-foreman-apt-key":
    command => "/usr/bin/wget https://deb.theforeman.org/foreman.asc -O /etc/apt/trusted.gpg.d/foreman.asc",
    creates => "/etc/apt/trusted.gpg.d/foreman.asc",
    before  => Exec['apt-get-update'],
  }

  file { "/etc/apt/sources.list.d/foreman.list":
    source => "puppet:///modules/profile/foreman_proxy/foreman.list",
    notify => Exec['apt-get-update'],
  }

  class { '::foreman_proxy':
    tftp     => true,
    foreman_base_url => "https://puppet7.example.com",
    oauth_consumer_key => "[redacted]",
    oauth_consumer_secret => "[redacted]",
    trusted_hosts => [
      "myforemanproxy.example.com",
      "puppet7.example.com",
    ],
    # Disable everything else
    puppet   => false,
    puppetca => false,
    dhcp     => false,
    dns      => false,
    bmc      => false,
    realm    => false,
  }

And the foreman.list file in site/profile/files/foreman_proxy/foreman.list is:

# Debian Bullseye
deb http://deb.theforeman.org/ bullseye 3.7
# Foreman plugins
deb http://deb.theforeman.org/ plugins 3.7

This runs with all green, i.e. it’s not still failing at some point.

However, still not satisfied with it because:

  1. I don’t like having secrets in a puppet manifest and it doesn’t seem it should be necessary.
  2. The new smart proxy doesn’t show up in the foreman UI after all of this. I think it has to be added manually. EDIT: Correction; it does show up. My location filter was set wrong in the Foreman UI. The location wasn’t set for the new smart proxy, which is fine.

I will also mention that the docs in Installing an External Smart Proxy Server on Debian are actually more useful for smartproxy installation than Foreman :: Manual although I had only found the latter until almost done with the process.

Instead of all the custom apt repository code, looks like you could just do

class { '::foreman::repo':
  repo => '3.7',
  before => Class['foreman_proxy::install']
}

Or even better

#hiera
foreman::repo::repo: '3.7'

#profile
include ::foreman::repo
Class['foreman::repo']
-> Class['foreman_proxy::install]
1 Like