diff --git a/.fixtures.yml b/.fixtures.yml index 0707f93e9..4c99ec0a4 100644 --- a/.fixtures.yml +++ b/.fixtures.yml @@ -41,6 +41,7 @@ fixtures: reboot: {"repo": "puppetlabs/reboot", "ref": "5.0.0" } sshkeys_core: {"repo": "puppetlabs/sshkeys_core", "ref": "2.5.0" } stdlib: {"repo": "puppetlabs/stdlib", "ref": "9.6.0" } + vcsrepo: {"repo": "puppetlabs/vcsrepo", "ref": "6.1.0" } debconf: {"repo": "stm/debconf", "ref": "6.0.0" } #postgresql: {"repo": "puppetlabs/postgresql", "ref": "8.3.0"} #puppetdb: {"repo": "puppetlabs/puppetdb", "ref": "7.13.0"} diff --git a/manifests/profile/bolt.pp b/manifests/profile/bolt.pp new file mode 100644 index 000000000..8a47e3b65 --- /dev/null +++ b/manifests/profile/bolt.pp @@ -0,0 +1,49 @@ +# Copyright (c) 2024 The Regents of the University of Michigan. +# All Rights Reserved. Licensed according to the terms of the Revised +# BSD License. See LICENSE.txt for details. + +class nebula::profile::bolt { + include nebula::profile::managed_known_hosts + include nebula::profile::github_pull_account + include nebula::virtual::users + package { 'puppet-bolt': } + + $users = lookup('nebula::profile::authorized_keys::ssh_keys').keys + $all_users = lookup('nebula::virtual::users::all_users') + + $users.each |$user| { + $data = $all_users[$user] + + User <| title == $user |> { + home => "/home/${user}", + gid => 100, + require => File["/home/${user}"], + } + + file { "/home/${user}": + ensure => 'directory', + owner => $data['uid'], + group => 100, + mode => '0755', + } + } + + file { "/opt/bolt": + ensure => "directory", + owner => "git", + group => 100, + mode => "0755", + } + + vcsrepo { "/opt/bolt": + provider => "git", + ensure => "latest", + source => "ssh://git@github.com/mlibrary/bolt.git", + user => "git", + require => [ + Class["nebula::profile::github_pull_account"], + File["/opt/bolt"], + Package["git"], + ] + } +} diff --git a/manifests/profile/github_pull_account.pp b/manifests/profile/github_pull_account.pp new file mode 100644 index 000000000..7955276bd --- /dev/null +++ b/manifests/profile/github_pull_account.pp @@ -0,0 +1,50 @@ +# Copyright (c) 2024 The Regents of the University of Michigan. +# All Rights Reserved. Licensed according to the terms of the Revised +# BSD License. See LICENSE.txt for details. + +class nebula::profile::github_pull_account ( + String $git_username = "git", + Integer $git_gid = 100, + String $git_homedir = "/var/lib/autogit", +) { + package { "git": } + + user { $git_username: + ensure => "present", + home => $git_homedir, + gid => $git_gid, + managehome => true, + } + + file { "${git_homedir}/.ssh": + ensure => "directory", + owner => $git_username, + group => $git_gid, + mode => "0700", + require => User[$git_username], + } + + # Once this exists, you have to add the id_ecdsa.pub to any private + # github repos you want to pull. + exec { "create ${git_homedir}/.ssh/id_ecdsa": + creates => "${git_homedir}/.ssh/id_ecdsa", + user => $git_username, + command => "/usr/bin/ssh-keygen -t ecdsa -N '' -C '${::hostname}' -f ${git_homedir}/.ssh/id_ecdsa", + require => File["${git_homedir}/.ssh"], + } + + exec { "create /var/local/github_ssh_keys": + creates => "/var/local/github_ssh_keys", + command => "/usr/bin/ssh-keyscan github.com > /var/local/github_ssh_keys", + } + + include nebula::profile::managed_known_hosts + + # Without this, the git user will not be able to pull from private + # repos using ssh. + concat_fragment { "github ssh keys": + target => "/etc/ssh/ssh_known_hosts", + source => "/var/local/github_ssh_keys", + require => Exec["create /var/local/github_ssh_keys"], + } +} diff --git a/manifests/profile/managed_known_hosts.pp b/manifests/profile/managed_known_hosts.pp new file mode 100644 index 000000000..ebb93d839 --- /dev/null +++ b/manifests/profile/managed_known_hosts.pp @@ -0,0 +1,10 @@ +# Copyright (c) 2024 The Regents of the University of Michigan. +# All Rights Reserved. Licensed according to the terms of the Revised +# BSD License. See LICENSE.txt for details. + +class nebula::profile::managed_known_hosts { + concat { '/etc/ssh/ssh_known_hosts': } + + # See nebula::profile::known_host_public_keys + Concat_fragment <<| tag == 'known_host_public_keys' |>> +} diff --git a/manifests/profile/networking/firewall.pp b/manifests/profile/networking/firewall.pp index f8cff0dd1..29cb0bb11 100644 --- a/manifests/profile/networking/firewall.pp +++ b/manifests/profile/networking/firewall.pp @@ -95,6 +95,12 @@ ] } + 'fwknop': { + $input_ignore = ['-j FWKNOP_INPUT'] + $output_ignore = [] + $forward_ignore = [] + } + default: { $input_ignore = [] $output_ignore = [] diff --git a/manifests/profile/networking/sshd.pp b/manifests/profile/networking/sshd.pp index d3943a673..8cd225d0c 100644 --- a/manifests/profile/networking/sshd.pp +++ b/manifests/profile/networking/sshd.pp @@ -14,6 +14,7 @@ class nebula::profile::networking::sshd ( Array[String] $whitelist, String $addon_directives = '', + Integer $port = 22, ) { # This will do nothing if the keytab doesn't exist diff --git a/manifests/role/bastion.pp b/manifests/role/bastion.pp new file mode 100644 index 000000000..6721e9551 --- /dev/null +++ b/manifests/role/bastion.pp @@ -0,0 +1,16 @@ +# Copyright (c) 2022 The Regents of the University of Michigan. +# All Rights Reserved. Licensed according to the terms of the Revised +# BSD License. See LICENSE.txt for details. + +class nebula::role::bastion { + include nebula::role::minimum + + include nebula::profile::bolt + include nebula::profile::root_ssh_private_keys + + # These three are effectively the requirements for getting user login + # with kerberos and duo. + include nebula::profile::duo + include nebula::profile::krb5 + include nebula::profile::networking +} diff --git a/metadata.json b/metadata.json index d277715d9..78d2f8bff 100644 --- a/metadata.json +++ b/metadata.json @@ -30,6 +30,7 @@ {"name": "puppetlabs/reboot", "version_requirement": ">= 5.0.0 < 6.0.0" }, {"name": "puppetlabs/sshkeys_core", "version_requirement": ">= 2.5.0 < 3.0.0" }, {"name": "puppetlabs/stdlib", "version_requirement": ">= 9.6.0 < 10.0.0"}, + {"name": "puppetlabs/vcsrepo", "version_requirement": ">= 6.1.0 < 7.0.0"}, {"name": "stm/debconf", "version_requirement": ">= 6.0.0 < 7.0.0" } ], "operatingsystem_support": [ diff --git a/spec/classes/profile/bolt_spec.rb b/spec/classes/profile/bolt_spec.rb new file mode 100644 index 000000000..4c8952c5c --- /dev/null +++ b/spec/classes/profile/bolt_spec.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# Copyright (c) 2022, 2024 The Regents of the University of Michigan. +# All Rights Reserved. Licensed according to the terms of the Revised +# BSD License. See LICENSE.txt for details. +require 'spec_helper' + +describe 'nebula::profile::bolt' do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + + it { is_expected.to compile } + it { is_expected.to contain_package('puppet-bolt') } + it { is_expected.to contain_file('/opt/bolt').with_ensure('directory') } + it { is_expected.to contain_vcsrepo('/opt/bolt').with_ensure('latest') } + end + end +end diff --git a/spec/classes/profile/github_pull_account_spec.rb b/spec/classes/profile/github_pull_account_spec.rb new file mode 100644 index 000000000..99073bceb --- /dev/null +++ b/spec/classes/profile/github_pull_account_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# Copyright (c) 2024 The Regents of the University of Michigan. +# All Rights Reserved. Licensed according to the terms of the Revised +# BSD License. See LICENSE.txt for details. +require 'spec_helper' + +describe 'nebula::profile::github_pull_account' do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + + it { is_expected.to compile } + it { is_expected.to contain_user('git').with_home('/var/lib/autogit') } + it { is_expected.to contain_user('git').with_gid(100) } + it { is_expected.to contain_user('git').with_managehome(true) } + it { is_expected.to contain_file('/var/lib/autogit/.ssh').with_ensure('directory') } + it { is_expected.to contain_file('/var/lib/autogit/.ssh').with_mode('0700') } + it { is_expected.to contain_exec('create /var/lib/autogit/.ssh/id_ecdsa') } + it { is_expected.to contain_exec('create /var/local/github_ssh_keys') } + it { is_expected.to contain_concat_fragment('github ssh keys').with_target('/etc/ssh/ssh_known_hosts') } + end + end +end diff --git a/spec/classes/profile/managed_known_hosts_spec.rb b/spec/classes/profile/managed_known_hosts_spec.rb new file mode 100644 index 000000000..9e797a785 --- /dev/null +++ b/spec/classes/profile/managed_known_hosts_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +# Copyright (c) 2024 The Regents of the University of Michigan. +# All Rights Reserved. Licensed according to the terms of the Revised +# BSD License. See LICENSE.txt for details. +require 'spec_helper' + +describe 'nebula::profile::managed_known_hosts' do + on_supported_os.each do |os, os_facts| + context "on #{os}" do + let(:facts) { os_facts } + + it { is_expected.to compile } + it { is_expected.to contain_concat('/etc/ssh/ssh_known_hosts') } + end + end +end diff --git a/spec/classes/profile/networking/sshd_spec.rb b/spec/classes/profile/networking/sshd_spec.rb index 56f92b922..a98150201 100644 --- a/spec/classes/profile/networking/sshd_spec.rb +++ b/spec/classes/profile/networking/sshd_spec.rb @@ -25,6 +25,7 @@ def contain_sshd end [ + %r{^#Port 22$}, %r{^PermitRootLogin (prohibit|without)-password$}, %r{^PubkeyAuthentication no$}, %r{^PasswordAuthentication no$}, @@ -97,6 +98,20 @@ class { 'nebula::profile::networking::keytab': .with_target('/etc/pam.d/sshd') .with_content(%r{@include sshd-defaults}) end + + context 'with port set to 44' do + let(:params) { { port: 44 } } + + it { is_expected.not_to contain_sshd.with_content(%r{^#Port 22$}) } + it { is_expected.to contain_sshd.with_content(%r{^Port 44$}) } + end + + context 'with port set to 333' do + let(:params) { { port: 333 } } + + it { is_expected.not_to contain_sshd.with_content(%r{^#Port 22$}) } + it { is_expected.to contain_sshd.with_content(%r{^Port 333$}) } + end end end end diff --git a/templates/profile/networking/sshd_config.erb b/templates/profile/networking/sshd_config.erb index 29c543752..527162d2b 100644 --- a/templates/profile/networking/sshd_config.erb +++ b/templates/profile/networking/sshd_config.erb @@ -12,7 +12,11 @@ # possible, but leave them commented. Uncommented options override the # default value. +<% if @port == 22 -%> #Port 22 +<% else -%> +Port <%= @port %> +<% end -%> #AddressFamily any #ListenAddress 0.0.0.0 #ListenAddress ::