diff --git a/ansible/.ansible-lint b/ansible/.ansible-lint new file mode 100644 index 0000000..0c31185 --- /dev/null +++ b/ansible/.ansible-lint @@ -0,0 +1,2 @@ +skip_list: + - '403' # Package installs should not use latest. diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg new file mode 100644 index 0000000..ae61bc8 --- /dev/null +++ b/ansible/ansible.cfg @@ -0,0 +1,5 @@ +[defaults] +roles_path = roles/ + +[connection] +pipelining = True \ No newline at end of file diff --git a/ansible/packer.yml b/ansible/packer.yml new file mode 100644 index 0000000..463c770 --- /dev/null +++ b/ansible/packer.yml @@ -0,0 +1,14 @@ +--- +- name: Configure template + hosts: default + become: true + roles: + - auditd + - fail2ban + - journald + - sshd + - timesyncd + post_tasks: + - name: Clean cloud-init + ansible.builtin.command: "cloud-init clean" + changed_when: false diff --git a/ansible/roles/auditd/files/custom.rules b/ansible/roles/auditd/files/custom.rules new file mode 100755 index 0000000..efdd0db --- /dev/null +++ b/ansible/roles/auditd/files/custom.rules @@ -0,0 +1,32 @@ +-w /sbin/insmod -p x -k insmod_execute +-w /sbin/modprobe -p x -k modprobe_execute +-w /sbin/rmmod -p x -k rmmod_execute +-w /bin/kmod -p x -k kmod_execute + +-w /etc/ -p wa -k etc_change +-w /dev/shm/ -p wa -k share_memory_change + +-w /root/ -p wa -k root_home_change +-w /etc/passwd -p wa -k passwd_change +-w /etc/shadow -p rwa -k shadow_change +-w /etc/group -p wa -k group_change +-w /etc/security -k security_change +-w /etc/audit/ -p rwa -k etc_audit_change +-w /etc/sudoers -p wa -k sudoers_change +-w /etc/sudoers.d -p wa -k sudoers_change + +-a exit,always -F arch=b64 -S mount -S umount2 -k partition_mount + +-a exit,always -F arch=b64 -S ioperm -S modify_ldt -k ioperm_modify_ldt + +-a exit,always -F arch=b64 -S get_kernel_syms -S ptrace -k get_kernel_syms + +-a exit,always -F arch=b64 -S unlink -S rmdir -S rename -k unlink_rmdir +-a exit,always -F arch=b64 -S creat -S open -S openat -F exit=-EACCES -k creat_openat +-a exit,always -F arch=b64 -S truncate -S ftruncate -F exit=-EACCES -k truncate + +-a exit,always -F arch=b64 -S init_module -S delete_module -k init_delete_module +-a exit,always -F arch=b64 -S finit_module -k finit_module -k finit + +-e 2 +-f 2 \ No newline at end of file diff --git a/ansible/roles/auditd/handlers/main.yml b/ansible/roles/auditd/handlers/main.yml new file mode 100755 index 0000000..17a7bb5 --- /dev/null +++ b/ansible/roles/auditd/handlers/main.yml @@ -0,0 +1,10 @@ +--- +- name: Start auditd + ansible.builtin.systemd: + name: auditd + state: started + +- name: Enable auditd + ansible.builtin.systemd: + name: auditd + enabled: true diff --git a/ansible/roles/auditd/tasks/main.yml b/ansible/roles/auditd/tasks/main.yml new file mode 100755 index 0000000..4588752 --- /dev/null +++ b/ansible/roles/auditd/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- name: Install audit + ansible.builtin.apt: + name: auditd + state: latest + notify: + - Start auditd + - Enable auditd + +- name: Add rules + ansible.builtin.copy: + src: 'custom.rules' + dest: '/etc/audit/rules.d/custom.rules' + mode: "0640" diff --git a/ansible/roles/fail2ban/files/sshd.conf b/ansible/roles/fail2ban/files/sshd.conf new file mode 100755 index 0000000..0730a9c --- /dev/null +++ b/ansible/roles/fail2ban/files/sshd.conf @@ -0,0 +1,4 @@ +[sshd] +enabled = true +bantime = -1 +maxretry = 3 diff --git a/ansible/roles/fail2ban/handlers/main.yml b/ansible/roles/fail2ban/handlers/main.yml new file mode 100755 index 0000000..094e747 --- /dev/null +++ b/ansible/roles/fail2ban/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart fail2ban + ansible.builtin.systemd: + name: fail2ban.service + state: restarted diff --git a/ansible/roles/fail2ban/tasks/main.yml b/ansible/roles/fail2ban/tasks/main.yml new file mode 100755 index 0000000..154e486 --- /dev/null +++ b/ansible/roles/fail2ban/tasks/main.yml @@ -0,0 +1,19 @@ +--- +- name: Install fail2ban + ansible.builtin.apt: + name: "fail2ban" + state: latest + +- name: Copy sshd.conf + ansible.builtin.copy: + src: 'sshd.conf' + dest: '/etc/fail2ban/jail.d/sshd.conf' + mode: "0640" + notify: + - Restart fail2ban + +- name: Start fail2ban.service + ansible.builtin.systemd: + state: started + name: fail2ban.service + enabled: true diff --git a/ansible/roles/journald/files/retention-time.conf b/ansible/roles/journald/files/retention-time.conf new file mode 100755 index 0000000..ae81718 --- /dev/null +++ b/ansible/roles/journald/files/retention-time.conf @@ -0,0 +1,2 @@ +[Journal] +MaxRetentionSec=7day diff --git a/ansible/roles/journald/handlers/main.yml b/ansible/roles/journald/handlers/main.yml new file mode 100755 index 0000000..3fee2c9 --- /dev/null +++ b/ansible/roles/journald/handlers/main.yml @@ -0,0 +1,5 @@ +--- +- name: Restart journald + ansible.builtin.systemd: + name: systemd-journald.service + state: restarted diff --git a/ansible/roles/journald/tasks/main.yml b/ansible/roles/journald/tasks/main.yml new file mode 100755 index 0000000..45400e5 --- /dev/null +++ b/ansible/roles/journald/tasks/main.yml @@ -0,0 +1,14 @@ +--- +- name: Create /etc/systemd/journald.conf.d + ansible.builtin.file: + path: '/etc/systemd/journald.conf.d' + state: 'directory' + mode: "0750" + +- name: Copy retention-time.conf + ansible.builtin.copy: + src: 'retention-time.conf' + dest: '/etc/systemd/journald.conf.d' + mode: "0640" + notify: + - Restart journald diff --git a/ansible/roles/sshd/files/crypto.conf b/ansible/roles/sshd/files/crypto.conf new file mode 100644 index 0000000..546ecdf --- /dev/null +++ b/ansible/roles/sshd/files/crypto.conf @@ -0,0 +1,17 @@ +# Restrict key exchange, cipher, and MAC algorithms, as per sshaudit.com +# hardening guide. +KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.org,gss-curve25519-sha256-,diffie-hellman-group16-sha512,gss-group16-sha512-,diffie-hellman-group18-sha512,diffie-hellman-group-exchange-sha256 + +Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr + +MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,umac-128-etm@openssh.com + +HostKeyAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 + +CASignatureAlgorithms sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512,rsa-sha2-256 + +GSSAPIKexAlgorithms gss-curve25519-sha256-,gss-group16-sha512- + +HostbasedAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256 + +PubkeyAcceptedAlgorithms sk-ssh-ed25519-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519@openssh.com,ssh-ed25519,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-512,rsa-sha2-256-cert-v01@openssh.com,rsa-sha2-256 diff --git a/ansible/roles/sshd/handlers/main.yml b/ansible/roles/sshd/handlers/main.yml new file mode 100644 index 0000000..89aa775 --- /dev/null +++ b/ansible/roles/sshd/handlers/main.yml @@ -0,0 +1,5 @@ +- name: Restart SSH + ansible.builtin.service: + name: sshd + state: restarted + enabled: true diff --git a/ansible/roles/sshd/tasks/main.yml b/ansible/roles/sshd/tasks/main.yml new file mode 100644 index 0000000..13a0776 --- /dev/null +++ b/ansible/roles/sshd/tasks/main.yml @@ -0,0 +1,40 @@ +--- +- name: Disable Password Authentication + ansible.builtin.lineinfile: + dest: /etc/ssh/sshd_config + regexp: '^PasswordAuthentication' + line: "PasswordAuthentication no" + state: present + backup: true + notify: + - Restart SSH + +- name: Disable Root Login + ansible.builtin.lineinfile: + dest: /etc/ssh/sshd_config + regexp: '^PermitRootLogin' + line: "PermitRootLogin no" + state: present + backup: true + notify: + - Restart SSH + +- name: Restrict host key + ansible.builtin.lineinfile: + dest: /etc/ssh/sshd_config + regexp: '#HostKey /etc/ssh/ssh_host_ed25519_key' + line: "HostKey /etc/ssh/ssh_host_ed25519_key" + state: present + backup: true + notify: + - Restart SSH + +- name: Configure sshd + ansible.builtin.copy: + src: "crypto.conf" + dest: "/etc/ssh/sshd_config.d/" + owner: root + group: root + mode: "0640" + notify: + - Restart SSH \ No newline at end of file diff --git a/ansible/roles/timesyncd/tasks/main.yml b/ansible/roles/timesyncd/tasks/main.yml new file mode 100755 index 0000000..51079fe --- /dev/null +++ b/ansible/roles/timesyncd/tasks/main.yml @@ -0,0 +1,8 @@ +--- +- name: Set timezone to Europe/Brussels + community.general.timezone: + name: Europe/Brussels + +- name: Enable ntp + ansible.builtin.command: 'timedatectl set-ntp true' + changed_when: false diff --git a/packer/http/meta-data b/packer/http/meta-data new file mode 100644 index 0000000..e69de29 diff --git a/packer/http/user-data b/packer/http/user-data new file mode 100644 index 0000000..e804715 --- /dev/null +++ b/packer/http/user-data @@ -0,0 +1,29 @@ +#cloud-config +autoinstall: + version: 1 + source: + id: ubuntu-server-minimal + identity: + hostname: ubuntu-2204-r4 + password: "${password_crypt}" + username: "${user}" + user-data: + disable_root: true + refresh-installer: + update: true + packages: + - openssh-server + - qemu-guest-agent + - cloud-init + ssh: + allow-pw: false + install-server: true + authorized-keys: + - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILBPOnqmExTKt8OceAq9K4d/MkVu4WsU+sqiEV7KbtyH" + storage: + layout: + name: direct + kernel: + package: linux-image-kvm + timezone: Europe/Brussels + updates: all diff --git a/packer/ubuntu-2204.pkr.hcl b/packer/ubuntu-2204.pkr.hcl new file mode 100644 index 0000000..3d49d11 --- /dev/null +++ b/packer/ubuntu-2204.pkr.hcl @@ -0,0 +1,115 @@ +packer { + required_plugins { + name = { + version = "~> 1" + source = "github.com/hashicorp/proxmox" + } + ansible = { + version = "~> 1" + source = "github.com/hashicorp/ansible" + } + } +} + +variable "ssh_password_crypt" { + type = string + default = null +} + +variable "ssh_user" { + type = string + default = "packer" +} + +variable "ssh_password" { + type = string + default = null +} + +variable "proxmox_user" { + type = string + default = "packer" +} + +variable "proxmox_token" { + type = string + default = null +} + +variable "proxmox_url" { + type = string + default = "localhost:8006" +} + +source "proxmox-iso" "ubuntu-2204" { + http_content = { + "/meta-data" = file("http/meta-data") + "/user-data" = templatefile("http/user-data", { user = var.ssh_user, password_crypt = var.ssh_password_crypt }) + } + + + boot_command = [ + "e", + " autoinstall ds=\"nocloud-net;seedfrom=http://{{.HTTPIP}}:{{.HTTPPort}}/\"", + "x", + ] + + + boot_wait = "10s" + + disks { + disk_size = "10G" + storage_pool = "lab" + type = "virtio" + } + scsi_controller = "virtio-scsi-single" + + bios = "ovmf" + efi_config { + efi_storage_pool = "lab" + efi_type = "4m" + pre_enrolled_keys = true + } + + insecure_skip_tls_verify = true + + iso_checksum = "45f873de9f8cb637345d6e66a583762730bbea30277ef7b32c9c3bd6700a32b2" + iso_url = "https://releases.ubuntu.com/22.04.4/ubuntu-22.04.4-live-server-amd64.iso" + iso_storage_pool = "local" + iso_download_pve = true + unmount_iso = true + + network_adapters { + bridge = "vmbr20" + model = "virtio" + } + + memory = 8192 + cores = 4 + vm_id = 9000 + + node = "sorm" + username = "${var.proxmox_user}" + token = "${var.proxmox_token}" + proxmox_url = "${var.proxmox_url}/api2/json" + ssh_username = "${var.ssh_user}" + ssh_private_key_file = "~/.ssh/id_ed25519" + ssh_timeout = "15m" + template_description = "Ubuntu 22.04 build by packer on ${timestamp()}" + template_name = "ubuntu-2204-r4" + cloud_init = true + cloud_init_storage_pool = "local-lvm" +} + + +build { + sources = ["source.proxmox-iso.ubuntu-2204"] + provisioner "ansible" { + ansible_env_vars = ["ANSIBLE_CONFIG=../ansible/ansible.cfg", "ANSIBLE_HOST_KEY_CHECKING=False", "ANSIBLE_BECOME_PASS=${var.ssh_password}"] + extra_arguments = [ "--scp-extra-args", "'-O'", "-vv", "--extra-vars", "ansible_become_password=${var.ssh_password}" ] + command = "ansible-playbook" + roles_path = "../ansible/roles" + playbook_file = "../ansible/packer.yml" + } + +}