Skip to content

Commit

Permalink
Fixes #27932 - Add REX Cockpit support (theforeman#760)
Browse files Browse the repository at this point in the history
  • Loading branch information
ekohl authored Oct 24, 2019
1 parent 3920bde commit 226e751
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 0 deletions.
53 changes: 53 additions & 0 deletions manifests/plugin/remote_execution/cockpit.pp
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Installs remote execution cockpit plugin
class foreman::plugin::remote_execution::cockpit {
require foreman::plugin::remote_execution

$config_directory = '/etc/foreman/cockpit'
$foreman_url = $foreman::foreman_url
$cockpit_path = '/webcon'
$cockpit_host = '127.0.0.1'
$cockpit_port = 9999
$cockpit_config = {
'foreman_url' => $foreman_url,
'ssl_ca_file' => $foreman::server_ssl_chain,
'ssl_certificate' => $foreman::client_ssl_cert,
'ssl_private_key' => $foreman::client_ssl_key,
}

foreman::plugin { 'remote_execution-cockpit': }
-> service { 'foreman-cockpit':
ensure => running,
enable => true,
}

file { "${config_directory}/cockpit.conf":
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => template('foreman/remote_execution_cockpit.conf.erb'),
require => Foreman::Plugin['remote_execution-cockpit'],
notify => Service['foreman-cockpit'],
}

file { "${config_directory}/foreman-cockpit-session.yml":
ensure => file,
owner => 'root',
group => 'root',
mode => '0644',
content => template('foreman/remote_execution_cockpit_session.yml.erb'),
require => Foreman::Plugin['remote_execution-cockpit'],
notify => Service['foreman-cockpit'],
}

include apache::mod::rewrite
include apache::mod::proxy_wstunnel
include apache::mod::proxy_http
foreman::config::apache::fragment { 'cockpit':
ssl_content => template('foreman/cockpit-apache-ssl.conf.erb'),
}

foreman_config_entry { 'remote_execution_cockpit_url':
value => "/${cockpit_path}/=%{host}",
}
}
88 changes: 88 additions & 0 deletions spec/acceptance/foreman_rex_cockpit_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
require 'spec_helper_acceptance'

describe 'Scenario: install foreman', if: os[:family] == 'centos' do
apache_service_name = ['debian', 'ubuntu'].include?(os[:family]) ? 'apache2' : 'httpd'

before(:context) do
case fact('osfamily')
when 'RedHat'
on default, 'yum -y remove foreman* tfm-* mod_passenger && rm -rf /etc/yum.repos.d/foreman*.repo'
when 'Debian'
on default, 'apt-get purge -y foreman*', { :acceptable_exit_codes => [0, 100] }
on default, 'apt-get purge -y ruby-hammer-cli-*', { :acceptable_exit_codes => [0, 100] }
on default, 'rm -rf /etc/apt/sources.list.d/foreman*'
end

on default, "systemctl stop #{apache_service_name}", { :acceptable_exit_codes => [0, 5] }
end

let(:pp) do
<<-EOS
$directory = '/etc/foreman'
$certificate = "${directory}/certificate.pem"
$key = "${directory}/key.pem"
exec { 'Create certificate directory':
command => "mkdir -p ${directory}",
path => ['/bin', '/usr/bin'],
creates => $directory,
} ->
exec { 'Generate certificate':
command => "openssl req -nodes -x509 -newkey rsa:2048 -subj '/CN=${facts['fqdn']}' -keyout '${key}' -out '${certificate}' -days 365",
path => ['/bin', '/usr/bin'],
creates => $certificate,
umask => '0022',
} ->
file { [$key, $certificate]:
owner => 'root',
group => 'root',
mode => '0640',
} ->
class { 'foreman':
repo => 'nightly',
user_groups => [],
initial_admin_username => 'admin',
initial_admin_password => 'changeme',
server_ssl_ca => $certificate,
server_ssl_chain => $certificate,
server_ssl_cert => $certificate,
server_ssl_key => $key,
server_ssl_crl => '',
}
include foreman::plugin::remote_execution::cockpit
EOS
end

it_behaves_like 'a idempotent resource'

describe service(apache_service_name) do
it { is_expected.to be_enabled }
it { is_expected.to be_running }
end

describe service('dynflowd') do
it { is_expected.to be_enabled }
it { is_expected.to be_running }
end

describe service('foreman') do
it { is_expected.to be_enabled }
it { is_expected.to be_running }
end

describe port(80) do
it { is_expected.to be_listening }
end

describe port(443) do
it { is_expected.to be_listening }
end

describe port(9999) do
it { is_expected.to be_listening.on('127.0.0.1').with('tcp') }
end

describe command("curl -s --cacert /etc/foreman/certificate.pem https://#{host_inventory['fqdn']} -w '\%{redirect_url}' -o /dev/null") do
its(:stdout) { is_expected.to eq("https://#{host_inventory['fqdn']}/users/login") }
its(:exit_status) { is_expected.to eq 0 }
end
end
72 changes: 72 additions & 0 deletions spec/classes/plugin/remote_execution_cockpit_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'spec_helper'

describe 'foreman::plugin::remote_execution::cockpit' do
on_os_under_test.each do |os, facts|
context "on #{os}" do
let(:facts) { facts }
let(:pre_condition) do
<<-PUPPET
class {'foreman':
foreman_url => 'https://foreman.example.com',
server_ssl_chain => '/path/to/ca.pem',
client_ssl_cert => '/path/to/cert.pem',
client_ssl_key => '/path/to/key.pem',
}
PUPPET
end

it { is_expected.to compile.with_all_deps }
it { is_expected.to contain_foreman__plugin('remote_execution-cockpit').that_notifies("Class[foreman::service]") }
it 'contains dependencies' do
is_expected.to contain_foreman__plugin('remote_execution')
is_expected.to contain_foreman__plugin('tasks')
end

it { is_expected.to contain_service('foreman-cockpit').with_ensure('running').with_enable('true') }

it 'creates configs' do
is_expected.to contain_file('/etc/foreman/cockpit/cockpit.conf')
.with_ensure('file')
.with_content([
'[WebService]',
'LoginTitle = Foreman Cockpit',
'UrlRoot = /webcon/',
'Origins = https://foreman.example.com',
'',
'[Bearer]',
'Action = remote-login-ssh',
'',
'[SSH-Login]',
'command = /usr/sbin/foreman-cockpit-session',
'',
'[OAuth]',
'Url = /cockpit/redirect',
].join("\n") + "\n")
.that_requires('Foreman::Plugin[remote_execution-cockpit]')
.that_notifies('Service[foreman-cockpit]')

is_expected.to contain_file('/etc/foreman/cockpit/foreman-cockpit-session.yml')
.with_ensure('file')
.with_content([
'---',
':foreman_url: "https://foreman.example.com"',
':ssl_ca_file: "/path/to/ca.pem"',
':ssl_certificate: "/path/to/cert.pem"',
':ssl_private_key: "/path/to/key.pem"',
].join("\n") + "\n")
.that_requires('Foreman::Plugin[remote_execution-cockpit]')
.that_notifies('Service[foreman-cockpit]')
end

it 'configures apache' do
is_expected.to contain_class('apache::mod::proxy_wstunnel')
is_expected.to contain_class('apache::mod::proxy_http')
is_expected.to contain_foreman__config__apache__fragment('cockpit')
.without_content
.with_ssl_content(%r{^<Location /webcon>$})
.with_ssl_content(%r{^ RewriteRule /webcon/\(\.\*\) ws://127\.0\.0\.1:9999/webcon/\$1 \[P\]$})
.with_ssl_content(%r{^ RewriteRule /webcon/\(\.\*\) http://127\.0\.0\.1:9999/webcon/\$1 \[P\]$})
end
end
end
end
11 changes: 11 additions & 0 deletions templates/cockpit-apache-ssl.conf.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### File managed with puppet ###

<Location <%= @cockpit_path %>>
ProxyPreserveHost On

RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule <%= @cockpit_path %>/(.*) ws://<%= @cockpit_host %>:<%= @cockpit_port %><%= @cockpit_path %>/$1 [P]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule <%= @cockpit_path %>/(.*) http://<%= @cockpit_host %>:<%= @cockpit_port %><%= @cockpit_path %>/$1 [P]
</Location>
13 changes: 13 additions & 0 deletions templates/remote_execution_cockpit.conf.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[WebService]
LoginTitle = Foreman Cockpit
UrlRoot = <%= @cockpit_path %>/
Origins = <%= @foreman_url %>

[Bearer]
Action = remote-login-ssh

[SSH-Login]
command = /usr/sbin/foreman-cockpit-session

[OAuth]
Url = /cockpit/redirect
4 changes: 4 additions & 0 deletions templates/remote_execution_cockpit_session.yml.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
<% @cockpit_config.each do |key, value| -%>
:<%= key %>: "<%= value %>"
<% end -%>

0 comments on commit 226e751

Please sign in to comment.