From 5543ae4d27702175b4c4357ff66b1e92583568ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B5=D1=80=D0=B3=D0=B5=D0=B9=20=D0=90=D0=BD=D1=82?= =?UTF-8?q?=D1=80=D0=BE=D0=BF=D0=BE=D0=B2?= Date: Mon, 27 Oct 2025 19:43:26 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20geop=20?= =?UTF-8?q?=D0=B2=20cod=20=D0=B8=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20ARM64=20=D0=BF=D0=BE=D0=B4=D0=B4?= =?UTF-8?q?=D0=B5=D1=80=D0=B6=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Переименован пресет geop.yml в cod.yml - Обновлены все группы с geop на cod - Добавлена поддержка ARM64 для Astra Linux и RedOS - Создан Dockerfile.arm64 для RedOS с исправлением конфликтов пакетов - Улучшены разделители в логах Molecule - Зашифрован файл vault/secrets.yml - Обновлена роль devops с поддержкой vault - Добавлены шаблоны для SSH и sudoers конфигураций --- Makefile | 3 +- dockerfiles/ansible-controller/Dockerfile | 9 +- dockerfiles/redos/Dockerfile.arm64 | 80 +++++ molecule/default/converge.yml | 92 +++--- molecule/default/create.yml | 103 +++++- molecule/default/destroy.yml | 53 ++- molecule/default/molecule.yml | 54 +++- molecule/default/site.yml | 3 + molecule/default/verify.yml | 28 +- molecule/presets/cod.yml | 93 ++++++ molecule/presets/minimal.yml | 45 +++ roles/deploy.yml | 7 +- roles/devops/QUICKSTART.md | 227 ------------- roles/devops/README.md | 297 ++++++++++------- roles/devops/defaults/main.yml | 126 ++++---- roles/devops/examples.yml | 85 ----- roles/devops/handlers/main.yml | 172 ++++++++-- roles/devops/meta/main.yml | 76 +++-- roles/devops/playbook.yml | 50 --- roles/devops/tasks/main.yml | 342 ++++++++++++++------ roles/devops/templates/devops_ssh_config.j2 | 79 +++++ roles/devops/templates/devops_sudoers.j2 | 21 ++ roles/devops/tests/test.yml | 90 ------ roles/devops/vars/main.yml | 222 +++++++++++-- vault/secrets.yml | 105 ++---- 25 files changed, 1531 insertions(+), 931 deletions(-) create mode 100644 dockerfiles/redos/Dockerfile.arm64 create mode 100644 molecule/presets/cod.yml create mode 100644 molecule/presets/minimal.yml delete mode 100644 roles/devops/QUICKSTART.md delete mode 100644 roles/devops/examples.yml delete mode 100644 roles/devops/playbook.yml create mode 100644 roles/devops/templates/devops_ssh_config.j2 create mode 100644 roles/devops/templates/devops_sudoers.j2 delete mode 100644 roles/devops/tests/test.yml diff --git a/Makefile b/Makefile index ab7b387..1533c9b 100644 --- a/Makefile +++ b/Makefile @@ -89,8 +89,9 @@ role: -e ANSIBLE_FORCE_COLOR=1 \ -e MOLECULE_PRESET=$$PRESET \ -e MOLECULE_EPHEMERAL_DIRECTORY=/tmp/molecule_workspace \ + -e MOLECULE_VAULT_ENABLED=$${MOLECULE_VAULT_ENABLED:-false} \ $(DOCKER_IMAGE) \ - bash -c "mkdir -p /tmp/molecule_workspace/inventory && cd molecule/default && ansible-playbook -i localhost, create.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini site.yml; ansible-playbook -i localhost, destroy.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace; echo '✅ Тестирование завершено'";; \ + bash -c "mkdir -p /tmp/molecule_workspace/inventory && cd molecule/default && ansible-playbook -i localhost, create.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && ansible-playbook -i localhost, converge.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace && ansible-playbook -i /tmp/molecule_workspace/inventory/hosts.ini site.yml; ansible-playbook -i localhost, destroy.yml --connection=local -e molecule_ephemeral_directory=/tmp/molecule_workspace; echo '✅ Тестирование завершено'";; \ deploy) \ echo "🚀 Развертывание ролей на реальные серверы..."; \ echo ""; \ diff --git a/dockerfiles/ansible-controller/Dockerfile b/dockerfiles/ansible-controller/Dockerfile index 71d3a77..2af0d70 100644 --- a/dockerfiles/ansible-controller/Dockerfile +++ b/dockerfiles/ansible-controller/Dockerfile @@ -16,7 +16,7 @@ RUN apt-get install -y \ build-essential \ && apt-get clean -# Устанавливаем Ansible, ansible-lint и passlib для хеширования паролей +# Устанавливаем Ansible, ansible-lint, passlib RUN pip3 install ansible ansible-core ansible-lint passlib # Устанавливаем дополнительные пакеты @@ -83,11 +83,18 @@ USER ansible RUN ansible-galaxy install geerlingguy.docker \ && ansible-galaxy install geerlingguy.kubernetes +# Устанавливаем molecule как root +RUN pip3 install ansible ansible-core ansible-lint molecule molecule-docker passlib + +# Проверяем, что molecule установлен +RUN which molecule || echo "molecule not found" + # Настройки для работы с Docker ENV DOCKER_HOST=unix:///var/run/docker.sock ENV ANSIBLE_FORCE_COLOR=1 ENV ANSIBLE_STDOUT_CALLBACK=yaml ENV ANSIBLE_CALLBACKS_ENABLED=profile_tasks +ENV PATH="/home/ansible/.local/bin:$PATH" # Команда по умолчанию CMD ["sleep", "infinity"] diff --git a/dockerfiles/redos/Dockerfile.arm64 b/dockerfiles/redos/Dockerfile.arm64 new file mode 100644 index 0000000..ea47867 --- /dev/null +++ b/dockerfiles/redos/Dockerfile.arm64 @@ -0,0 +1,80 @@ +# RedOS совместимый образ для ARM64 +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# Базируется на CentOS Stream для совместимости с ARM64 +# ВАЖНО: Это эмуляция RedOS на CentOS Stream для ARM64 + +FROM quay.io/centos/centos:stream9 + +# Устанавливаем переменные окружения +ENV LANG=ru_RU.UTF-8 +ENV LANGUAGE=ru_RU:ru +ENV LC_ALL=ru_RU.UTF-8 + +# Обновляем систему +RUN dnf update -y && dnf upgrade -y + +# Устанавливаем локали +RUN dnf install -y glibc-langpack-ru glibc-locale-source && \ + localedef -i ru_RU -f UTF-8 ru_RU.UTF-8 || true + +# Устанавливаем systemd и необходимые пакеты +RUN dnf install -y --allowerasing \ + systemd \ + systemd-sysv \ + dbus \ + curl \ + wget \ + nano \ + python3 \ + python3-pip \ + sudo \ + ca-certificates \ + gnupg \ + && dnf clean all + +# Устанавливаем yq (автоопределение архитектуры) +RUN ARCH=$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/') && \ + wget -qO /usr/local/bin/yq "https://github.com/mikefarah/yq/releases/latest/download/yq_linux_${ARCH}" && \ + chmod +x /usr/local/bin/yq + +# Устанавливаем Docker для ARM64 +RUN ARCH=$(uname -m) && \ + dnf install -y dnf-plugins-core && \ + dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \ + dnf install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin && \ + dnf clean all + +# Устанавливаем Docker Compose +RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose \ + && chmod +x /usr/local/bin/docker-compose + +# Создаем файлы конфигурации для эмуляции RedOS +RUN echo "Red OS" > /etc/os-release && \ + echo "VERSION_ID=\"8.0\"" >> /etc/os-release && \ + echo "PRETTY_NAME=\"Red OS 8.0 (ARM64 Compatible)\"" >> /etc/os-release && \ + echo "ID=\"redos\"" >> /etc/os-release && \ + echo "ID_LIKE=\"rhel fedora\"" >> /etc/os-release && \ + echo "VERSION=\"8.0\"" >> /etc/os-release && \ + echo "VERSION_CODENAME=\"\"" >> /etc/os-release && \ + echo "PLATFORM_ID=\"platform:el8\"" >> /etc/os-release && \ + echo "HOME_URL=\"https://www.red-soft.ru/\"" >> /etc/os-release && \ + echo "BUG_REPORT_URL=\"https://www.red-soft.ru/support/\"" >> /etc/os-release && \ + echo "REDHAT_BUGZILLA_PRODUCT=\"Red OS\"" >> /etc/os-release && \ + echo "REDHAT_BUGZILLA_PRODUCT_VERSION=\"8.0\"" >> /etc/os-release && \ + echo "REDHAT_SUPPORT_PRODUCT=\"Red OS\"" >> /etc/os-release && \ + echo "REDHAT_SUPPORT_PRODUCT_VERSION=\"8.0\"" >> /etc/os-release + +# Настраиваем systemd +RUN systemctl set-default multi-user.target + +# Настраиваем sudoers для root и пользователей +RUN echo "root ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers && \ + echo "ALL ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/ansible-test + +# Создаем пользователя для Ansible +RUN useradd -m -s /bin/bash ansible \ + && echo "ansible ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers + +# Команда по умолчанию (система запускается от root для systemd) +CMD ["/sbin/init"] diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index 8c67047..d1c39c6 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -1,4 +1,7 @@ --- +# ============================================================================= +# CONVERGE - Сборка и запуск тестовых сценариев +# ============================================================================= - hosts: localhost gather_facts: false vars: @@ -15,6 +18,18 @@ - /workspace/roles/**/vars/vault.yml tasks: + # ============================================================================= + # НАСТРОЙКА - Загрузка конфигурации и подготовка + # ============================================================================= + - name: Configuration setup + debug: + msg: | + ================================================================================ + НАСТРОЙКА - Загрузка конфигурации и подготовка + ================================================================================ + Preset: {{ preset_name }} + ================================================================================ + - name: Load preset configuration include_vars: "{{ preset_file }}" when: preset_file is file @@ -25,52 +40,55 @@ # container: ansible-controller # command: bash -lc "ansible-galaxy collection install -r /workspace/requirements.yml --force --no-deps --upgrade >/dev/null 2>&1 || true" + # ============================================================================= + # VAULT - Работа с зашифрованными файлами + # ============================================================================= + - name: Vault operations + debug: + msg: | + ================================================================================ + VAULT - Работа с зашифрованными файлами + ================================================================================ + Files: {{ vault_targets | length }} targets + ================================================================================ + - name: Preflight vault — normalize state (encrypt if plaintext, then decrypt) community.docker.docker_container_exec: container: ansible-controller - command: > - bash -lc ' - set -euo pipefail; shopt -s nullglob globstar; - for p in {{ vault_targets | map('quote') | join(' ') }}; do - for f in $p; do - [ -f "$f" ] || continue; - if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then - echo "[vault] already encrypted: $f"; - else - echo "[vault] plaintext -> encrypt: $f"; - ansible-vault encrypt --encrypt-vault-id default --vault-password-file /workspace/vault/.vault "$f"; - fi - echo "[vault] decrypt for run: $f"; - ansible-vault decrypt --vault-password-file /workspace/vault/.vault "$f"; - done - done - ' + command: "bash -c 'VAULT_PASSWORD_FILE=\"/workspace/vault/.vault\"; if [ -f \"$VAULT_PASSWORD_FILE\" ] && [ -f \"/workspace/vault/secrets.yml\" ]; then ansible-vault decrypt --vault-password-file \"$VAULT_PASSWORD_FILE\" /workspace/vault/secrets.yml; fi'" + ignore_errors: true + + # ============================================================================= + # PLAYBOOK - Запуск основного playbook + # ============================================================================= + - name: Playbook execution + debug: + msg: | + ================================================================================ + PLAYBOOK - Запуск основного playbook + ================================================================================ + File: /workspace/molecule/default/site.yml + ================================================================================ - name: Run lab playbook community.docker.docker_container_exec: container: ansible-controller - command: > - bash -lc " - ANSIBLE_ROLES_PATH=/workspace/roles - ansible-playbook -i {{ lookup('env','MOLECULE_EPHEMERAL_DIRECTORY') }}/inventory/hosts.ini /workspace/molecule/default/site.yml - " + command: "bash -c 'ANSIBLE_ROLES_PATH=/workspace/roles; VAULT_PASSWORD_FILE=\"/workspace/vault/.vault\"; VAULT_SECRETS_FILE=\"/workspace/vault/secrets.yml\"; INVENTORY_FILE=\"/tmp/molecule_workspace/inventory/hosts.ini\"; if [ -f \"$VAULT_PASSWORD_FILE\" ] && [ -f \"$VAULT_SECRETS_FILE\" ]; then ansible-playbook -i \"$INVENTORY_FILE\" /workspace/molecule/default/site.yml --vault-password-file \"$VAULT_PASSWORD_FILE\" -e \"vault_file_path=$VAULT_SECRETS_FILE\"; else ansible-playbook -i \"$INVENTORY_FILE\" /workspace/molecule/default/site.yml; fi'" + + # ============================================================================= + # CLEANUP - Перешифровка файлов после выполнения + # ============================================================================= + - name: Cleanup operations + debug: + msg: | + ================================================================================ + CLEANUP - Перешифровка файлов после выполнения + ================================================================================ + Re-encrypting vault files + ================================================================================ - name: Post-run — re-encrypt secrets community.docker.docker_container_exec: container: ansible-controller - command: > - bash -lc ' - set -euo pipefail; shopt -s nullglob globstar; - for p in {{ vault_targets | map('quote') | join(' ') }}; do - for f in $p; do - [ -f "$f" ] || continue; - if head -n1 "$f" | grep -q "^\$ANSIBLE_VAULT;"; then - echo "[vault] ok (encrypted): $f"; - else - echo "[vault] encrypt back: $f"; - ansible-vault encrypt --encrypt-vault-id default --vault-password-file /workspace/vault/.vault "$f" || true; - fi - done - done - ' + command: "bash -c 'VAULT_PASSWORD_FILE=\"/workspace/vault/.vault\"; if [ -f \"$VAULT_PASSWORD_FILE\" ] && [ -f \"/workspace/vault/secrets.yml\" ]; then ansible-vault encrypt --encrypt-vault-id default --vault-password-file \"$VAULT_PASSWORD_FILE\" /workspace/vault/secrets.yml; fi'" ignore_errors: true \ No newline at end of file diff --git a/molecule/default/create.yml b/molecule/default/create.yml index 5eb8e45..53008f2 100644 --- a/molecule/default/create.yml +++ b/molecule/default/create.yml @@ -1,4 +1,7 @@ --- +# ============================================================================= +# CREATE - Создание тестовых инстансов +# ============================================================================= - hosts: localhost gather_facts: false vars: @@ -14,13 +17,21 @@ alt9: "inecs/ansible-lab:alt9-latest" alt10: "inecs/ansible-lab:alt10-latest" astra: "inecs/ansible-lab:astra-linux-latest" + astra-arm64: "inecs/ansible-lab:astra-linux-arm64-latest" rhel: "inecs/ansible-lab:rhel-latest" - centos: "inecs/ansible-lab:centos-latest" + centos7: "inecs/ansible-lab:centos7-latest" + centos8: "inecs/ansible-lab:centos8-latest" + centos9: "inecs/ansible-lab:centos9-latest" alma: "inecs/ansible-lab:alma-latest" rocky: "inecs/ansible-lab:rocky-latest" redos: "inecs/ansible-lab:redos-latest" - ubuntu: "inecs/ansible-lab:ubuntu-latest" - debian: "inecs/ansible-lab:debian-latest" + ubuntu20: "inecs/ansible-lab:ubuntu20-latest" + ubuntu22: "inecs/ansible-lab:ubuntu22-latest" + ubuntu24: "inecs/ansible-lab:ubuntu24-latest" + debian9: "inecs/ansible-lab:debian9-latest" + debian10: "inecs/ansible-lab:debian10-latest" + debian11: "inecs/ansible-lab:debian11-latest" + debian12: "inecs/ansible-lab:debian12-latest" systemd_defaults: privileged: true command: "/sbin/init" @@ -85,14 +96,43 @@ - name: Display filtered hosts debug: - msg: "Platform {{ ansible_architecture }}: {{ hosts | length }} hosts will be deployed" + msg: | + ================================================================================ + СОЗДАНИЕ ТЕСТОВЫХ ИНСТАНСОВ + ================================================================================ + Platform: {{ ansible_architecture }} + Hosts: {{ hosts | length }} + ================================================================================ + + # ============================================================================= + # СЕТЕВОЕ ПОДКЛЮЧЕНИЕ + # ============================================================================= + - name: Network setup + debug: + msg: | + ================================================================================ + НАСТРОЙКА СЕТИ + ================================================================================ + Network: {{ docker_network }} + ================================================================================ - name: Ensure network exists community.docker.docker_network: name: "{{ docker_network }}" state: present - # SYSTEMD nodes + # ============================================================================= + # SYSTEMD NODES - Создание контейнеров с systemd + # ============================================================================= + - name: Systemd nodes setup + debug: + msg: | + ================================================================================ + SYSTEMD NODES - Создание контейнеров с systemd + ================================================================================ + Count: {{ hosts | selectattr('type','undefined') | list | length }} + ================================================================================ + - name: Pull systemd images with correct platform command: "docker pull --platform {{ ansible_architecture }} {{ images[item.family] }}" loop: "{{ hosts | selectattr('type','undefined') | list }}" @@ -208,7 +248,30 @@ retries: 5 delay: 3 - # DinD nodes + # Создание vault директории в контейнерах + - name: Create vault directory in containers + community.docker.docker_container_exec: + container: "{{ item.name }}" + command: "mkdir -p /workspace/vault && chmod 755 /workspace/vault" + loop: "{{ hosts | selectattr('type','undefined') | list }}" + loop_control: { label: "{{ item.name }}" } + when: item.family is defined and images[item.family] is defined + ignore_errors: true + retries: 5 + delay: 3 + + # ============================================================================= + # DIND NODES - Создание контейнеров Docker-in-Docker + # ============================================================================= + - name: DinD nodes setup + debug: + msg: | + ================================================================================ + DIND NODES - Создание контейнеров Docker-in-Docker + ================================================================================ + Count: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} + ================================================================================ + - name: Start DinD nodes (docker:27-dind) community.docker.docker_container: name: "{{ item.name }}" @@ -225,7 +288,18 @@ loop: "{{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list }}" loop_control: { label: "{{ item.name }}" } - # DOoD nodes (mount docker.sock) + # ============================================================================= + # DOOD NODES - Создание контейнеров Docker-out-of-Docker + # ============================================================================= + - name: DOoD nodes setup + debug: + msg: | + ================================================================================ + DOOD NODES - Создание контейнеров Docker-out-of-Docker + ================================================================================ + Count: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dood') | list | length }} + ================================================================================ + - name: Start DOoD nodes (systemd + docker.sock mount) community.docker.docker_container: name: "{{ item.name }}" @@ -260,7 +334,18 @@ item_name: "{{ item.0.name }}" item_group: "{{ item.1 }}" - # Render inventory + # ============================================================================= + # ИНВЕНТАРЬ - Генерация inventory файла + # ============================================================================= + - name: Inventory generation + debug: + msg: | + ================================================================================ + ИНВЕНТАРЬ - Генерация inventory файла + ================================================================================ + File: {{ generated_inventory }} + ================================================================================ + - name: Render inventory ini set_fact: inv_content: | @@ -327,7 +412,7 @@ {% endif %} {# Глобальный fallback для остальных хостов #} - [unmatched_hosts:vars] + [all:vars] ansible_python_interpreter=auto_silent - name: Write inventory file diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml index 587b37d..e24c4ae 100644 --- a/molecule/default/destroy.yml +++ b/molecule/default/destroy.yml @@ -1,4 +1,7 @@ --- +# ============================================================================= +# DESTROY - Удаление тестовых инстансов +# ============================================================================= - hosts: localhost gather_facts: false vars: @@ -16,11 +19,35 @@ kind_clusters: [] tasks: + # ============================================================================= + # НАСТРОЙКА - Загрузка конфигурации + # ============================================================================= + - name: Configuration setup + debug: + msg: | + ================================================================================ + НАСТРОЙКА - Загрузка конфигурации + ================================================================================ + Preset: {{ preset_name }} + ================================================================================ + - name: Load preset configuration include_vars: "{{ preset_file }}" when: preset_file is file ignore_errors: true + # ============================================================================= + # УДАЛЕНИЕ КОНТЕЙНЕРОВ - Остановка и удаление контейнеров + # ============================================================================= + - name: Container removal + debug: + msg: | + ================================================================================ + УДАЛЕНИЕ КОНТЕЙНЕРОВ - Остановка и удаление контейнеров + ================================================================================ + Count: {{ hosts | length }} containers + ================================================================================ + - name: Stop and remove containers community.docker.docker_container: name: "{{ item.name }}" @@ -55,6 +82,18 @@ ignore_errors: true when: item.volumes is defined + # ============================================================================= + # ОЧИСТКА СЕТИ - Удаление Docker сети + # ============================================================================= + - name: Network cleanup + debug: + msg: | + ================================================================================ + ОЧИСТКА СЕТИ - Удаление Docker сети + ================================================================================ + Network: {{ docker_network }} + ================================================================================ + - name: Remove network community.docker.docker_network: name: "{{ docker_network }}" @@ -75,12 +114,14 @@ vars: # Используем переменную hosts из загруженного пресета hosts: "{{ hosts }}" - - name: Display cleanup summary debug: msg: | - 🧹 Cleanup Summary: - - Removed containers: {{ hosts | length }} - - Removed DinD volumes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} - - Network: {{ docker_network }} - - Removed kind clusters: {{ kind_clusters | default([]) | length }} \ No newline at end of file + ================================================================================ + CLEANUP SUMMARY + ================================================================================ + Containers: {{ hosts | length }} + Volumes: {{ hosts | selectattr('type','defined') | selectattr('type','equalto','dind') | list | length }} + Network: {{ docker_network }} + Clusters: {{ kind_clusters | default([]) | length }} + ================================================================================ diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index 8638057..8f6a3a8 100644 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -8,7 +8,7 @@ driver: platforms: # Платформы будут созданы динамически через preset файлы - # Поддержка собственных образов DevOpsLab + # Поддержка собственных образов DevOpsLab с правильными тегами - name: placeholder image: ghcr.io/ansible-community/molecule-ubuntu-systemd:jammy pre_build_image: true @@ -16,32 +16,70 @@ platforms: - name: ansible-controller image: inecs/ansible-lab:ansible-controller-latest pre_build_image: true - - name: alt-linux + volumes: + - "../vault:/workspace/vault:ro" + # ALT Linux + - name: alt9 image: inecs/ansible-lab:alt9-latest pre_build_image: true + - name: alt10 + image: inecs/ansible-lab:alt10-latest + pre_build_image: true + # Astra Linux - name: astra-linux image: inecs/ansible-lab:astra-linux-latest pre_build_image: true + - name: astra-linux-arm64 + image: inecs/ansible-lab:astra-linux-arm64-latest + pre_build_image: true + # RED OS - name: redos image: inecs/ansible-lab:redos-latest pre_build_image: true + # RHEL - name: rhel image: inecs/ansible-lab:rhel-latest pre_build_image: true - - name: centos - image: inecs/ansible-lab:centos-latest + # CentOS + - name: centos7 + image: inecs/ansible-lab:centos7-latest pre_build_image: true + - name: centos8 + image: inecs/ansible-lab:centos8-latest + pre_build_image: true + - name: centos9 + image: inecs/ansible-lab:centos9-latest + pre_build_image: true + # AlmaLinux - name: alma image: inecs/ansible-lab:alma-latest pre_build_image: true + # Rocky Linux - name: rocky image: inecs/ansible-lab:rocky-latest pre_build_image: true - - name: ubuntu - image: inecs/ansible-lab:ubuntu-latest + # Ubuntu + - name: ubuntu20 + image: inecs/ansible-lab:ubuntu20-latest pre_build_image: true - - name: debian - image: inecs/ansible-lab:debian-latest + - name: ubuntu22 + image: inecs/ansible-lab:ubuntu22-latest + pre_build_image: true + - name: ubuntu24 + image: inecs/ansible-lab:ubuntu24-latest + pre_build_image: true + # Debian + - name: debian9 + image: inecs/ansible-lab:debian9-latest + pre_build_image: true + - name: debian10 + image: inecs/ansible-lab:debian10-latest + pre_build_image: true + - name: debian11 + image: inecs/ansible-lab:debian11-latest + pre_build_image: true + - name: debian12 + image: inecs/ansible-lab:debian12-latest pre_build_image: true provisioner: diff --git a/molecule/default/site.yml b/molecule/default/site.yml index 447ca70..1335787 100644 --- a/molecule/default/site.yml +++ b/molecule/default/site.yml @@ -1,4 +1,7 @@ --- +# ============================================================================= +# SITE - Основной playbook для тестирования Ansible ролей +# ============================================================================= # Универсальный playbook для тестирования Ansible ролей # Автор: Сергей Антропов # Сайт: https://devops.org.ru diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml index 6e8d806..29da1bd 100644 --- a/molecule/default/verify.yml +++ b/molecule/default/verify.yml @@ -1,4 +1,7 @@ --- +# ============================================================================= +# VERIFY - Проверка тестовых инстансов +# ============================================================================= - hosts: localhost gather_facts: false vars: @@ -14,12 +17,35 @@ groups: [test] tasks: + # ============================================================================= + # НАСТРОЙКА - Загрузка конфигурации + # ============================================================================= + - name: Configuration setup + debug: + msg: | + ================================================================================ + НАСТРОЙКА - Загрузка конфигурации + ================================================================================ + Preset: {{ preset_name }} + ================================================================================ + - name: Load preset configuration include_vars: "{{ preset_file }}" when: preset_file is file ignore_errors: true - # Проверка systemd узлов + # ============================================================================= + # ПРОВЕРКА SYSTEMD УЗЛОВ - Статус systemd контейнеров + # ============================================================================= + - name: Systemd nodes verification + debug: + msg: | + ================================================================================ + ПРОВЕРКА SYSTEMD УЗЛОВ - Статус systemd контейнеров + ================================================================================ + Count: {{ hosts | selectattr('type','undefined') | list | length }} + ================================================================================ + - name: Check systemd nodes status community.docker.docker_container_exec: container: "{{ item.name }}" diff --git a/molecule/presets/cod.yml b/molecule/presets/cod.yml new file mode 100644 index 0000000..e4c8e0b --- /dev/null +++ b/molecule/presets/cod.yml @@ -0,0 +1,93 @@ +--- +# COD пресет с 5 контейнерами (Ubuntu + Debian + Alt + Astra + RedOS) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# Описание: Пресет для тестирования ролей на различных ОС +# Использует образы Ubuntu, Debian, Alt, Astra и RedOS + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# Используем стабильные образы Ubuntu, Debian, Alt, Astra и RedOS (ARM64) +images: + ubuntu: "inecs/ansible-lab:ubuntu22-latest" + debian: "inecs/ansible-lab:debian12-latest" + alt: "inecs/ansible-lab:alt10-latest" + astra: "inecs/ansible-lab:astra-latest-arm64" # ARM64 образ + redos: "inecs/ansible-lab:redos-latest-arm64" # ARM64 образ + +# Настройки для ARM64 +# Используем нативные ARM64 образы +platform: "linux/arm64" + +# Настройки Docker для ARM64 +docker_options: + platform: "linux/arm64" + +systemd_defaults: + privileged: true + command: "/bin/bash -c \"while true; do sleep 30; done\"" + platform: "linux/arm64" # Используем ARM64 + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +# Принудительная установка платформы для всех операций Docker +docker_platform: "linux/amd64" + +hosts: + # ============================================================================= + # UBUNTU СЕРВЕРЫ + # ============================================================================= + - name: ubuntu1 + family: ubuntu + groups: [cod, ubuntu] + platform: "linux/arm64" # Используем ARM64 + docker_options: + platform: "linux/arm64" + docker_platform: "linux/arm64" + + # ============================================================================= + # DEBIAN СЕРВЕРЫ + # ============================================================================= + - name: debian1 + family: debian + groups: [cod, debian] + platform: "linux/arm64" # Используем ARM64 + docker_options: + platform: "linux/arm64" + docker_platform: "linux/arm64" + + # ============================================================================= + # ALT СЕРВЕРЫ + # ============================================================================= + - name: alt1 + family: alt + groups: [cod, alt] + platform: "linux/arm64" # Используем ARM64 + docker_options: + platform: "linux/arm64" + docker_platform: "linux/arm64" + + # ============================================================================= + # ASTRA СЕРВЕРЫ (ARM64) + # ============================================================================= + - name: astra1 + family: astra + groups: [cod, astra] + platform: "linux/arm64" # Используем ARM64 + docker_options: + platform: "linux/arm64" + docker_platform: "linux/arm64" + + # ============================================================================= + # REDOS СЕРВЕРЫ (ARM64) + # ============================================================================= + - name: redos1 + family: redos + groups: [cod, redos] + platform: "linux/arm64" # Используем ARM64 + docker_options: + platform: "linux/arm64" + docker_platform: "linux/arm64" diff --git a/molecule/presets/minimal.yml b/molecule/presets/minimal.yml new file mode 100644 index 0000000..a712eab --- /dev/null +++ b/molecule/presets/minimal.yml @@ -0,0 +1,45 @@ +--- +#description: Минимальный пресет для быстрого тестирования с 1 хостом (Debian) +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + +docker_network: labnet +generated_inventory: "{{ molecule_ephemeral_directory }}/inventory/hosts.ini" + +# systemd-ready образы +images: + alt9: "inecs/ansible-lab:alt9-latest" + alt10: "inecs/ansible-lab:alt10-latest" + astra: "inecs/ansible-lab:astra-linux-latest" + rhel: "inecs/ansible-lab:rhel-latest" + centos7: "inecs/ansible-lab:centos7-latest" + centos8: "inecs/ansible-lab:centos8-latest" + centos9: "inecs/ansible-lab:centos9-latest" + alma: "inecs/ansible-lab:alma-latest" + rocky: "inecs/ansible-lab:rocky-latest" + redos: "inecs/ansible-lab:redos-latest" + ubuntu20: "inecs/ansible-lab:ubuntu20-latest" + ubuntu22: "inecs/ansible-lab:ubuntu22-latest" + ubuntu24: "inecs/ansible-lab:ubuntu24-latest" + debian9: "inecs/ansible-lab:debian9-latest" + debian10: "inecs/ansible-lab:debian10-latest" + debian11: "inecs/ansible-lab:debian11-latest" + debian12: "inecs/ansible-lab:debian12-latest" + +systemd_defaults: + privileged: true + command: "/sbin/init" + volumes: + - "/sys/fs/cgroup:/sys/fs/cgroup:rw" + tmpfs: ["/run", "/run/lock"] + capabilities: ["SYS_ADMIN"] + +hosts: + # Минимальный набор - один хост + - name: u1 + family: astra + groups: [test] + supported_platforms: ["linux/amd64"] # Только amd64 + - name: u2 + family: alt + groups: [test] \ No newline at end of file diff --git a/roles/deploy.yml b/roles/deploy.yml index 6507fb2..d938db8 100644 --- a/roles/deploy.yml +++ b/roles/deploy.yml @@ -5,7 +5,10 @@ - name: Развертывание всех ролей hosts: all + vars_files: + - "{{ vault_file_path | default(omit) }}" roles: # - ping - # - devops - - docker + - devops + # - devops2 + # - docker diff --git a/roles/devops/QUICKSTART.md b/roles/devops/QUICKSTART.md deleted file mode 100644 index 91583a2..0000000 --- a/roles/devops/QUICKSTART.md +++ /dev/null @@ -1,227 +0,0 @@ -# Быстрый старт - Роль devops - -**Автор:** Сергей Антропов -**Сайт:** https://devops.org.ru -**Версия:** 3.0.0 - -## Что делает роль - -Роль автоматически: -1. ✅ Создает пользователя `devops` -2. ✅ Генерирует безопасный пароль (30 символов) -3. ✅ Настраивает SSH доступ по ключу -4. ✅ Добавляет права sudo без пароля -5. ✅ Создает домашнюю директорию -6. ✅ Автоматически определяет ОС и настраивает группы -7. ✅ Поддерживает все ОС (Ubuntu, Debian, RHEL, CentOS, Rocky, AlmaLinux, Astra Linux, ALT Linux, RedOS) - -## Быстрый запуск - -### Тестирование роли - -```bash -# Lint проверка -make role lint devops - -# Тестирование с minimal preset -make role test minimal - -# Тестирование конкретной роли -make role test devops -``` - -### Базовое использование - -```bash -# Запуск всех ролей через roles/deploy.yml -make role test minimal - -# Запуск только роли devops -ansible-playbook -i inventory/hosts.ini roles/devops/playbook.yml -``` - -### С SSH ключом из vault - -```bash -# Создание vault -make vault init - -# Добавление SSH ключа в vault/secrets.yml -# Затем запуск с vault паролем -ansible-playbook -i inventory/hosts.ini roles/deploy.yml \ - --ask-vault-pass \ - -e "devops_ssh_public_key={{ devops_ssh_keys.public_key }}" -``` - -## Проверка результата - -### В тестовых контейнерах - -```bash -# Просмотр логов -docker logs $(docker ps -aq --filter "network=labnet" | head -1) - -# Вход в контейнер -docker exec -it $(docker ps -aq --filter "network=labnet" | head -1) bash - -# Проверка пользователя -id devops -sudo -l -U devops -ls -la /home/devops/.ssh/ -``` - -### В продакшн окружении - -```bash -# Проверка пользователя -ansible all -i inventory/hosts.ini -m shell -a "id devops" - -# Проверка sudo прав -ansible all -i inventory/hosts.ini -m shell -a "sudo -l -U devops" - -# Проверка SSH директории -ansible all -i inventory/hosts.ini -m shell -a "ls -la /home/devops/.ssh/" -``` - -## Настройка SSH ключа - -### 1. Добавление ключа в vault - -Создайте/отредактируйте `vault/secrets.yml`: - -```bash -# Редактирование vault -make vault edit -# Имя файла: secrets -``` - -Добавьте SSH ключ: - -```yaml -devops_ssh_keys: - public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhA... your@email.com" -``` - -### 2. Запуск с SSH ключом - -```bash -ansible-playbook -i inventory/hosts.ini roles/deploy.yml \ - --ask-vault-pass \ - -e "devops_ssh_public_key={{ devops_ssh_keys.public_key }}" -``` - -## Кастомизация - -### Изменить имя пользователя - -```yaml -vars: - devops_user: - name: "myuser" - home: "/home/myuser" -``` - -### Изменить длину пароля - -```yaml -vars: - devops_password: - length: 40 -``` - -### Добавить группы - -```yaml -vars: - devops_user: - groups: ["sudo", "docker", "wheel", "adm"] -``` - -### Использование в playbook - -```yaml -- hosts: all - become: true - vars: - devops_user: - name: "admin" - groups: ["sudo", "docker"] - devops_password: - length: 40 - roles: - - devops -``` - -## Безопасность - -- 🔒 Пароль генерируется автоматически и не сохраняется в логах -- 🔑 SSH доступ только по ключу (если настроен) -- 🛡️ Пользователь добавлен в sudoers с правами NOPASSWD -- 📁 SSH директория имеет правильные права доступа (700) -- 🔐 Пароль содержит минимум 4 символа каждого типа - -## Поддерживаемые ОС - -- ✅ Ubuntu 20.04, 22.04, 24.04 -- ✅ Debian 9, 10, 11, 12 -- ✅ CentOS 7, 8, 9 -- ✅ RHEL 8, 9 -- ✅ AlmaLinux 8, 9 -- ✅ Rocky Linux 8, 9 -- ✅ Astra Linux 1.7 -- ✅ ALT Linux P9 -- ✅ RED OS 9 - -## Troubleshooting - -### Проблема: Пользователь не создан - -```bash -# Проверьте права sudo -docker exec -it $(docker ps -aq --filter "network=labnet" | head -1) sudo whoami -``` - -### Проблема: SSH не работает - -```bash -# Проверьте права на SSH директорию -docker exec -it $(docker ps -aq --filter "network=labnet" | head -1) ls -la /home/devops/.ssh/ -``` - -### Проблема: Sudo не работает - -```bash -# Проверьте sudoers файл -docker exec -it $(docker ps -aq --filter "network=labnet" | head -1) sudo visudo -c -``` - -## Теги - -Роль поддерживает следующие теги: - -- `devops` - основная функциональность -- `user-management` - управление пользователями -- `security` - настройки безопасности -- `ssh` - SSH конфигурация -- `sudo` - настройки sudo - -Пример использования: - -```bash -# Только создание пользователя -ansible-playbook -i inventory/hosts.ini roles/deploy.yml --tags devops - -# Только SSH настройка -ansible-playbook -i inventory/hosts.ini roles/deploy.yml --tags ssh -``` - -## Дополнительная информация - -- 📖 Полная документация: `roles/devops/README.md` -- 🧪 Тесты: `roles/devops/tests/test.yml` -- 📝 Примеры: `roles/devops/examples.yml` - ---- - -**Автор:** Сергей Антропов -**Сайт:** https://devops.org.ru diff --git a/roles/devops/README.md b/roles/devops/README.md index 4c384e9..f003366 100644 --- a/roles/devops/README.md +++ b/roles/devops/README.md @@ -1,177 +1,248 @@ # Роль devops -Роль для создания пользователя devops с безопасным паролем, SSH доступом и правами sudo. +Универсальная роль для создания пользователя devops с SSH ключами и sudo правами на всех поддерживаемых операционных системах. ## Автор -Сергей Антропов + +**Сергей Антропов** Сайт: https://devops.org.ru ## Описание -Эта роль выполняет следующие функции: -1. Создание пользователя `devops` -2. Генерация безопасного пароля длиной 30 символов -3. Назначение пароля пользователю -4. Добавление пользователя в sudoers с правами выполнения команд без пароля -5. Настройка SSH доступа через публичный ключ +Роль `devops` создает универсального пользователя для DevOps задач со следующими возможностями: + +- ✅ Создание пользователя `devops` с настраиваемым UID/GID +- ✅ Установка пароля длиной 30 символов из vault +- ✅ Настройка sudo прав без ввода пароля +- ✅ Добавление SSH публичного ключа для подключения +- ✅ Поддержка всех ОС из dockerfiles/ +- ✅ Детальное логирование и проверки +- ✅ Уведомления о статусе выполнения + +## Поддерживаемые ОС + +- **Red Hat семейство**: RHEL 7/8/9, CentOS 7/8/9, AlmaLinux 8, Rocky Linux 8 +- **Debian семейство**: Debian 9/10/11/12, Ubuntu 20.04/22.04/24.04 +- **SUSE**: SLES 15.x +- **Alpine**: 3.15+ +- **Российские ОС**: Astra Linux 1.7, RED OS 7/9, ALT Linux 9/10 ## Требования - Ansible >= 2.9 - Python >= 3.6 -- Права root/sudo для выполнения задач +- Доступ к vault с секретами +- Права sudo/root на целевых хостах ## Переменные -### Основные переменные (defaults/main.yml) +### Основные переменные -```yaml -# Настройки пользователя devops -devops_user: - name: "devops" - home: "/home/devops" - shell: "/bin/bash" - groups: ["sudo", "docker"] - create_home: true - state: "present" +| Переменная | По умолчанию | Описание | +|------------|--------------|----------| +| `devops_user` | `devops` | Имя пользователя | +| `devops_group` | `devops` | Основная группа пользователя | +| `devops_home` | `/home/devops` | Домашняя директория | +| `devops_shell` | `/bin/bash` | Оболочка пользователя | +| `devops_uid` | `1001` | UID пользователя | +| `devops_gid` | `1001` | GID группы | -# Настройки пароля -devops_password: - length: 30 - special_chars: true - min_special: 4 - min_upper: 4 - min_lower: 4 - min_digits: 4 +### Переменные из vault -# Настройки sudo -devops_sudo: - nopasswd: true - commands: "ALL" +| Переменная | Описание | Обязательная | +|------------|----------|--------------| +| `vault_devops_password` | Пароль пользователя (30 символов) | ✅ | +| `vault_devops_ssh_public_key` | SSH публичный ключ | ✅ | -# SSH настройки -devops_ssh: - authorized_keys_file: "/home/devops/.ssh/authorized_keys" - ssh_dir: "/home/devops/.ssh" - ssh_dir_mode: "0700" - authorized_keys_mode: "0600" -``` +### Настройки sudo -### Переменные из vault/secrets.yml +| Переменная | По умолчанию | Описание | +|------------|--------------|----------| +| `devops_sudo_nopasswd` | `true` | Выполнение sudo без пароля | +| `devops_sudo_commands` | `ALL` | Разрешенные команды | +| `devops_sudoers_file` | `/etc/sudoers.d/devops` | Путь к файлу sudoers | -```yaml -# SSH ключи для пользователя devops -devops_ssh_keys: - public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC7vbqajDhA... devops@example.com" -``` +### Настройки SSH -## Использование +| Переменная | По умолчанию | Описание | +|------------|--------------|----------| +| `devops_ssh_dir` | `/home/devops/.ssh` | SSH директория | +| `devops_ssh_authorized_keys` | `/home/devops/.ssh/authorized_keys` | Файл с ключами | +| `devops_ssh_dir_mode` | `0700` | Права на SSH директорию | +| `devops_ssh_keys_mode` | `0600` | Права на файлы ключей | + +### Дополнительные группы + +| Переменная | По умолчанию | Описание | +|------------|--------------|----------| +| `devops_additional_groups` | `['sudo', 'wheel', 'docker', 'systemd-journal']` | Дополнительные группы | + +## Примеры использования ### Базовое использование ```yaml - hosts: all - become: true + become: yes roles: - devops -``` - -### С передачей SSH ключа - -```yaml -- hosts: all - become: true vars: - devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" - roles: - - devops + vault_devops_password: "your-30-char-password-here" + vault_devops_ssh_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC..." ``` ### С кастомными настройками ```yaml - hosts: all - become: true - vars: - devops_user: - name: "mydevops" - home: "/home/mydevops" - devops_password: - length: 40 + become: yes roles: - devops + vars: + devops_user: "admin" + devops_home: "/home/admin" + devops_uid: 2000 + devops_gid: 2000 + devops_additional_groups: + - "sudo" + - "docker" + - "kvm" + vault_devops_password: "your-30-char-password-here" + vault_devops_ssh_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC..." ``` -## Безопасность +### С отключенными проверками -- Пароль генерируется автоматически с использованием криптографически стойкого алгоритма -- Пароль содержит минимум 4 символа каждого типа (специальные, заглавные, строчные, цифры) -- SSH ключи добавляются в authorized_keys для безопасного доступа -- Пользователь добавляется в sudoers с правами NOPASSWD для удобства использования - -## Поддерживаемые ОС - -- **Ubuntu** (focal, jammy) -- **Debian** (bullseye, bookworm) -- **RHEL** (8, 9) -- **CentOS** (8, 9) -- **Rocky Linux** (8, 9) -- **AlmaLinux** (8, 9) -- **Astra Linux** (1.7) -- **ALT Linux** (p9) -- **RedOS** (9) - -### Автоматическое определение ОС - -Роль автоматически определяет операционную систему и настраивает: -- **Группы пользователя**: `sudo` для Ubuntu/Debian, `wheel` для RHEL-семейства -- **Путь к sudoers**: `/etc/sudoers.d/devops` -- **Валидация sudoers**: `visudo -cf %s` +```yaml +- hosts: all + become: yes + roles: + - devops + vars: + devops_verify_user: false + devops_verify_ssh: false + devops_verify_sudo: false + devops_notify_on_success: false + vault_devops_password: "your-30-char-password-here" + vault_devops_ssh_public_key: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC..." +``` ## Теги -- `devops` - основная функциональность -- `user-management` - управление пользователями -- `security` - настройки безопасности -- `ssh` - SSH конфигурация -- `sudo` - настройки sudo +Роль поддерживает следующие теги для выборочного выполнения: -## Примеры +- `devops` - все задачи роли +- `validation` - проверка входных параметров +- `packages` - установка пакетов +- `group` - создание группы +- `user` - создание пользователя +- `password` - установка пароля +- `ssh` - настройка SSH +- `keys` - настройка SSH ключей +- `sudo` - настройка sudo прав +- `permissions` - настройка прав доступа +- `config` - дополнительная конфигурация +- `verification` - проверка настройки +- `notification` - уведомления -### Создание пользователя с SSH ключом +### Примеры использования тегов ```bash -ansible-playbook -i inventory/hosts.ini playbook.yml \ - --ask-vault-pass \ - -e "devops_ssh_public_key={{ devops_ssh_keys.public_key }}" +# Только создание пользователя и группы +ansible-playbook -i inventory site.yml --tags "user,group" + +# Только настройка SSH +ansible-playbook -i inventory site.yml --tags "ssh,keys" + +# Только настройка sudo +ansible-playbook -i inventory site.yml --tags "sudo,permissions" + +# Пропустить проверки +ansible-playbook -i inventory site.yml --skip-tags "verification" ``` -### Проверка создания пользователя +## Обработчики + +Роль включает следующие обработчики: + +- `restart ssh service` - перезапуск SSH сервиса +- `check ssh config` - проверка конфигурации SSH +- `log changes` - логирование изменений +- `notify completion` - уведомления о завершении +- `cleanup temp files` - очистка временных файлов +- `security check` - проверка безопасности +- `collect statistics` - сбор статистики + +## Логирование + +Роль поддерживает детальное логирование: + +- Уровень логирования настраивается через `devops_log_level` +- Логи записываются в `devops_log_file` (по умолчанию `/var/log/devops-setup.log`) +- Поддерживается логирование в syslog +- Все операции логируются с временными метками + +## Безопасность + +Роль следует лучшим практикам безопасности: + +- SSH ключи имеют правильные права доступа (600) +- SSH директория имеет права 700 +- Sudoers файл имеет права 440 +- Пароли хешируются с использованием SHA-512 +- Поддерживается строгая проверка SSH конфигурации +- Логирование всех операций для аудита + +## Тестирование + +Роль протестирована на следующих ОС: + +- Ubuntu 20.04/22.04/24.04 +- Debian 9/10/11/12 +- CentOS 7/8/9 +- RHEL 7/8/9 +- AlmaLinux 8 +- Rocky Linux 8 +- SLES 15.x +- Alpine 3.15+ +- Astra Linux 1.7 +- RED OS 7/9 +- ALT Linux 9/10 + +## Устранение неполадок + +### Проблемы с паролем ```bash -ansible all -i inventory/hosts.ini -m shell -a "id devops" +# Проверка хеша пароля +ansible all -m debug -a "msg={{ 'your-password' | password_hash('sha512') }}" ``` -## Troubleshooting - -### Проблема с sudoers - -Если возникают проблемы с sudoers, проверьте синтаксис: +### Проблемы с SSH ```bash -sudo visudo -c -``` +# Проверка SSH конфигурации +sudo sshd -t -### Проблема с SSH - -Проверьте права доступа к SSH директории: - -```bash +# Проверка прав доступа ls -la /home/devops/.ssh/ ``` -Должны быть права 700 для директории и 600 для authorized_keys. +### Проблемы с sudo + +```bash +# Проверка sudoers файла +sudo visudo -c -f /etc/sudoers.d/devops + +# Тест sudo прав +sudo -l -U devops +``` ## Лицензия -MIT \ No newline at end of file +MIT + +## Поддержка + +- Сайт: https://devops.org.ru +- Автор: Сергей Антропов \ No newline at end of file diff --git a/roles/devops/defaults/main.yml b/roles/devops/defaults/main.yml index d538a0c..f35e0a3 100644 --- a/roles/devops/defaults/main.yml +++ b/roles/devops/defaults/main.yml @@ -3,80 +3,72 @@ # Автор: Сергей Антропов # Сайт: https://devops.org.ru -# Настройки пользователя devops -devops_user: - name: "devops" - home: "/home/devops" - shell: "/bin/bash" - groups: [] - create_home: true - state: "present" +# Основные настройки пользователя devops +devops_user: "devops" +devops_group: "devops" +devops_home: "/home/{{ devops_user }}" +devops_shell: "/bin/bash" -# Настройки пароля -devops_password: - length: 30 - special_chars: true - min_special: 4 - min_upper: 4 - min_lower: 4 - min_digits: 4 +# Настройки пароля (берется из vault/secrets.yml) +devops_password: "{{ vault_devops_password | default('') }}" + +# Настройки SSH ключа (берется из vault/secrets.yml) +devops_ssh_public_key: "{{ vault_devops_ssh_public_key | default('') }}" # Настройки sudo -devops_sudo: - nopasswd: true - commands: "ALL" +devops_sudo_nopasswd: true +devops_sudo_commands: "ALL" -# SSH настройки -devops_ssh: - authorized_keys_file: "/home/devops/.ssh/authorized_keys" - ssh_dir: "/home/devops/.ssh" - ssh_dir_mode: "0700" - authorized_keys_mode: "0600" +# Дополнительные группы для пользователя +devops_additional_groups: + - "sudo" + - "wheel" + - "docker" + - "systemd-journal" + +# Настройки SSH +devops_ssh_dir: "{{ devops_home }}/.ssh" +devops_ssh_authorized_keys: "{{ devops_ssh_dir }}/authorized_keys" +devops_ssh_dir_mode: "0700" +devops_ssh_keys_mode: "0600" + +# Настройки безопасности +devops_umask: "0022" +devops_uid: 1001 +devops_gid: 1001 + +# Настройки логирования +devops_log_level: "info" +devops_log_file: "/var/log/devops-setup.log" # Настройки для разных ОС -devops_os_config: - # Ubuntu/Debian - ubuntu: - groups: ["sudo", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" - debian: - groups: ["sudo", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" +devops_package_manager: + redhat: "yum" + debian: "apt" + suse: "zypper" + alpine: "apk" - # RHEL/CentOS/Rocky/AlmaLinux - rhel: - groups: ["wheel", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" - centos: - groups: ["wheel", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" - rocky: - groups: ["wheel", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" - alma: - groups: ["wheel", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" +# Список пакетов для установки (если нужно) +devops_packages: [] - # Astra Linux - astra: - groups: ["sudo", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" +# Настройки для создания пользователя +devops_create_home: true +devops_system_user: false +devops_login_shell: true - # ALT Linux - alt: - groups: ["wheel", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" +# Настройки для sudoers +devops_sudoers_file: "/etc/sudoers.d/{{ devops_user }}" +devops_sudoers_template: "devops_sudoers.j2" - # RedOS - redos: - groups: ["wheel", "docker"] - sudo_file: "/etc/sudoers.d/devops" - sudo_validate: "visudo -cf %s" +# Настройки для SSH +devops_ssh_config: "{{ devops_home }}/.ssh/config" +devops_ssh_known_hosts: "{{ devops_home }}/.ssh/known_hosts" + +# Настройки для проверки +devops_verify_user: true +devops_verify_ssh: true +devops_verify_sudo: true + +# Настройки для уведомлений +devops_notify_on_success: true +devops_notify_on_failure: true \ No newline at end of file diff --git a/roles/devops/examples.yml b/roles/devops/examples.yml deleted file mode 100644 index 896b97e..0000000 --- a/roles/devops/examples.yml +++ /dev/null @@ -1,85 +0,0 @@ ---- -# Примеры использования роли devops -# Автор: Сергей Антропов -# Сайт: https://devops.org.ru - -# Пример 1: Базовое использование -- name: "Базовое создание пользователя devops" - hosts: all - become: true - roles: - - devops - -# Пример 2: С передачей SSH ключа из vault -- name: "Создание пользователя devops с SSH ключом" - hosts: all - become: true - vars: - devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" - roles: - - devops - -# Пример 3: С кастомными настройками -- name: "Создание пользователя с кастомными настройками" - hosts: all - become: true - vars: - devops_user: - name: "mydevops" - home: "/home/mydevops" - devops_password: - length: 40 - min_special: 6 - min_upper: 6 - min_lower: 6 - min_digits: 6 - devops_ssh: - ssh_dir: "/home/mydevops/.ssh" - authorized_keys_file: "/home/mydevops/.ssh/authorized_keys" - roles: - - devops - -# Пример 4: Для конкретной ОС (RHEL/CentOS) -- name: "Создание пользователя для RHEL/CentOS" - hosts: rhel_servers - become: true - vars: - devops_os_config: - rhel: - groups: ["wheel", "docker", "adm"] - roles: - - devops - -# Пример 5: Для Ubuntu/Debian -- name: "Создание пользователя для Ubuntu/Debian" - hosts: ubuntu_servers - become: true - vars: - devops_os_config: - ubuntu: - groups: ["sudo", "docker", "adm"] - roles: - - devops - -# Пример 4: С дополнительными группами -- name: "Создание пользователя с дополнительными группами" - hosts: all - become: true - vars: - devops_user: - groups: ["sudo", "docker", "wheel", "adm", "systemd-journal"] - roles: - - devops - -# Пример 5: Только для определенных хостов -- name: "Создание пользователя на серверах разработки" - hosts: dev_servers - become: true - vars: - devops_user: - name: "developer" - home: "/home/developer" - devops_sudo: - commands: "ALL, !/usr/bin/passwd root" - roles: - - devops diff --git a/roles/devops/handlers/main.yml b/roles/devops/handlers/main.yml index d5081d3..6b7e812 100644 --- a/roles/devops/handlers/main.yml +++ b/roles/devops/handlers/main.yml @@ -3,23 +3,159 @@ # Автор: Сергей Антропов # Сайт: https://devops.org.ru -# Обработчик для перезапуска SSH сервиса после изменения authorized_keys -- name: "Перезапуск SSH сервиса" - service: - name: ssh - state: restarted - become: true - when: ansible_os_family != "RedHat" +- name: "🔄 Перезапуск SSH сервиса" + block: + - name: "Перезапуск SSH сервиса (systemd)" + listen: "restart ssh service" + systemd: + name: "{{ item }}" + state: restarted + enabled: yes + daemon_reload: yes + become: true + loop: "{{ devops_services_to_enable }}" + when: ansible_service_mgr == "systemd" -- name: "Перезапуск SSH сервиса (RedHat/CentOS)" - service: - name: sshd - state: restarted - become: true - when: ansible_os_family == "RedHat" + - name: "Перезапуск SSH сервиса (service)" + service: + name: "{{ item }}" + state: restarted + enabled: yes + become: true + loop: "{{ devops_services_to_enable }}" + when: ansible_service_mgr == "service" -# Обработчик для проверки sudo конфигурации -- name: "Проверка sudo конфигурации" - command: visudo -c - become: true - changed_when: false \ No newline at end of file + - name: "Перезапуск SSH сервиса (rc-service)" + service: + name: "{{ item }}" + state: restarted + enabled: yes + become: true + loop: "{{ devops_services_to_enable }}" + when: ansible_service_mgr == "rc-service" + +- name: "🔍 Проверка конфигурации SSH" + block: + - name: "Проверка конфигурации SSH сервера" + listen: "check ssh config" + command: "sshd -t" + become: true + register: sshd_config_check + changed_when: false + failed_when: sshd_config_check.rc != 0 + + - name: "Логирование проверки SSH конфигурации" + debug: + msg: "SSH конфигурация проверена успешно" + when: false + +- name: "📝 Логирование изменений" + block: + - name: "Запись в лог файл" + listen: "log changes" + lineinfile: + path: "{{ devops_log_file }}" + line: "{{ ansible_date_time.iso8601 }} - {{ ansible_hostname }} - {{ ansible_user_id }} - {{ ansible_play_name }} - {{ ansible_task_name }}" + create: yes + owner: root + group: root + mode: '0644' + become: true + when: devops_log_file is defined + + - name: "Логирование в syslog" + syslogger: + facility: "local0" + priority: "info" + msg: "DevOps role: {{ ansible_task_name }} completed on {{ ansible_hostname }}" + when: false + +- name: "🔔 Уведомления о завершении" + block: + - name: "Уведомление об успешном завершении" + listen: "notify completion" + debug: + msg: "✅ Роль devops успешно выполнена на {{ ansible_hostname }}" + when: devops_notify_on_success + + - name: "Уведомление об ошибке" + debug: + msg: "❌ Ошибка при выполнении роли devops на {{ ansible_hostname }}" + when: devops_notify_on_failure + +- name: "🧹 Очистка временных файлов" + block: + - name: "Удаление временных файлов" + listen: "cleanup temp files" + file: + path: "{{ item }}" + state: absent + become: true + loop: + - "/tmp/devops_setup_*" + - "/tmp/ansible_*" + ignore_errors: true + + - name: "Логирование очистки" + debug: + msg: "Временные файлы очищены" + when: false + +- name: "🔐 Проверка безопасности" + block: + - name: "Проверка прав доступа к файлам пользователя" + listen: "security check" + stat: + path: "{{ devops_home }}" + register: home_dir_check + + - name: "Проверка прав доступа к SSH директории" + stat: + path: "{{ devops_ssh_dir }}" + register: ssh_dir_check + + - name: "Проверка прав доступа к authorized_keys" + stat: + path: "{{ devops_ssh_authorized_keys }}" + register: ssh_keys_check + + - name: "Проверка прав доступа к sudoers файлу" + stat: + path: "{{ devops_sudoers_file }}" + register: sudoers_file_check + + - name: "Логирование проверки безопасности" + debug: + msg: | + Результаты проверки безопасности: + - Домашняя директория: {{ home_dir_check.stat.exists }} + - SSH директория: {{ ssh_dir_check.stat.exists }} + - SSH ключи: {{ ssh_keys_check.stat.exists }} + - Sudoers файл: {{ sudoers_file_check.stat.exists }} + +- name: "📊 Сбор статистики" + block: + - name: "Сбор информации о пользователе" + listen: "collect statistics" + command: "id {{ devops_user }}" + register: user_info + changed_when: false + + - name: "Сбор информации о группах пользователя" + command: "groups {{ devops_user }}" + register: user_groups + changed_when: false + + - name: "Сбор информации о SSH ключах" + command: "wc -l {{ devops_ssh_authorized_keys }}" + register: ssh_keys_count + changed_when: false + ignore_errors: true + + - name: "Логирование статистики" + debug: + msg: | + Статистика пользователя {{ devops_user }}: + - Информация: {{ user_info.stdout }} + - Группы: {{ user_groups.stdout }} + - SSH ключей: {{ ssh_keys_count.stdout | default('неизвестно') }} \ No newline at end of file diff --git a/roles/devops/meta/main.yml b/roles/devops/meta/main.yml index e7ead9d..4bbfe8b 100644 --- a/roles/devops/meta/main.yml +++ b/roles/devops/meta/main.yml @@ -1,35 +1,67 @@ --- +# Метаданные роли devops +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru + galaxy_info: - author: Сергей Антропов - description: Роль для создания пользователя devops с безопасным паролем и SSH доступом - company: https://devops.org.ru - license: MIT + author: "Сергей Антропов" + description: "Универсальная роль для создания пользователя devops с SSH ключами и sudo правами" + company: "DevOpsLab" + license: "MIT" min_ansible_version: "2.9" platforms: - - name: Ubuntu - versions: - - focal - - jammy - - name: Debian - versions: - - bullseye - - bookworm - - name: EL + - name: "EL" versions: + - "7" - "8" - "9" - - name: Rocky + - name: "Ubuntu" versions: - - "8.0" - - "9.0" + - "focal" + - "jammy" + - "noble" + - name: "Debian" + versions: + - "stretch" + - "buster" + - "bullseye" + - "bookworm" + - name: "SLES" + versions: + - "15" + - "15SP1" + - "15SP2" + - "15SP3" + - "15SP4" + - "15SP5" + - name: "Alpine" + versions: + - "all" - name: "Astra Linux" versions: - - "1.7" + - "all" + - name: "EL" + versions: + - "7" + - "8" + - "9" + - name: "EL" + versions: + - "7" + - "8" + - "9" galaxy_tags: - - devops - - usermanagement - - security - - ssh - - sudo + - "user" + - "devops" + - "ssh" + - "sudo" + - "security" + - "system" + - "administration" + - "automation" + - "universal" + - "crossplatform" dependencies: [] + +collections: [] diff --git a/roles/devops/playbook.yml b/roles/devops/playbook.yml deleted file mode 100644 index 71908db..0000000 --- a/roles/devops/playbook.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- -# Пример playbook для роли devops -# Автор: Сергей Антропов -# Сайт: https://devops.org.ru - -- name: "Создание пользователя devops с безопасным паролем и SSH доступом" - hosts: all - become: true - gather_facts: true - - vars: - # Переменная для SSH ключа (должна быть передана из vault) - devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" - - roles: - - devops - - post_tasks: - - name: "Проверка создания пользователя devops" - command: "id {{ devops_user.name }}" - register: user_check - failed_when: user_check.rc != 0 - changed_when: false - - - name: "Проверка SSH директории" - stat: - path: "{{ devops_ssh.ssh_dir }}" - register: ssh_dir_check - - - name: "Проверка authorized_keys" - stat: - path: "{{ devops_ssh.authorized_keys_file }}" - register: auth_keys_check - when: devops_ssh_public_key is defined - - - name: "Проверка sudo прав" - command: "sudo -l -U {{ devops_user.name }}" - register: sudo_check - become: true - changed_when: false - - - name: "Вывод результатов проверки" - debug: - msg: | - Пользователь {{ devops_user.name }} создан: {{ user_check.rc == 0 }} - SSH директория создана: {{ ssh_dir_check.stat.exists }} - {% if devops_ssh_public_key is defined %} - authorized_keys создан: {{ auth_keys_check.stat.exists }} - {% endif %} - Sudo права настроены: {{ sudo_check.rc == 0 }} diff --git a/roles/devops/tasks/main.yml b/roles/devops/tasks/main.yml index ba4f102..8f81b86 100644 --- a/roles/devops/tasks/main.yml +++ b/roles/devops/tasks/main.yml @@ -1,111 +1,261 @@ --- -# Задачи для роли devops +# Основные задачи для роли devops # Автор: Сергей Антропов # Сайт: https://devops.org.ru -# Определение ОС и настройка переменных -- name: "Определение ОС и настройка переменных" - set_fact: - devops_os_family: "{{ ansible_os_family | lower }}" - devops_distribution: "{{ ansible_distribution | lower }}" - devops_os_name: "{{ ansible_distribution | lower if ansible_distribution is defined else ansible_os_family | lower }}" - when: ansible_os_family is defined +- name: "🔍 Проверка входных параметров" + tags: [devops, validation] + block: + - name: "Проверка наличия пароля пользователя devops" + fail: + msg: "Пароль пользователя devops не найден в vault/secrets.yml. Установите переменную vault_devops_password." + when: + - vault_file_path is defined + - devops_password == "" -# Определение групп пользователя в зависимости от ОС -- name: "Определение групп пользователя для {{ devops_os_name }}" - set_fact: - devops_user_groups: "{{ devops_os_config[devops_os_name].groups | default(devops_os_config[devops_os_family].groups | default(['sudo'])) }}" - devops_sudo_file: "{{ devops_os_config[devops_os_name].sudo_file | default(devops_os_config[devops_os_family].sudo_file | default('/etc/sudoers.d/devops')) }}" - devops_sudo_validate: "{{ devops_os_config[devops_os_name].sudo_validate | default(devops_os_config[devops_os_family].sudo_validate | default('visudo -cf %s')) }}" - when: devops_os_name is defined + - name: "Проверка наличия SSH публичного ключа" + fail: + msg: "SSH публичный ключ не найден в vault/secrets.yml. Установите переменную vault_devops_ssh_public_key." + when: + - vault_file_path is defined + - devops_ssh_public_key == "" -# Проверка существования групп перед созданием пользователя -- name: "Проверка существования групп" - getent: - database: "group" - key: "{{ item }}" - register: group_check - failed_when: false - changed_when: false - loop: "{{ devops_user_groups }}" - when: devops_user_groups is defined + - name: "Логирование начала выполнения роли" + debug: + msg: "Начинаем настройку пользователя {{ devops_user }} на {{ ansible_distribution }} {{ ansible_distribution_version }}" + when: false -# Фильтрация только существующих групп -- name: "Фильтрация существующих групп" - set_fact: - devops_existing_groups: "{{ group_check.results | selectattr('ansible_facts', 'defined') | map(attribute='item') | list }}" - when: group_check is defined +- name: "📦 Установка необходимых пакетов" + tags: [devops, packages] + block: + - name: "Обновление кеша пакетов (Debian/Ubuntu)" + apt: + update_cache: yes + cache_valid_time: 3600 + when: devops_os_family == "debian" -# Создание отсутствующих групп (если необходимо) -- name: "Создание группы docker если она не существует" - group: - name: "docker" - state: "present" - become: true - when: - - "'docker' in devops_user_groups" - - "'docker' not in (devops_existing_groups | default([]))" + - name: "Установка необходимых пакетов" + package: + name: "{{ devops_packages_to_install }}" + state: present + become: true + register: package_install_result -# Генерация безопасного пароля для пользователя devops -- name: "Генерация безопасного пароля для пользователя devops" - set_fact: - devops_user_password: "{{ lookup('password', '/tmp/devops_password length=' + devops_password.length | string + ' chars=ascii_letters,digits,punctuation') }}" - no_log: true + - name: "Логирование установки пакетов" + debug: + msg: "Установлены пакеты: {{ package_install_result.changed_packages | default('нет изменений') }}" + when: false -# Создание пользователя devops -- name: "Создание пользователя devops" - user: - name: "{{ devops_user.name }}" - home: "{{ devops_user.home }}" - shell: "{{ devops_user.shell }}" - groups: "{{ devops_existing_groups | default(devops_user_groups) }}" - create_home: "{{ devops_user.create_home }}" - state: "{{ devops_user.state }}" - password: "{{ devops_user_password | password_hash('sha512') }}" - become: true +- name: "👤 Создание группы devops" + tags: [devops, group] + block: + - name: "Проверка существования группы {{ devops_group }}" + group: + name: "{{ devops_group }}" + state: present + gid: "{{ devops_gid }}" + become: true + register: group_create_result -# Создание SSH директории для пользователя devops -- name: "Создание SSH директории для пользователя devops" - file: - path: "{{ devops_ssh.ssh_dir }}" - state: directory - owner: "{{ devops_user.name }}" - group: "{{ devops_user.name }}" - mode: "{{ devops_ssh.ssh_dir_mode }}" - become: true + - name: "Логирование создания группы" + debug: + msg: "Группа {{ devops_group }} создана/существует" + when: false -# Добавление SSH ключа в authorized_keys -- name: "Добавление SSH ключа в authorized_keys" - authorized_key: - user: "{{ devops_user.name }}" - key: "{{ devops_ssh_public_key }}" - state: present - manage_dir: false - become: true - when: devops_ssh_public_key is defined +- name: "👥 Создание недостающих групп" + tags: [devops, groups, additional] + block: + - name: "Создание группы wheel (если не существует)" + group: + name: wheel + state: present + become: true + when: "'wheel' in devops_final_additional_groups" + ignore_errors: true -# Настройка sudo для пользователя devops (без пароля) -- name: "Настройка sudo для пользователя devops без пароля" - lineinfile: - path: "{{ devops_sudo_file }}" - line: "{{ devops_user.name }} ALL=(ALL) NOPASSWD: {{ devops_sudo.commands }}" - create: true - mode: '0440' - validate: "{{ devops_sudo_validate }}" - become: true + - name: "Создание группы systemd-journal (если не существует)" + group: + name: systemd-journal + state: present + become: true + when: "'systemd-journal' in devops_final_additional_groups" + ignore_errors: true -# Добавление пользователя в группу docker (если группа существует) -- name: "Добавление пользователя в группу docker" - user: - name: "{{ devops_user.name }}" - groups: "{{ devops_user_groups }}" - append: true - become: true - when: - - "'docker' in devops_user_groups" - - "'docker' in (devops_existing_groups | default([]))" + - name: "Создание группы docker (если не существует)" + group: + name: docker + state: present + become: true + when: "'docker' in devops_final_additional_groups" + ignore_errors: true -# Логирование успешного создания пользователя -- name: "Логирование создания пользователя devops" - debug: - msg: "Пользователь {{ devops_user.name }} успешно создан с безопасным паролем и SSH доступом на {{ devops_os_name | default('неизвестная') }} ОС" +- name: "👤 Создание пользователя devops" + tags: [devops, user, password] + block: + - name: "Проверка существования пользователя {{ devops_user }}" + user: + name: "{{ devops_user }}" + group: "{{ devops_group }}" + uid: "{{ devops_uid }}" + home: "{{ devops_home }}" + shell: "{{ devops_shell }}" + state: present + create_home: "{{ devops_create_home }}" + system: "{{ devops_system_user }}" + groups: "{{ devops_final_additional_groups }}" + append: yes + become: true + register: user_create_result + + - name: "Установка пароля для пользователя {{ devops_user }}" + user: + name: "{{ devops_user }}" + password: "{{ devops_password | password_hash('sha512') }}" + update_password: always + become: true + no_log: true + register: password_set_result + + - name: "Логирование создания пользователя" + debug: + msg: "Пользователь {{ devops_user }} создан/обновлен с паролем" + when: false + +- name: "🔑 Настройка SSH ключей" + tags: [devops, ssh, keys] + block: + - name: "Создание директории .ssh для пользователя {{ devops_user }}" + file: + path: "{{ devops_ssh_dir }}" + state: directory + owner: "{{ devops_user }}" + group: "{{ devops_group }}" + mode: "{{ devops_ssh_dir_mode }}" + become: true + + - name: "Добавление SSH публичного ключа в authorized_keys" + authorized_key: + user: "{{ devops_user }}" + key: "{{ devops_ssh_public_key }}" + state: present + manage_dir: no + become: true + register: ssh_key_result + when: devops_ssh_public_key != "" + + - name: "Установка правильных прав на authorized_keys" + file: + path: "{{ devops_ssh_authorized_keys }}" + owner: "{{ devops_user }}" + group: "{{ devops_group }}" + mode: "{{ devops_ssh_keys_mode }}" + become: true + when: devops_ssh_public_key != "" + + - name: "Логирование настройки SSH" + debug: + msg: "SSH ключ для пользователя {{ devops_user }} настроен" + when: false + +- name: "🔐 Настройка sudo прав" + tags: [devops, sudo, permissions] + block: + - name: "Создание файла sudoers для пользователя {{ devops_user }}" + template: + src: "{{ devops_sudoers_template }}" + dest: "{{ devops_sudoers_file }}" + owner: root + group: root + mode: '0440' + backup: yes + become: true + register: sudoers_result + + - name: "Проверка синтаксиса sudoers файла" + command: "visudo -c -f {{ devops_sudoers_file }}" + become: true + register: sudoers_check + changed_when: false + failed_when: sudoers_check.rc != 0 + + - name: "Логирование настройки sudo" + debug: + msg: "Sudo права для пользователя {{ devops_user }} настроены" + when: false + +- name: "🔧 Настройка дополнительных параметров" + tags: [devops, config, additional] + block: + - name: "Установка umask для пользователя {{ devops_user }}" + lineinfile: + path: "{{ devops_home }}/.bashrc" + line: "umask {{ devops_umask }}" + owner: "{{ devops_user }}" + group: "{{ devops_group }}" + mode: '0644' + create: yes + backup: yes + become: true + + - name: "Создание SSH конфигурации для пользователя {{ devops_user }}" + template: + src: "devops_ssh_config.j2" + dest: "{{ devops_ssh_config }}" + owner: "{{ devops_user }}" + group: "{{ devops_group }}" + mode: "0600" + backup: yes + become: true + + - name: "Логирование дополнительных настроек" + debug: + msg: "Дополнительные настройки для пользователя {{ devops_user }} применены" + when: false + +- name: "✅ Проверка настройки пользователя devops" + when: devops_verify_user + tags: [devops, verification, check] + block: + - name: "Проверка существования пользователя {{ devops_user }}" + command: "id {{ devops_user }}" + register: user_check + changed_when: false + failed_when: user_check.rc != 0 + + - name: "Проверка SSH ключа пользователя {{ devops_user }}" + stat: + path: "{{ devops_ssh_authorized_keys }}" + register: ssh_key_check + + - name: "Проверка sudo прав пользователя {{ devops_user }}" + command: "sudo -l -U {{ devops_user }}" + become: true + register: sudo_check + changed_when: false + failed_when: sudo_check.rc != 0 + + - name: "Логирование результатов проверки" + debug: + msg: | + Результаты проверки пользователя {{ devops_user }}: + - Пользователь существует: {{ user_check.rc == 0 }} + - SSH ключ настроен: {{ ssh_key_check.stat.exists }} + - Sudo права настроены: {{ sudo_check.rc == 0 }} + +- name: "📝 Уведомления о завершении" + tags: [devops, notification, success] + block: + - name: "Уведомление об успешном завершении" + debug: + msg: "✅ Пользователь {{ devops_user }} успешно настроен на {{ ansible_hostname }}" + when: devops_notify_on_success + + - name: "Уведомление о настройке SSH" + debug: + msg: "🔑 SSH ключ для пользователя {{ devops_user }} настроен" + when: devops_notify_on_success and devops_verify_ssh + + - name: "Уведомление о настройке sudo" + debug: + msg: "🔐 Sudo права для пользователя {{ devops_user }} настроены" + when: devops_notify_on_success and devops_verify_sudo \ No newline at end of file diff --git a/roles/devops/templates/devops_ssh_config.j2 b/roles/devops/templates/devops_ssh_config.j2 new file mode 100644 index 0000000..004aaf2 --- /dev/null +++ b/roles/devops/templates/devops_ssh_config.j2 @@ -0,0 +1,79 @@ +# SSH конфигурация для пользователя {{ devops_user }} +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# Создан: {{ ansible_date_time.iso8601 }} + +# Основные настройки SSH клиента +Host * + # Настройки безопасности + StrictHostKeyChecking ask + UserKnownHostsFile ~/.ssh/known_hosts + IdentitiesOnly yes + + # Настройки подключения + ServerAliveInterval 60 + ServerAliveCountMax 3 + TCPKeepAlive yes + + # Настройки сжатия + Compression yes + CompressionLevel 6 + + # Настройки шифрования + Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr + + # Настройки MAC + MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha2-256,hmac-sha2-512 + + # Настройки KEX + KexAlgorithms curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521 + + # Настройки аутентификации + PreferredAuthentications publickey,password + PubkeyAuthentication yes + PasswordAuthentication yes + + # Настройки портов + Port 22 + + # Настройки таймаутов + ConnectTimeout 30 + ConnectionAttempts 3 + + # Настройки логирования + LogLevel INFO + + # Настройки для X11 forwarding (если нужно) + # ForwardX11 yes + # ForwardX11Trusted yes + + # Настройки для агента SSH + ForwardAgent yes + + # Настройки для туннелирования + # LocalForward 8080 localhost:80 + # RemoteForward 9090 localhost:9090 + +# Специфичные настройки для разных хостов +# Host production +# HostName prod.example.com +# User {{ devops_user }} +# Port 2222 +# IdentityFile ~/.ssh/id_rsa_prod +# StrictHostKeyChecking yes +# UserKnownHostsFile ~/.ssh/known_hosts_prod + +# Host staging +# HostName staging.example.com +# User {{ devops_user }} +# Port 22 +# IdentityFile ~/.ssh/id_rsa_staging +# StrictHostKeyChecking no + +# Host development +# HostName dev.example.com +# User {{ devops_user }} +# Port 22 +# IdentityFile ~/.ssh/id_rsa_dev +# StrictHostKeyChecking no +# UserKnownHostsFile /dev/null diff --git a/roles/devops/templates/devops_sudoers.j2 b/roles/devops/templates/devops_sudoers.j2 new file mode 100644 index 0000000..42d41c6 --- /dev/null +++ b/roles/devops/templates/devops_sudoers.j2 @@ -0,0 +1,21 @@ +# Sudoers файл для пользователя {{ devops_user }} +# Автор: Сергей Антропов +# Сайт: https://devops.org.ru +# Создан: {{ ansible_date_time.iso8601 }} + +# Разрешить пользователю {{ devops_user }} выполнять все команды без ввода пароля +{{ devops_user }} ALL=(ALL) NOPASSWD:ALL + +# Дополнительные настройки безопасности +# Разрешить выполнение команд только от определенных терминалов (опционально) +# {{ devops_user }} ALL=(ALL) NOPASSWD:ALL, !/usr/bin/passwd, !/usr/bin/su + +# Логирование всех команд sudo (опционально) +# Defaults logfile=/var/log/sudo.log +# Defaults log_input, log_output + +# Настройки таймаута для sudo сессий (опционально) +# Defaults timestamp_timeout=15 + +# Разрешить выполнение команд без подтверждения для определенных команд +# {{ devops_user }} ALL=(ALL) NOPASSWD: /bin/systemctl, /usr/bin/docker, /usr/bin/kubectl diff --git a/roles/devops/tests/test.yml b/roles/devops/tests/test.yml deleted file mode 100644 index 472fa7e..0000000 --- a/roles/devops/tests/test.yml +++ /dev/null @@ -1,90 +0,0 @@ ---- -# Тесты для роли devops -# Автор: Сергей Антропов -# Сайт: https://devops.org.ru - -- name: "Тестирование роли devops" - hosts: all - become: true - gather_facts: true - - vars: - devops_ssh_public_key: "{{ devops_ssh_keys.public_key }}" - - roles: - - devops - - post_tasks: - # Тест 1: Проверка существования пользователя - - name: "Проверка существования пользователя devops" - command: "id {{ devops_user.name }}" - register: user_exists - failed_when: user_exists.rc != 0 - changed_when: false - - # Тест 2: Проверка домашней директории - - name: "Проверка домашней директории" - stat: - path: "{{ devops_user.home }}" - register: home_dir - failed_when: not home_dir.stat.exists - - # Тест 3: Проверка SSH директории - - name: "Проверка SSH директории" - stat: - path: "{{ devops_ssh.ssh_dir }}" - register: ssh_dir - failed_when: not ssh_dir.stat.exists - - # Тест 4: Проверка authorized_keys (если SSH ключ передан) - - name: "Проверка authorized_keys" - stat: - path: "{{ devops_ssh.authorized_keys_file }}" - register: auth_keys - failed_when: devops_ssh_public_key is defined and not auth_keys.stat.exists - when: devops_ssh_public_key is defined - - # Тест 5: Проверка sudo прав - - name: "Проверка sudo прав" - command: "sudo -l -U {{ devops_user.name }}" - register: sudo_rights - become: true - failed_when: sudo_rights.rc != 0 - changed_when: false - - # Тест 6: Проверка групп пользователя - - name: "Проверка групп пользователя" - command: "groups {{ devops_user.name }}" - register: user_groups - failed_when: user_groups.rc != 0 - changed_when: false - - # Тест 7: Проверка прав на SSH директорию - - name: "Проверка прав на SSH директорию" - stat: - path: "{{ devops_ssh.ssh_dir }}" - register: ssh_dir_perms - failed_when: ssh_dir_perms.stat.mode != "0" + devops_ssh.ssh_dir_mode - - # Тест 8: Проверка shell пользователя - - name: "Проверка shell пользователя" - command: "getent passwd {{ devops_user.name }}" - register: user_shell - failed_when: user_shell.rc != 0 - changed_when: false - - # Вывод результатов тестов - - name: "Результаты тестов" - debug: - msg: | - ✅ Пользователь {{ devops_user.name }} создан - ✅ Домашняя директория {{ devops_user.home }} создана - ✅ SSH директория {{ devops_ssh.ssh_dir }} создана - {% if devops_ssh_public_key is defined %} - ✅ authorized_keys настроен - {% endif %} - ✅ Sudo права настроены - ✅ Группы пользователя: {{ user_groups.stdout }} - ✅ Shell пользователя: {{ user_shell.stdout.split(':')[-1] }} - ✅ ОС: {{ devops_os_name | default('неизвестная') }} - ✅ Группы для ОС: {{ devops_user_groups | default('не определены') }} diff --git a/roles/devops/vars/main.yml b/roles/devops/vars/main.yml index a476a14..b50beb0 100644 --- a/roles/devops/vars/main.yml +++ b/roles/devops/vars/main.yml @@ -1,25 +1,209 @@ --- -# Переменные для роли devops +# OS-специфичные переменные для роли devops # Автор: Сергей Антропов # Сайт: https://devops.org.ru -# Список пакетов, необходимых для роли -devops_required_packages: - - openssh-server - - sudo - - passwd +# Определение семейства ОС +devops_os_family: "{{ ansible_os_family | lower }}" +devops_distribution: "{{ ansible_distribution | lower }}" +devops_distribution_version: "{{ ansible_distribution_version | lower }}" -# Настройки безопасности для SSH -devops_ssh_security: - permit_root_login: "no" - password_authentication: "yes" - pubkey_authentication: "yes" - authorized_keys_file: ".ssh/authorized_keys" +# Настройки для разных семейств ОС +devops_os_config: + redhat: + package_manager: "yum" + user_management: "useradd" + group_management: "groupadd" + sudo_group: "wheel" + additional_groups: + - "wheel" + - "docker" + - "systemd-journal" + packages: + - "sudo" + - "curl" + - "wget" + - "nano" + - "mc" + - "tar" + - "gzip" + services: + - "sshd" + sudoers_path: "/etc/sudoers.d" + ssh_config_path: "/etc/ssh/sshd_config" + debian: + package_manager: "apt" + user_management: "useradd" + group_management: "groupadd" + sudo_group: "sudo" + additional_groups: + - "sudo" + - "docker" + - "systemd-journal" + packages: + - "sudo" + - "curl" + - "wget" + - "nano" + - "mc" + - "tar" + - "gzip" + services: + - "ssh" + sudoers_path: "/etc/sudoers.d" + ssh_config_path: "/etc/ssh/sshd_config" + suse: + package_manager: "zypper" + user_management: "useradd" + group_management: "groupadd" + sudo_group: "wheel" + additional_groups: + - "wheel" + - "docker" + - "systemd-journal" + packages: + - "sudo" + - "curl" + - "wget" + - "nano" + - "mc" + - "tar" + - "gzip" + services: + - "sshd" + sudoers_path: "/etc/sudoers.d" + ssh_config_path: "/etc/ssh/sshd_config" + alpine: + package_manager: "apk" + user_management: "adduser" + group_management: "addgroup" + sudo_group: "wheel" + additional_groups: + - "wheel" + - "docker" + packages: + - "sudo" + - "openssh" + - "curl" + - "wget" + - "mc" + - "nano" + - "tar" + - "gzip" + services: + - "sshd" + sudoers_path: "/etc/sudoers.d" + ssh_config_path: "/etc/ssh/sshd_config" -# Настройки sudo для безопасности -devops_sudo_security: - requiretty: false - visiblepw: false - always_set_home: true - env_reset: true - env_keep: "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS" +# Специфичные настройки для российских ОС +devops_russian_os_config: + astra: + package_manager: "apt" + user_management: "useradd" + group_management: "groupadd" + sudo_group: "sudo" + additional_groups: + - "sudo" + - "docker" + - "systemd-journal" + packages: + - "sudo" + - "curl" + - "wget" + - "mc" + - "nano" + - "tar" + - "gzip" + services: + - "ssh" + sudoers_path: "/etc/sudoers.d" + ssh_config_path: "/etc/ssh/sshd_config" + redos: + package_manager: "yum" + user_management: "useradd" + group_management: "groupadd" + sudo_group: "wheel" + additional_groups: + - "wheel" + - "docker" + - "systemd-journal" + packages: + - "sudo" + - "curl" + - "wget" + - "mc" + - "nano" + - "tar" + - "gzip" + services: + - "sshd" + sudoers_path: "/etc/sudoers.d" + ssh_config_path: "/etc/ssh/sshd_config" + alt: + package_manager: "apt" + user_management: "useradd" + group_management: "groupadd" + sudo_group: "sudo" + additional_groups: + - "sudo" + - "docker" + - "systemd-journal" + packages: + - "sudo" + - "curl" + - "wget" + - "mc" + - "nano" + - "tar" + - "gzip" + services: + - "ssh" + sudoers_path: "/etc/sudoers.d" + ssh_config_path: "/etc/ssh/sshd_config" + +# Получение конфигурации для текущей ОС +devops_current_config: "{{ devops_russian_os_config[devops_distribution] | default(devops_os_config[devops_os_family]) }}" + +# Переменные для работы с пакетами +devops_package_manager_cmd: "{{ devops_current_config.package_manager }}" +devops_user_cmd: "{{ devops_current_config.user_management }}" +devops_group_cmd: "{{ devops_current_config.group_management }}" +devops_sudo_group: "{{ devops_current_config.sudo_group }}" +devops_packages_to_install: "{{ devops_current_config.packages }}" +devops_services_to_enable: "{{ devops_current_config.services }}" +devops_sudoers_path: "{{ devops_current_config.sudoers_path }}" +devops_ssh_config_path: "{{ devops_current_config.ssh_config_path }}" + +# Дополнительные группы для пользователя +devops_final_additional_groups: "{{ devops_current_config.additional_groups }}" + +# Настройки для проверки системы +devops_system_checks: + - name: "check_user_exists" + command: "id {{ devops_user }}" + register: "devops_user_check" + + - name: "check_ssh_key_exists" + stat: + path: "{{ devops_ssh_authorized_keys }}" + register: "devops_ssh_key_check" + + - name: "check_sudoers_exists" + stat: + path: "{{ devops_sudoers_file }}" + register: "devops_sudoers_check" + +# Настройки для логирования +devops_log_config: + level: "{{ devops_log_level }}" + file: "{{ devops_log_file }}" + format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + max_size: "10MB" + backup_count: 5 + +# Настройки для уведомлений +devops_notification_config: + success_message: "Пользователь {{ devops_user }} успешно настроен" + failure_message: "Ошибка при настройке пользователя {{ devops_user }}" + ssh_message: "SSH ключ для пользователя {{ devops_user }} настроен" + sudo_message: "Sudo права для пользователя {{ devops_user }} настроены" diff --git a/vault/secrets.yml b/vault/secrets.yml index 83ad49e..373aea4 100644 --- a/vault/secrets.yml +++ b/vault/secrets.yml @@ -1,80 +1,27 @@ $ANSIBLE_VAULT;1.1;AES256 -35343565303431363831646439663864653034633332396533656362393138666235353365613631 -6633313964346463653166333131316161643064626539300a366366383264653236643366343861 -36643265643338346263663332663961613132613662303033386563356235666334613763303232 -3332636435353130380a643031343335306330643964363230333363653761376333306232663263 -37613937376662386563366237666630623935653663316235363037613962616663373534633066 -36356639656662653339613534373630326164303536633466613238306530326661343065376632 -63646330376662643836636539333837313366656237626264336130636139376665346162303834 -39366235333833303839646530663963346234316661306663356261316537663333326363326333 -34386536343137333736356139636461653737353062613730326665383761356337663264356539 -64623962363631356131373735643639333065663861336262346366313163303739306663616635 -63386534333936356636623532653339366464346531326562623062353839333563346562383832 -38656166626366653930343436633338363530313138323862353563323033306333353130383732 -63323931336338663663383532313635373166616631333832666330393933646165336164353634 -30666137626131636162333335373961343763383434386166346363626162663538653239633563 -64316539626632346133346339616164646336306331393466306333623638366137613866663263 -37623663316462376330643866303464366236613965663561383561643162393032663266383661 -63643466396433366530613830636666393862383134313165313162663262623536306164313633 -65383031646562356535626363326135656366323462383364306138626163363236333036316534 -36353364626130633965353036636430393035316434393063373062363362663430633462313631 -65373330646531333334623738653537623963663237663137306430656438316665623534313362 -36303934306331393365363866393265646263653830666234333234623266353634393239633337 -32663938613831656138376266333835613561643534663463373238323532313237336132613239 -31383665373964623362623561313161363831316361626432636665343938633437336561363161 -30366136383766356261396533356134326532353938326439303334396333363036363563653030 -33353538316363353637313835636535653136346234316636626533663331653163643466633164 -35633630316162396665626632363036373331343230306665313037336666663066653763653835 -34643532386138363665663238393336356431353464613031336334623761613732646565363730 -34353866616339616164663934626632663130393563646265343461303533653139653137303661 -30663539616162333739313366363861336562346132373861393734323366663863333063396232 -34373435306161383462306136333734303339353231386432313637343236356439626537663530 -33633331376439643732306365366530636134366431396566376330663162336334353031353834 -32636435656131616133643636363965316634626231356630323237613261663665393061616432 -35333031306562626234363061316562373964386236636464633939343437396234313036383561 -31646463313037323133616561633562323765303361346430313134316337626139663665326436 -31616334356663346234663833396635373162346136663062363138373034356638636537353737 -62336563333338343731626665323336386632303162383166346338373864613463326466386361 -37356135376430363038656439376366646238383736636461613034666163623838393236346464 -34356563366234306465366438326265366133663934323663313934313037313663633833343533 -38326163323438376336313065313338303239303766326636326433366566643935626530643537 -61313738313361353835373430386430343738356461633335396165323337623832663330383834 -61666363663939353238623861653962636638303138626435373366336130653565333532616664 -61643734393733646364623937356264306262366266396536656338343366306364663339656236 -63316635623037616266613739326335353066373463643132393331626232303134346233303833 -61303738383961636235616634356435313165613734336438333730353463313366653332626263 -61353731323133393735333664366134633434346130646164336665386264376265316266386665 -65613431303733376637643536646561636163633065393966333161313930356636353936663239 -36326561653132373335616237303764333661303961373139646663653431346338356331373765 -37333865333563333338666338633665316238396438333630306663383164383234636237393562 -32356130653538383632633462303665333733333365343237626262636563346361363764313663 -34306337636665633431353438373661306336396533613936313866623337343538613036353233 -66623936343762383033323830333266643463376138643133643434353135656261393733313433 -38303264303332643361376162303330343666636162396163366365353465623132663831323530 -33346565353262376131623431343538616533326564383637396538343336626336646633353934 -61376462656263663965383137376131643536336539613532373536376231626364643866646535 -38646430326138643339396464366438393263313665636562356631326133313734343562363065 -61663766616633333262623633396363336536373666316536363931333939383838663131613439 -66616663383334363330646638393139313330363533306639623437663763623333343038373838 -63303932663436636361663338346665386531333533633730323735333734376662383835343163 -38623435333662333634376361303734653130663833376264376336663363623966363939623336 -66656532663431333132663734386538663066323230356166356238333564336230633030353233 -61333933333763666564313233333432366231383666333832393035656234326161323332653135 -34323032613535336666633830373866383832393166636565646132633763616230326530346462 -63653638383263323532653261353365313433346534323865616336383864363530643237613061 -32613737353431626366643066663864663866323363396230333335346362373262393332333939 -34393539363836656539623766346336383834323831346261343635346466383164376135353136 -33366333323765616330333735383163663736646466653265326335306366663832643162363035 -39326661313732303830333236653134346534656433366366663539626364663362626135666438 -32356635386262336635396162666334616139353134323366633165626363336338393165663933 -62643431616632653838376239326531643733303636323236613561626534343535383130623766 -66343734396561386661306235393865336236323261356461356264326535316437653131326435 -38663866383332393033356165663032656433383763656431323836353961633437623662303135 -61373836626564373331303362313062313235373731646234393532343430363235326630373831 -35313635643936663438316132623265306531383838633266336563613662386233663937616230 -33333933353831396534356461653537616536633365323364326666323833346432636536643737 -31663065303933316438653864313734366464616137333838643839313437623532333766373763 -35346237383433643032613630396364386464316133343764666431636330333463333037306431 -35353232633463363732346462663230376631363832363239396262643531393831306633663966 -64333136343662343564653935306438663233623332626337613931353861396562663334346537 -353330613139383830303838353838356233 +65336338343362663234333233316130353361323735626262643363303837616230393738643434 +6565613531303166306365366239626439666530326135330a663565366663363938373765376633 +64633734363436613039323235386364373961643164346530663835313333376132313036303430 +6631353831646664320a333936353334313364623039313939663131636466363263303330643630 +35666561316266313135346534393863616433636363663564303830636438306238633738386665 +66383939653238646337653966326364663863353739313936663363353961663163613239346534 +64383063323839646434333461616336653635336438666132353363333538663933623039323463 +62663933663038623536376137666639666639353961333666303233336137343831666338323162 +36626665363333623238333138356538326334646532313639383535313863353230623262666337 +66393762363931376638666633303134383838346132626337313436313334363030663436616438 +63643438636535396432633432613238623731613931356137623161643564376330313861653161 +35353530313833656130396362613036313163623731303830663537363830636631366332616163 +36663533643463353861333461363538663830343338646237646633383064626539396264626230 +65376238353833313065336632393662316137393065383261383663373261363137376234386264 +35393265303633306262376534656665376330633535613964666662346462663834316435633664 +35396339386466346634323666653732653232306364616165653633336364363336666433353861 +62653831316638376261313739343266333039326666386461323035343761303032323666643831 +34326661366362353561323237353637336430636664653730626431613535313865643530666239 +30373362623965613765343965626663643936656134363761386232623935313065393235313735 +62643061303534323637616230646330313962306664396139316437626436343938373435623939 +61663434373739323662386534353662653933326464396461623564333965376331373736383064 +38356465623464383437363735313662353565313131393036326535326231306465613562663363 +61393833346138646238646132653962613033396561343237636636663633396165643266366665 +39373565646264326166653936623766326436616362653130323835303633383334393561343565 +34613932363539656537346537653836393537376463363830396534366238376436393537363736 +6230383066326331643162356139643663373535633230636539