فهرست منبع

add bootstrap and common roles

Blaine Story 3 سال پیش
والد
کامیت
745f97b723

+ 10 - 0
plays/bootstrap.yml

@@ -0,0 +1,10 @@
+---
+- hosts: bootstrap
+  gather_facts: false
+  remote_user: root
+  become: true
+  vars:
+    ansible_host_key_checking: false
+    ansible_host_pattern_mismatch: ignore
+  roles:
+    - role: bootstrap

+ 59 - 0
roles/bootstrap/README.md

@@ -0,0 +1,59 @@
+Bootstrap
+=========
+
+An ansible role to bootstrap a fresh system to be able to utilize Ansible. It will install all the ansible dependencies, create an ansible user and give it the necessary permissions, install an ssh key and finally setting SSH to only allow logins with an ssh key.
+
+
+Requirements
+------------
+
+* A pre-generated ssh key installed on the local system. (Defaults to `~/.ssh/ansible_rsa.pub`, but can be changed by setting the ansible_ssh_key_path variable.
+* Add the list of hosts to bootstrap to the [bootstrap] group in the ansible [inventory file](https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html) file. Defaults to `hosts` in the root of the ansible git repo.
+* This role __must__ be run with the option `--ask-pass`.
+
+NOTE: Debian distros disable SSH root login by default. In order to run this role, you must first enable it by setting `PermitRootLogin yes` in `/etc/ssh/sshd_config` and restarting SSH `systemctl restart ssh`
+
+```
+[bootstrap]
+webserver1
+webserver2
+10.0.0.162
+```
+
+Role Variables
+--------------
+
+* __bootstrap_hosts__: DNS hostname(s) or IP address(es) of the host(s) to be bootstrapped. Defaults to the ansible inventory group "bootstrap"
+
+* __ansible\_ssh\_key\_path__: Local path to the public key ansible will install. Defaults to `~/.ssh/ansible_rsa.pub`
+
+* __ansible_username__: User that ansible will create for connecting over after bootstrapping. Defaults to `ansible`
+
+* __ssh_username__: User that ansible will connect over SSH as while doing the initial bootstrap installation. Defaults to `root`
+
+* __os_family__: Used to determine which package manager to use. Defaults to `redhat`. For Debian-style distros change to `debian`
+
+
+
+Example Usage
+-------------
+
+#### Bootstrap a new server:
+
+    ansible-playbook bootstrap.yml --ask-pass
+
+#### Bootstrap a server with a different ssh key:
+
+    ansible-playbook bootstrap.yml --extra-vars 'ansible_ssh_key_path="~/.ssh/my_other_key.pub"' --ask-pass
+
+#### Bootstrap a Debian server:
+
+    ansible-playbook bootstrap.yml --extra-vars 'os_family=debian' --ask-pass
+
+__Note__: This role __must__ be run with the option `--ask-pass`.
+
+License
+-------
+
+GPLv3
+

+ 6 - 0
roles/bootstrap/defaults/main.yml

@@ -0,0 +1,6 @@
+---
+ansible_ssh_key_path: "~/.ssh/ansible_rsa.pub"
+ansible_username: "ansible"
+ansible_ssh_user: "root"
+bootstrap_hosts: "bootstrap"
+os_family: "redhat"

+ 1 - 0
roles/bootstrap/files/10_ansible

@@ -0,0 +1 @@
+ansible ALL = NOPASSWD: ALL

+ 5 - 0
roles/bootstrap/handlers/main.yml

@@ -0,0 +1,5 @@
+---
+- name: Restart sshd
+  systemd:
+    name: sshd
+    state: restarted

+ 73 - 0
roles/bootstrap/tasks/main.yml

@@ -0,0 +1,73 @@
+---
+- name: Install Python without using Ansible modules
+  raw: >
+       bash -c "test -e /usr/bin/python3 || 
+       (test -e /usr/bin/yum && yum install -y python3) || 
+       (apt install -y python3 python-apt) || 
+       grep -i LibreELEC /etc/os-release"
+  changed_when: false
+
+- name: Gather facts now that Python is installed
+  setup:
+
+- name: Install sudo and lsb (RPM)
+  package:
+    name:
+      - sudo
+      - "{% if ansible_distribution_major_version != '9' %}redhat-lsb-core{% else %}python3-libselinux{% endif %}"
+    state: present
+  when:
+    - ansible_distribution == 'CentOS' or ansible_distribution == 'Fedora'
+
+- name: Install sudo and lsb (DEB)
+  package:
+    name:
+      - sudo
+      - lsb-release
+    state: present
+  when:
+    - ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
+
+- name: Install SELinux Python Modules (Fedora)
+  package:
+    name:
+      - python3-libselinux
+    state: present
+  when:
+    - ansible_distribution == 'Fedora'
+
+- name: Gather facts again now that lsb is installed
+  setup:
+
+- name: Creating ansible user
+  user:
+    name: ansible
+    state: present
+    shell: /bin/bash
+    create_home: yes
+  when:
+    - ansible_os_family != 'LibreELEC'
+
+- name: Adding ansible as a sudoer
+  copy:
+    src: 10_ansible
+    dest: /etc/sudoers.d/10_ansible
+    owner: root
+    group: root
+    mode: '0640'
+  when:
+    - ansible_os_family != 'LibreELEC'
+
+- import_role:
+    name: common
+
+- name: Ensure only key-based SSH logins are allowed
+  lineinfile:
+    path: /etc/ssh/sshd_config
+    regexp: '^PasswordAuthentication'
+    line: 'PasswordAuthentication no'
+    state: present
+  notify:
+    - Restart sshd
+  when:
+    - ansible_os_family != 'LibreELEC' # / is mounted RO in LibreELEC

+ 2 - 0
roles/common/defaults/main.yml

@@ -0,0 +1,2 @@
+---
+host_ssh_root_keys: []

+ 182 - 0
roles/common/tasks/main.yml

@@ -0,0 +1,182 @@
+---
+- name: Enable crb on CentOS 9
+  shell:
+    cmd: dnf config-manager --set-enabled crb
+    warn: false # I know shell module is bad...
+  changed_when: false
+  when:
+    - ansible_distribution == "CentOS"
+    - ansible_distribution_major_version == "9"
+
+- name: Enable EPEL Repo on CentOS 7/8
+  package:
+    name: epel-release
+    state: present
+  when:
+    - ansible_distribution == "CentOS"
+    - ansible_distribution_major_version|int > 9
+
+- name: Check for EPEL Repo on CentOS 9
+  shell:
+    cmd: rpm -q epel-release
+    warn: false
+  changed_when: false
+  failed_when: false
+  register: epel_check
+  when:
+    - ansible_distribution == "CentOS"
+    - ansible_distribution_major_version == "9"
+
+- name: Enable EPEL Repo on CentOS 9
+  dnf:
+    name:
+      - https://dl.fedoraproject.org/pub/epel/9/Everything/x86_64/Packages/e/epel-release-9-2.el9.noarch.rpm
+      - https://dl.fedoraproject.org/pub/epel/9/Everything/x86_64/Packages/e/epel-next-release-9-2.el9.noarch.rpm
+    state: present
+    disable_gpg_check: yes
+  when:
+    - ansible_distribution == "CentOS"
+    - ansible_distribution_major_version == "9"
+    - epel_check.rc|int == 1
+
+- name: Enable PowerTools on CentOS 8
+  lineinfile:
+    path: /etc/yum.repos.d/CentOS-{% if ansible_lsb.id == 'CentOSStream' %}Stream-{% endif %}PowerTools.repo
+    regexp: '^enabled='
+    line: 'enabled=1'
+  when:
+    - ansible_distribution == 'CentOS'
+    - ansible_distribution_major_version == "8"
+
+- name: Download RPMFusion .rpms 
+  get_url:
+    url: "{{ item }}"
+    dest: /home/ansible/{{ item | basename }}
+    owner: ansible
+    group: ansible
+    mode: '0644'
+  loop:
+    - https://download1.rpmfusion.org/free/{{ 'el' if ansible_distribution == 'CentOS' else 'fedora' }}/rpmfusion-free-release-{{ ansible_distribution_major_version }}.noarch.rpm 
+    - https://download1.rpmfusion.org/nonfree/{{ 'el' if ansible_distribution == 'CentOS' else 'fedora' }}/rpmfusion-nonfree-release-{{ ansible_distribution_major_version }}.noarch.rpm 
+  loop_control:
+    label: "{{ item | basename }}"
+  register: rpmfusion_repos
+  when:
+    - ansible_distribution == 'CentOS' or ansible_distribution == 'Fedora'
+    - ansible_distribution_major_version != "9" # no RPMFusion yet for CentOS Stream 9
+    - '"rpmfusion" not in ansible_facts.packages|list'
+
+
+- name: Install RPMFusion .rpms
+  yum:
+    name: 
+      - /home/ansible/rpmfusion-free-release-{{ ansible_distribution_major_version }}.noarch.rpm
+      - /home/ansible/rpmfusion-nonfree-release-{{ ansible_distribution_major_version }}.noarch.rpm
+    disable_gpg_check: yes
+    state: present
+  when:
+    - rpmfusion_repos is defined
+    - rpmfusion_repos.changed
+    - ansible_distribution == 'CentOS' or ansible_distribution == 'Fedora'
+    - ansible_distribution_major_version != "9" # no RPMFusion yet for CentOS Stream 9
+
+
+- name: Combine Packages (RPM)
+  set_fact:
+    all_pkgs: "{{ all_pkgs | default([]) | union(item) }}"
+  loop:
+    - "{{ common_pkgs }}"
+    - "{{ common_pkgs_rpm }}"
+    - "{{ host_pkgs | default([]) }}"
+  loop_control:
+    label: "{{ all_pkgs | default([]) | length }} Packages"
+  when:
+    - ansible_distribution == 'CentOS' or ansible_distribution == 'Fedora'
+
+- name: Combine Packages (DEB)
+  set_fact:
+    all_pkgs: "{{ all_pkgs | default([]) | union(item) }}"
+  loop:
+    - "{{ common_pkgs }}"
+    - "{{ common_pkgs_deb }}"
+    - "{{ host_pkgs | default([]) }}"
+  when:
+    - ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
+
+- name: Install packages
+  package:
+    name: "{{ all_pkgs }}"
+    state: present
+  when:
+    - all_pkgs is defined
+
+- name: Install ansible SSH keys
+  authorized_key:
+    user: ansible
+    state: present
+    exclusive: yes
+    key: "{{ ssh_ansible_keys | join('\n') }}"
+  when:
+    - ansible_os_family != 'LibreELEC'
+  tags: ssh
+
+
+- name: Install root SSH keys
+  authorized_key:
+    user: root
+    state: present
+    exclusive: yes
+    key: "{{ ssh_root_keys | union(host_ssh_root_keys) | join('\n') }}"
+  tags: ssh
+
+
+- name: Install pi SSH keys
+  authorized_key:
+    user: pi
+    state: present
+    exclusive: yes
+    key: "{{ ssh_root_keys | join('\n') }}"
+  when:
+    - '"libreelec" in group_names'
+  tags: ssh
+
+
+- name: Add Bash aliases for root user
+  lineinfile:
+    dest: /root/.bashrc
+    create: yes
+    mode: '0644'
+    line: "alias {{ item.alias }}='{{ item.command }}'"
+    regexp: "^alias {{ item.alias }}="
+  with_items:
+    - "{{ common_bash_aliases | default('') }}"
+    - "{{ host_bash_aliases | default('') }}"
+  when:
+    - (item.user is not defined or item.user == 'root')
+    - item.alias is defined
+    - item.command is defined
+    - ansible_os_family != 'LibreELEC'
+  tags: aliases
+
+
+- name: Add bash aliases for non-root users
+  lineinfile:
+    dest: /home/{{ item.user }}/.bashrc
+    create: no
+    mode: '0644'
+    line: "alias {{ item.alias }}='{{ item.command }}'"
+    regexp: "^alias {{ item.alias }}="
+  register: create_alias
+  failed_when:
+    - create_alias.rc is defined
+    - create_alias.rc != 257
+  with_items:
+    - "{{ common_bash_aliases | default('') }}"
+    - "{{ host_bash_aliases | default('') }}"
+  when:
+    - item.user is defined
+    - item.user != 'root'
+    - item.alias is defined
+    - item.command is defined
+    - ansible_os_family != 'LibreELEC'
+  tags: aliases