initial comit with first sprint of terraform and ansible files
This commit is contained in:
commit
6c9f41c26c
|
|
@ -0,0 +1,36 @@
|
||||||
|
# EditorConfig for OpenCMMC Stack
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Default settings for all files
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Python files
|
||||||
|
[*.py]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
# YAML / Ansible / Terraform files
|
||||||
|
[*.yml]
|
||||||
|
indent_size = 2
|
||||||
|
[*.yaml]
|
||||||
|
indent_size = 2
|
||||||
|
[*.tf]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Markdown files
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Shell scripts
|
||||||
|
[*.sh]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
# Mermaid diagrams
|
||||||
|
[*.mmd]
|
||||||
|
indent_size = 2
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
# Normalize all text files to LF endings
|
||||||
|
* text=auto eol=lf
|
||||||
|
|
||||||
|
# Markdown, YAML, Terraform, and code files treated as text
|
||||||
|
*.md text
|
||||||
|
*.markdown text
|
||||||
|
*.yml text
|
||||||
|
*.yaml text
|
||||||
|
*.tf text
|
||||||
|
*.tfvars text
|
||||||
|
*.sh text
|
||||||
|
*.py text
|
||||||
|
*.mmd text
|
||||||
|
|
||||||
|
# Treat images and binary files as binary (no diff)
|
||||||
|
*.svg binary
|
||||||
|
*.png binary
|
||||||
|
*.jpg binary
|
||||||
|
*.jpeg binary
|
||||||
|
*.gif binary
|
||||||
|
*.ico binary
|
||||||
|
*.pdf binary
|
||||||
|
*.zip binary
|
||||||
|
*.tar.gz binary
|
||||||
|
*.gz binary
|
||||||
|
|
||||||
|
# GitHub language statistics override (if needed)
|
||||||
|
docs/** linguist-documentation
|
||||||
|
*.md linguist-language=Markdown
|
||||||
|
*.mmd linguist-language=Mermaid
|
||||||
|
|
||||||
|
# Avoid diffs on lock and compiled files
|
||||||
|
*.lock binary
|
||||||
|
*.retry binary
|
||||||
|
|
@ -0,0 +1,301 @@
|
||||||
|
# Local .terraform directories
|
||||||
|
**/.terraform/*
|
||||||
|
|
||||||
|
# .tfstate files
|
||||||
|
*.tfstate
|
||||||
|
*.tfstate.*
|
||||||
|
|
||||||
|
# Crash log files
|
||||||
|
crash.log
|
||||||
|
crash.*.log
|
||||||
|
|
||||||
|
# Exclude all .tfvars files, which are likely to contain sensitive data, such as
|
||||||
|
# password, private keys, and other secrets. These should not be part of version
|
||||||
|
# control as they are data points which are potentially sensitive and subject
|
||||||
|
# to change depending on the environment.
|
||||||
|
*.tfvars
|
||||||
|
*.tfvars.json
|
||||||
|
|
||||||
|
# Ignore override files as they are usually used to override resources locally and so
|
||||||
|
# are not checked in
|
||||||
|
override.tf
|
||||||
|
override.tf.json
|
||||||
|
*_override.tf
|
||||||
|
*_override.tf.json
|
||||||
|
|
||||||
|
# Ignore transient lock info files created by terraform apply
|
||||||
|
.terraform.tfstate.lock.info
|
||||||
|
|
||||||
|
# Include override files you do wish to add to version control using negated pattern
|
||||||
|
# !example_override.tf
|
||||||
|
|
||||||
|
# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
|
||||||
|
# example: *tfplan*
|
||||||
|
|
||||||
|
# Ignore CLI configuration files
|
||||||
|
.terraformrc
|
||||||
|
terraform.rc
|
||||||
|
|
||||||
|
*.retry
|
||||||
|
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
*.py,cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
cover/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
db.sqlite3-journal
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
.pybuilder/
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
# For a library or package, you might want to ignore these files since the code is
|
||||||
|
# intended to run in multiple environments; otherwise, check them in:
|
||||||
|
# .python-version
|
||||||
|
|
||||||
|
# pipenv
|
||||||
|
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||||
|
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||||
|
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||||
|
# install all needed dependencies.
|
||||||
|
#Pipfile.lock
|
||||||
|
|
||||||
|
# UV
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
#uv.lock
|
||||||
|
|
||||||
|
# poetry
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||||
|
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||||
|
# commonly ignored for libraries.
|
||||||
|
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||||
|
#poetry.lock
|
||||||
|
|
||||||
|
# pdm
|
||||||
|
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||||
|
#pdm.lock
|
||||||
|
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||||
|
# in version control.
|
||||||
|
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
||||||
|
.pdm.toml
|
||||||
|
.pdm-python
|
||||||
|
.pdm-build/
|
||||||
|
|
||||||
|
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||||
|
__pypackages__/
|
||||||
|
|
||||||
|
# Celery stuff
|
||||||
|
celerybeat-schedule
|
||||||
|
celerybeat.pid
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
# pytype static type analyzer
|
||||||
|
.pytype/
|
||||||
|
|
||||||
|
# Cython debug symbols
|
||||||
|
cython_debug/
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||||
|
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||||
|
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||||
|
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||||
|
#.idea/
|
||||||
|
|
||||||
|
# Ruff stuff:
|
||||||
|
.ruff_cache/
|
||||||
|
|
||||||
|
# PyPI configuration file
|
||||||
|
.pypirc
|
||||||
|
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
|
# Local History for Visual Studio Code
|
||||||
|
.history/
|
||||||
|
|
||||||
|
# Built Visual Studio Code Extensions
|
||||||
|
*.vsix
|
||||||
|
|
||||||
|
# ————————————————————————
|
||||||
|
# MkDocs/Mermaid CLI Additions
|
||||||
|
# ————————————————————————
|
||||||
|
|
||||||
|
# Mermaid CLI output (SVGs or temp)
|
||||||
|
*.svg
|
||||||
|
*.mmdc-log
|
||||||
|
|
||||||
|
# Mermaid cache (if any future builds generate it)
|
||||||
|
.mermaid-cache/
|
||||||
|
|
||||||
|
# ————————————————————————
|
||||||
|
# Ansible Molecule Testing
|
||||||
|
# ————————————————————————
|
||||||
|
|
||||||
|
molecule/
|
||||||
|
**/molecule/*/.tox/
|
||||||
|
**/molecule/*/.molecule/
|
||||||
|
**/molecule/*/logs/
|
||||||
|
**/molecule/*/default/
|
||||||
|
|
||||||
|
# Lint and report files
|
||||||
|
*.retry
|
||||||
|
ansible-lint.log
|
||||||
|
molecule-report.xml
|
||||||
|
|
||||||
|
# ————————————————————————
|
||||||
|
# Ansible Role Packaging
|
||||||
|
# ————————————————————————
|
||||||
|
|
||||||
|
*.tar.gz
|
||||||
|
*.tar
|
||||||
|
*.zip
|
||||||
|
*.gz
|
||||||
|
|
||||||
|
# Built or temp roles
|
||||||
|
roles/**/collections/
|
||||||
|
roles/**/.python-version
|
||||||
|
roles/**/__pycache__/
|
||||||
|
roles/**/.pytest_cache/
|
||||||
|
|
||||||
|
# ————————————————————————
|
||||||
|
# SSH/Secrets Safety (add for clarity)
|
||||||
|
# ————————————————————————
|
||||||
|
|
||||||
|
# Never commit real keypairs or their fingerprints
|
||||||
|
id_rsa
|
||||||
|
id_rsa.pub
|
||||||
|
*.pem
|
||||||
|
*.crt
|
||||||
|
*.key
|
||||||
|
*.jks
|
||||||
|
|
||||||
|
# Example fallback (should be updated before use)
|
||||||
|
!example_id_rsa.pub
|
||||||
|
|
||||||
|
# ————————————————————————
|
||||||
|
# Terraform Local Logs and CLI Plan Files
|
||||||
|
# ————————————————————————
|
||||||
|
|
||||||
|
*.log
|
||||||
|
*.tfplan
|
||||||
|
|
||||||
|
# Explicitly ignore Terraform's crash diagnostic dirs
|
||||||
|
.terraform.d/
|
||||||
|
|
||||||
|
# ————————————————————————
|
||||||
|
# General Safety
|
||||||
|
# ————————————————————————
|
||||||
|
|
||||||
|
# Lock files generated by CI/test runs
|
||||||
|
.lockfile
|
||||||
|
open-cmmc.lock
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
---
|
||||||
|
# 🔐 Global Access & Identity Settings
|
||||||
|
default_user: cmmcadmin
|
||||||
|
default_shell: /bin/bash
|
||||||
|
ssh_authorized_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||||||
|
|
||||||
|
# 🌐 Network & Proxy Settings
|
||||||
|
nextcloud_port: 8080
|
||||||
|
mailcow_port: 443
|
||||||
|
keycloak_port: 8081
|
||||||
|
tailscale_auth_key: tskey-abc123
|
||||||
|
stepca_port: 9000
|
||||||
|
wazuh_port: 55000
|
||||||
|
|
||||||
|
# 📦 Container Images
|
||||||
|
nextcloud_aio_image: nextcloud/all-in-one:latest
|
||||||
|
keycloak_image: quay.io/keycloak/keycloak:24.0.2
|
||||||
|
|
||||||
|
# 🗂️ Data Directories
|
||||||
|
nextcloud_data_dir: /srv/nextcloud
|
||||||
|
backup_base_dir: /srv/backups
|
||||||
|
logs_dir: /var/log/open-cmmc
|
||||||
|
|
||||||
|
# ⚙️ System Users
|
||||||
|
svc_keycloak: svc_keycloak
|
||||||
|
svc_mailcow: svc_mailcow
|
||||||
|
svc_wazuh: svc_wazuh
|
||||||
|
svc_stepca: svc_stepca
|
||||||
|
|
||||||
|
# 🔄 Backup/Restore
|
||||||
|
restic_password: changeme-securely
|
||||||
|
restic_repo: /srv/backups/restic-repo
|
||||||
|
|
||||||
|
# 📛 DNS & Hostname
|
||||||
|
domain_name: example.cmmc.local
|
||||||
|
hostname: open-cmmc-gateway
|
||||||
|
|
||||||
|
# 📜 Default Realm for Keycloak
|
||||||
|
keycloak_realm: OpenCMMC
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
# file_storage Role
|
||||||
|
|
||||||
|
This Ansible role deploys **Nextcloud All-in-One (AIO)** as the secure file sharing and collaboration solution in the OpenCMMC Stack.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Pulls and runs the official `nextcloud/all-in-one` container image
|
||||||
|
- Sets up a persistent storage directory for CUI/FCI content
|
||||||
|
- Configures container restart and port mapping for access via reverse proxy
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
| Variable | Description | Default |
|
||||||
|
|-----------------------|--------------------------------------------|-----------------------------|
|
||||||
|
| `nextcloud_aio_image` | Container image for Nextcloud AIO | `nextcloud/all-in-one:latest` |
|
||||||
|
| `nextcloud_data_dir` | Host volume path for Nextcloud data | `/mnt/ncdata` |
|
||||||
|
| `nextcloud_port` | Port exposed on the host | `8080` |
|
||||||
|
|
||||||
|
## Example Playbook
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- hosts: all
|
||||||
|
roles:
|
||||||
|
- role: file_storage
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Make sure this container is **behind a reverse proxy** (e.g., NGINX or Caddy).
|
||||||
|
- Configure DNS and TLS externally as needed.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
nextcloud_aio_image: "nextcloud/all-in-one:latest"
|
||||||
|
nextcloud_container_name: "nextcloud-aio-mastercontainer"
|
||||||
|
nextcloud_data_dir: "/opt/nextcloud/data"
|
||||||
|
nextcloud_port: 8080
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
# Placeholder for handlers (e.g., restart Nextcloud container)
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: file_storage
|
||||||
|
author: open-cmmc
|
||||||
|
description: Deploy secure file collaboration using Nextcloud AIO
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.10"
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
---
|
||||||
|
- name: Create Nextcloud data directory
|
||||||
|
file:
|
||||||
|
path: "{{ nextcloud_data_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Pull Nextcloud AIO container image
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: "{{ nextcloud_aio_image }}"
|
||||||
|
|
||||||
|
- name: Deploy Nextcloud AIO container
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: "{{ nextcloud_container_name }}"
|
||||||
|
image: "{{ nextcloud_aio_image }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
ports:
|
||||||
|
- "{{ nextcloud_port }}:8080"
|
||||||
|
volumes:
|
||||||
|
- "{{ nextcloud_data_dir }}:/mnt/ncdata:z"
|
||||||
|
- "nextcloud_aio_mastercontainer:/mnt/docker-aio-config:z"
|
||||||
|
env:
|
||||||
|
NEXTCLOUD_DATADIR: "/mnt/ncdata"
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Identity Role
|
||||||
|
|
||||||
|
This role installs and configures Keycloak for identity and access management, and Step-CA for internal certificate authority needs in the OpenCMMC Stack.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
keycloak_version: "24.0.2"
|
||||||
|
keycloak_admin_user: "admin"
|
||||||
|
keycloak_admin_password: "securepassword"
|
||||||
|
keycloak_realm: "OpenCMMC"
|
||||||
|
step_ca_provisioner: "admin@example.com"
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Restart keycloak
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: keycloak
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
- name: Restart step-ca
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: step-ca
|
||||||
|
state: restarted
|
||||||
|
enabled: true
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: OpenCMMC Team
|
||||||
|
description: Identity and Access Management (IAM) role with Keycloak and Step-CA.
|
||||||
|
company: Kell Engineering
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.12"
|
||||||
|
platforms:
|
||||||
|
- name: Ubuntu
|
||||||
|
versions:
|
||||||
|
- 22.04
|
||||||
|
dependencies: []
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
- name: Ensure Keycloak CLI (kcadm.sh) is installed
|
||||||
|
stat:
|
||||||
|
path: /opt/keycloak/bin/kcadm.sh
|
||||||
|
register: kcadm_path
|
||||||
|
|
||||||
|
- name: Install Keycloak CLI if missing
|
||||||
|
get_url:
|
||||||
|
url: https://downloads.jboss.org/keycloak/24.0.2/keycloak-24.0.2.zip
|
||||||
|
dest: /tmp/keycloak.zip
|
||||||
|
when: not kcadm_path.stat.exists
|
||||||
|
|
||||||
|
- name: Unarchive Keycloak CLI
|
||||||
|
unarchive:
|
||||||
|
src: /tmp/keycloak.zip
|
||||||
|
dest: /opt/
|
||||||
|
remote_src: yes
|
||||||
|
when: not kcadm_path.stat.exists
|
||||||
|
|
||||||
|
- name: Authenticate Keycloak admin CLI session
|
||||||
|
command: >
|
||||||
|
/opt/keycloak/bin/kcadm.sh config credentials --server http://localhost:8080/auth
|
||||||
|
--realm master --user {{ keycloak_admin_user }} --password {{ keycloak_admin_password }}
|
||||||
|
environment:
|
||||||
|
KCADM_CONFIG: /opt/keycloak/kcadm.config
|
||||||
|
|
||||||
|
- name: Create OpenCMMC realm
|
||||||
|
command: /opt/keycloak/bin/kcadm.sh create realms -s realm=OpenCMMC -s enabled=true
|
||||||
|
|
||||||
|
- name: Create groups
|
||||||
|
loop:
|
||||||
|
- Access_CUI
|
||||||
|
- Access_FCI
|
||||||
|
- Access_Proprietary
|
||||||
|
command: /opt/keycloak/bin/kcadm.sh create groups -r OpenCMMC -s name="{{ item }}"
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: Configure Keycloak realm and groups
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "/opt/keycloak/bin/kcadm.sh create realms -s realm={{ keycloak_realm }} -s enabled=true"
|
||||||
|
when: keycloak_realm is defined
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
- name: Pull Keycloak image
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: quay.io/keycloak/keycloak:24.0.2
|
||||||
|
|
||||||
|
- name: Create systemd service user
|
||||||
|
user:
|
||||||
|
name: svc_keycloak
|
||||||
|
shell: /usr/sbin/nologin
|
||||||
|
system: yes
|
||||||
|
create_home: no
|
||||||
|
|
||||||
|
- name: Create Keycloak config directory
|
||||||
|
file:
|
||||||
|
path: /opt/services/keycloak
|
||||||
|
state: directory
|
||||||
|
owner: svc_keycloak
|
||||||
|
group: svc_keycloak
|
||||||
|
mode: '0755'
|
||||||
|
|
||||||
|
- name: Deploy Keycloak container
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: keycloak
|
||||||
|
image: quay.io/keycloak/keycloak:24.0.2
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
user: svc_keycloak
|
||||||
|
env:
|
||||||
|
KEYCLOAK_ADMIN: "{{ keycloak_admin_user }}"
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD: "{{ keycloak_admin_password }}"
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
command: "start --optimized"
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
- name: Enroll clients in Step-CA
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Provision client certificates using Step-CA"
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
- name: Generate CA certs using step-ca CLI
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Running step ca init with preconfigured values"
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Install Keycloak container
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: keycloak
|
||||||
|
image: quay.io/keycloak/keycloak:{{ keycloak_version }}
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
env:
|
||||||
|
KEYCLOAK_ADMIN: "{{ keycloak_admin_user }}"
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD: "{{ keycloak_admin_password }}"
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
- name: Setup OIDC clients for SSO integration
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Configure OIDC clients for Mailcow, Gitea and SAML for Nextcloud"
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
---
|
||||||
|
- name: Include tasks to install and configure Keycloak
|
||||||
|
include_tasks: install_keycloak.yml
|
||||||
|
|
||||||
|
- name: Include tasks to configure realm and users
|
||||||
|
include_tasks: configure_realm.yml
|
||||||
|
|
||||||
|
- name: Include tasks to setup SSO integration
|
||||||
|
include_tasks: integrate_sso.yml
|
||||||
|
|
||||||
|
- name: Include tasks to configure MFA policies
|
||||||
|
include_tasks: setup_mfa.yml
|
||||||
|
|
||||||
|
- name: Include tasks to provision Step-CA
|
||||||
|
include_tasks: provision_step_ca.yml
|
||||||
|
|
||||||
|
- name: Include tasks to enroll clients in Step-CA
|
||||||
|
include_tasks: enroll_clients.yml
|
||||||
|
|
||||||
|
- name: Include tasks to generate CA certificates
|
||||||
|
include_tasks: generate_ca_certs.yml
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
- name: Install step-ca and create systemd service
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: systemd-step-ca.service.j2
|
||||||
|
dest: /etc/systemd/system/step-ca.service
|
||||||
|
notify: Restart step-ca
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
- name: Enable MFA for users
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Enabling TOTP in Keycloak authentication flow"
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
- name: Install Tailscale
|
||||||
|
shell: curl -fsSL https://tailscale.com/install.sh | sh
|
||||||
|
args:
|
||||||
|
creates: /usr/bin/tailscale
|
||||||
|
|
||||||
|
- name: Bring up Tailscale interface
|
||||||
|
command: tailscale up --authkey {{ tailscale_authkey }}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Keycloak Server
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/podman start -a keycloak
|
||||||
|
ExecStop=/usr/bin/podman stop -t 10 keycloak
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"address": ":9000",
|
||||||
|
"dnsNames": ["stepca.{{ inventory_hostname }}"],
|
||||||
|
"root": "step-ca-root.crt",
|
||||||
|
"crt": "step-ca-intermediate.crt",
|
||||||
|
"key": "step-ca-key.pem"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
your-secure-password
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Step CA
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/local/bin/step-ca /etc/step-ca/config/step-ca-config.json
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
realm_clients:
|
||||||
|
- name: nextcloud
|
||||||
|
protocol: saml
|
||||||
|
- name: mailcow
|
||||||
|
protocol: oidc
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# Ansible Role: keycloak_init
|
||||||
|
|
||||||
|
This role initializes a Keycloak instance with a predefined realm, groups, and clients for the OpenCMMC Stack.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
- name: Register SAML client for Nextcloud
|
||||||
|
shell: '/opt/keycloak/bin/kcadm.sh create clients -r OpenCMMC -s clientId=nextcloud-aio -s protocol=saml -s enabled=true'
|
||||||
|
|
||||||
|
- name: Register OIDC client for Mailcow
|
||||||
|
shell: '/opt/keycloak/bin/kcadm.sh create clients -r OpenCMMC -s clientId=mailcow -s protocol=openid-connect -s enabled=true'
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
- name: Create Keycloak Groups
|
||||||
|
shell: '/opt/keycloak/bin/kcadm.sh create groups -r OpenCMMC -s name=Access_CUI'
|
||||||
|
|
||||||
|
- name: Create FCI Group
|
||||||
|
shell: '/opt/keycloak/bin/kcadm.sh create groups -r OpenCMMC -s name=Access_FCI'
|
||||||
|
|
||||||
|
- name: Create Proprietary Group
|
||||||
|
shell: '/opt/keycloak/bin/kcadm.sh create groups -r OpenCMMC -s name=Access_Proprietary'
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
---
|
||||||
|
- name: Check if Keycloak is already installed
|
||||||
|
stat:
|
||||||
|
path: /opt/keycloak/bin/kcadm.sh
|
||||||
|
register: keycloak_installed
|
||||||
|
|
||||||
|
- name: Download Keycloak if not already present
|
||||||
|
unarchive:
|
||||||
|
src: "https://github.com/keycloak/keycloak/releases/download/{{ keycloak_version }}/keycloak-{{ keycloak_version }}.tar.gz"
|
||||||
|
dest: /opt/
|
||||||
|
remote_src: yes
|
||||||
|
when: not keycloak_installed.stat.exists
|
||||||
|
|
||||||
|
- name: Rename keycloak directory
|
||||||
|
command: mv /opt/keycloak-{{ keycloak_version }} /opt/keycloak
|
||||||
|
args:
|
||||||
|
creates: /opt/keycloak/bin/kcadm.sh
|
||||||
|
when: not keycloak_installed.stat.exists
|
||||||
|
|
||||||
|
- name: Set executable permissions on kcadm.sh
|
||||||
|
file:
|
||||||
|
path: /opt/keycloak/bin/kcadm.sh
|
||||||
|
mode: '0755'
|
||||||
|
when: not keycloak_installed.stat.exists
|
||||||
|
|
||||||
|
- name: Log in to Keycloak Admin CLI
|
||||||
|
command: >
|
||||||
|
/opt/keycloak/bin/kcadm.sh config credentials
|
||||||
|
--server http://localhost:8080
|
||||||
|
--realm master
|
||||||
|
--user {{ keycloak_admin_user }}
|
||||||
|
--password {{ keycloak_admin_password }}
|
||||||
|
environment:
|
||||||
|
KC_HOME: /opt/keycloak
|
||||||
|
register: kcadm_login
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Create OpenCMMC realm
|
||||||
|
command: >
|
||||||
|
/opt/keycloak/bin/kcadm.sh create realms
|
||||||
|
-s realm=OpenCMMC -s enabled=true
|
||||||
|
environment:
|
||||||
|
KC_HOME: /opt/keycloak
|
||||||
|
when: kcadm_login is succeeded
|
||||||
|
|
||||||
|
- name: Create groups
|
||||||
|
loop:
|
||||||
|
- Access_CUI
|
||||||
|
- Access_FCI
|
||||||
|
- Access_Proprietary
|
||||||
|
command: >
|
||||||
|
/opt/keycloak/bin/kcadm.sh create groups -r OpenCMMC -s name={{ item }}
|
||||||
|
environment:
|
||||||
|
KC_HOME: /opt/keycloak
|
||||||
|
when: kcadm_login is succeeded
|
||||||
|
|
||||||
|
- name: Create OIDC client for Mailcow
|
||||||
|
command: >
|
||||||
|
/opt/keycloak/bin/kcadm.sh create clients -r OpenCMMC
|
||||||
|
-s clientId=mailcow
|
||||||
|
-s enabled=true
|
||||||
|
-s protocol=openid-connect
|
||||||
|
-s publicClient=false
|
||||||
|
-s 'redirectUris=["https://mail.yourdomain.com/*"]'
|
||||||
|
environment:
|
||||||
|
KC_HOME: /opt/keycloak
|
||||||
|
when: kcadm_login is succeeded
|
||||||
|
|
||||||
|
- name: Create SAML client for Nextcloud
|
||||||
|
command: >
|
||||||
|
/opt/keycloak/bin/kcadm.sh create clients -r OpenCMMC
|
||||||
|
-s clientId=nextcloud
|
||||||
|
-s enabled=true
|
||||||
|
-s protocol=saml
|
||||||
|
-s 'redirectUris=["https://nextcloud.yourdomain.com/*"]'
|
||||||
|
-s 'attributes.saml.assertion.signature=true'
|
||||||
|
-s 'attributes.saml.force.post.binding=true'
|
||||||
|
environment:
|
||||||
|
KC_HOME: /opt/keycloak
|
||||||
|
when: kcadm_login is succeeded
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: Create Keycloak Realm
|
||||||
|
shell: '/opt/keycloak/bin/kcadm.sh create realms -s realm=OpenCMMC -s enabled=true'
|
||||||
|
args:
|
||||||
|
creates: /opt/keycloak/data/realms/OpenCMMC
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
- name: Ensure kcadm.sh is present
|
||||||
|
stat:
|
||||||
|
path: /opt/keycloak/bin/kcadm.sh
|
||||||
|
register: kcadm_path
|
||||||
|
|
||||||
|
- name: Install unzip (required for kcadm)
|
||||||
|
apt:
|
||||||
|
name: unzip
|
||||||
|
state: present
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
wazuh_container_name: "wazuh-manager"
|
||||||
|
wazuh_image: "wazuh/wazuh:latest"
|
||||||
|
wazuh_config_path: "/opt/wazuh/config"
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
# Reserved for any future log restart triggers or alert changes
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: monitoring
|
||||||
|
author: open-cmmc
|
||||||
|
description: Centralized security logging and SIEM services using Wazuh and auditd
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.10"
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
- name: Pull Wazuh container image
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: wazuh/wazuh:latest
|
||||||
|
|
||||||
|
- name: Create Wazuh configuration directory
|
||||||
|
file:
|
||||||
|
path: "/opt/wazuh/config"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Deploy Wazuh container
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: wazuh-manager
|
||||||
|
image: wazuh/wazuh:latest
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
ports:
|
||||||
|
- "1514:1514/udp"
|
||||||
|
- "1515:1515"
|
||||||
|
- "55000:55000"
|
||||||
|
volumes:
|
||||||
|
- "/opt/wazuh/config:/var/ossec/config:z"
|
||||||
|
|
||||||
|
- name: Ensure auditd is installed
|
||||||
|
apt:
|
||||||
|
name: auditd
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Ensure auditd service is enabled and started
|
||||||
|
service:
|
||||||
|
name: auditd
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Podman Services Role
|
||||||
|
|
||||||
|
This Ansible role provisions and manages containerized infrastructure components (excluding Nextcloud AIO) using **Podman**. It includes configurations for Wazuh, Mailcow, Redis, and more.
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
podman_services:
|
||||||
|
- name: redis
|
||||||
|
image: redis:7
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
ports: []
|
||||||
|
volumes: []
|
||||||
|
env: {}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Include in your playbook:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- hosts: all
|
||||||
|
roles:
|
||||||
|
- role: podman_services
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Only non-root Podman containers are supported
|
||||||
|
- Customize via `podman_services` variable in `defaults/main.yml`
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
podman_services: []
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
# Reserved for future restarts
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: podman_services
|
||||||
|
author: open-cmmc
|
||||||
|
description: Modular deployment of rootless Podman containers
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.10"
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
- name: Deploy keycloak container with Podman
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: keycloak
|
||||||
|
image: "{{ keycloak_image }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
volumes:
|
||||||
|
- "{{ keycloak_data_dir }}:/data:z"
|
||||||
|
env:
|
||||||
|
CONFIG_PATH: "/data/config"
|
||||||
|
|
||||||
|
- name: Ensure systemd service is enabled for keycloak
|
||||||
|
copy:
|
||||||
|
dest: "/etc/systemd/system/podman-keycloak.service"
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Podman container for keycloak
|
||||||
|
Wants=network.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/podman start -a keycloak
|
||||||
|
ExecStop=/usr/bin/podman stop -t 10 keycloak
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Reload systemd and enable service for keycloak
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
name: podman-keycloak.service
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
- name: Deploy mailcow container with Podman
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: mailcow
|
||||||
|
image: "{{ mailcow_image }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
volumes:
|
||||||
|
- "{{ mailcow_data_dir }}:/data:z"
|
||||||
|
env:
|
||||||
|
CONFIG_PATH: "/data/config"
|
||||||
|
|
||||||
|
- name: Ensure systemd service is enabled for mailcow
|
||||||
|
copy:
|
||||||
|
dest: "/etc/systemd/system/podman-mailcow.service"
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Podman container for mailcow
|
||||||
|
Wants=network.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/podman start -a mailcow
|
||||||
|
ExecStop=/usr/bin/podman stop -t 10 mailcow
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Reload systemd and enable service for mailcow
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
name: podman-mailcow.service
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Ensure Podman is installed
|
||||||
|
apt:
|
||||||
|
name: podman
|
||||||
|
state: present
|
||||||
|
become: true
|
||||||
|
|
||||||
|
- name: Pull and run Podman services
|
||||||
|
include_tasks: run_service.yml
|
||||||
|
loop: "{{ podman_services }}"
|
||||||
|
loop_control:
|
||||||
|
loop_var: service
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
- name: Pull image for {{ service.name }}
|
||||||
|
containers.podman.podman_image:
|
||||||
|
name: "{{ service.image }}"
|
||||||
|
|
||||||
|
- name: Create data directory for {{ service.name }}
|
||||||
|
file:
|
||||||
|
path: "{{ service.data_dir }}"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ service.user | default('root') }}"
|
||||||
|
group: "{{ service.group | default('root') }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Run {{ service.name }} container
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: "{{ service.name }}"
|
||||||
|
image: "{{ service.image }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
ports: "{{ service.ports | default(omit) }}"
|
||||||
|
env: "{{ service.env | default({}) }}"
|
||||||
|
volumes: "{{ service.volumes | default([]) }}"
|
||||||
|
user: "{{ service.user | default(omit) }}"
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
- name: Deploy step_ca container with Podman
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: step_ca
|
||||||
|
image: "{{ step_ca_image }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
volumes:
|
||||||
|
- "{{ step_ca_data_dir }}:/data:z"
|
||||||
|
env:
|
||||||
|
CONFIG_PATH: "/data/config"
|
||||||
|
|
||||||
|
- name: Ensure systemd service is enabled for step_ca
|
||||||
|
copy:
|
||||||
|
dest: "/etc/systemd/system/podman-step_ca.service"
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Podman container for step_ca
|
||||||
|
Wants=network.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/podman start -a step_ca
|
||||||
|
ExecStop=/usr/bin/podman stop -t 10 step_ca
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Reload systemd and enable service for step_ca
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
name: podman-step_ca.service
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
- name: Deploy wazuh container with Podman
|
||||||
|
containers.podman.podman_container:
|
||||||
|
name: wazuh
|
||||||
|
image: "{{ wazuh_image }}"
|
||||||
|
state: started
|
||||||
|
restart_policy: always
|
||||||
|
volumes:
|
||||||
|
- "{{ wazuh_data_dir }}:/data:z"
|
||||||
|
env:
|
||||||
|
CONFIG_PATH: "/data/config"
|
||||||
|
|
||||||
|
- name: Ensure systemd service is enabled for wazuh
|
||||||
|
copy:
|
||||||
|
dest: "/etc/systemd/system/podman-wazuh.service"
|
||||||
|
content: |
|
||||||
|
[Unit]
|
||||||
|
Description=Podman container for wazuh
|
||||||
|
Wants=network.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/podman start -a wazuh
|
||||||
|
ExecStop=/usr/bin/podman stop -t 10 wazuh
|
||||||
|
Restart=always
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Reload systemd and enable service for wazuh
|
||||||
|
systemd:
|
||||||
|
daemon_reload: yes
|
||||||
|
name: podman-wazuh.service
|
||||||
|
enabled: yes
|
||||||
|
state: started
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
# 🔐 Ansible Role: secure_ubuntu
|
||||||
|
|
||||||
|
Harden an Ubuntu 22.04 LTS host to meet **CMMC Level 2** compliance requirements using a modular, auditable Ansible role.
|
||||||
|
|
||||||
|
This role configures:
|
||||||
|
- SSH and login security
|
||||||
|
- Non-root administrative user
|
||||||
|
- System auditing and file integrity monitoring
|
||||||
|
- UFW firewall
|
||||||
|
- Secure banners for compliance
|
||||||
|
- Automatic updates and password policies
|
||||||
|
|
||||||
|
## ✅ CMMC Practices Addressed
|
||||||
|
|
||||||
|
| Domain | Practice | Description |
|
||||||
|
|--------|---------------|---------------------------------------------------------|
|
||||||
|
| AC | AC.1.001 | Limit system access to authorized users |
|
||||||
|
| AC | AC.3.017 | Display system use notifications (login banner) |
|
||||||
|
| CM | CM.2.062 | Employ security configuration baseline |
|
||||||
|
| SI | SI.1.210 | Identify unauthorized use of systems |
|
||||||
|
| SI | SI.3.219 | Detect and report unauthorized changes to software |
|
||||||
|
|
||||||
|
## 📦 Requirements
|
||||||
|
|
||||||
|
- Ubuntu 22.04 LTS
|
||||||
|
- Ansible >= 2.11
|
||||||
|
|
||||||
|
## 🚀 Role Variables
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
secure_user: cmmcadmin
|
||||||
|
ssh_pubkey_path: "~/.ssh/id_rsa.pub"
|
||||||
|
```
|
||||||
|
|
||||||
|
> Set `ssh_pubkey_path` to the local path of the public key to be authorized for `secure_user`.
|
||||||
|
|
||||||
|
## 📁 Example Playbook
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Apply CMMC hardening baseline
|
||||||
|
hosts: all
|
||||||
|
become: yes
|
||||||
|
roles:
|
||||||
|
- role: secure_ubuntu
|
||||||
|
vars:
|
||||||
|
secure_user: cmmcadmin
|
||||||
|
ssh_pubkey_path: "~/.ssh/id_rsa.pub"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
roles/
|
||||||
|
└── secure_ubuntu/
|
||||||
|
├── defaults/
|
||||||
|
│ └── main.yml
|
||||||
|
├── meta/
|
||||||
|
│ └── main.yml
|
||||||
|
├── tasks/
|
||||||
|
│ ├── main.yml
|
||||||
|
│ ├── ssh.yml
|
||||||
|
│ ├── user.yml
|
||||||
|
│ ├── firewall.yml
|
||||||
|
│ ├── audit_aide.yml
|
||||||
|
│ ├── banner.yml
|
||||||
|
│ ├── updates.yml
|
||||||
|
│ └── password_policy.yml
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔒 License
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
## 🧠 Author
|
||||||
|
|
||||||
|
Maintained by **Kell Engineering**
|
||||||
|
https://github.com/mtkell/open-cmmc-stack
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
---
|
||||||
|
admin_user: cmmcadmin
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- name: Restart SSH
|
||||||
|
service:
|
||||||
|
name: ssh
|
||||||
|
state: restarted
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: secure_ubuntu
|
||||||
|
author: open-cmmc
|
||||||
|
description: Harden Ubuntu system for CMMC Level 2
|
||||||
|
license: MIT
|
||||||
|
min_ansible_version: "2.10"
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Install audit and integrity tools
|
||||||
|
apt:
|
||||||
|
name:
|
||||||
|
- auditd
|
||||||
|
- aide
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Initialize AIDE database
|
||||||
|
command: aideinit
|
||||||
|
args:
|
||||||
|
creates: /var/lib/aide/aide.db.gz
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
- name: Deploy system login banner
|
||||||
|
template:
|
||||||
|
src: banner.txt.j2
|
||||||
|
dest: /etc/banner.txt
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Apply banner for SSH
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/ssh/sshd_config
|
||||||
|
regexp: '^Banner'
|
||||||
|
line: 'Banner /etc/banner.txt'
|
||||||
|
notify: Restart SSH
|
||||||
|
|
||||||
|
- name: Apply banner for console (TTY)
|
||||||
|
copy:
|
||||||
|
src: /etc/banner.txt
|
||||||
|
dest: /etc/issue
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Apply banner for pre-login
|
||||||
|
copy:
|
||||||
|
src: /etc/banner.txt
|
||||||
|
dest: /etc/issue.net
|
||||||
|
mode: '0644'
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
- name: Install UFW firewall
|
||||||
|
apt:
|
||||||
|
name: ufw
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Set UFW default deny policy
|
||||||
|
ufw:
|
||||||
|
state: enabled
|
||||||
|
policy: deny
|
||||||
|
|
||||||
|
- name: Allow SSH through firewall
|
||||||
|
ufw:
|
||||||
|
rule: allow
|
||||||
|
port: "22"
|
||||||
|
proto: tcp
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
- name: Include SSH hardening tasks
|
||||||
|
import_tasks: ssh.yml
|
||||||
|
|
||||||
|
- name: Include firewall configuration
|
||||||
|
import_tasks: firewall.yml
|
||||||
|
|
||||||
|
- name: Include audit logging setup
|
||||||
|
import_tasks: audit.yml
|
||||||
|
|
||||||
|
- name: Include banner setup
|
||||||
|
import_tasks: banners.yml
|
||||||
|
|
||||||
|
- name: Include automatic update configuration
|
||||||
|
import_tasks: updates.yml
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Set password complexity
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/security/pwquality.conf
|
||||||
|
regexp: '^minlen'
|
||||||
|
line: 'minlen = 14'
|
||||||
|
|
||||||
|
- name: Lock out after 5 failed login attempts
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/pam.d/common-auth
|
||||||
|
line: 'auth required pam_tally2.so deny=5 onerr=fail unlock_time=900'
|
||||||
|
create: yes
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
- name: Disable root login over SSH
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/ssh/sshd_config
|
||||||
|
regexp: '^PermitRootLogin'
|
||||||
|
line: 'PermitRootLogin no'
|
||||||
|
notify: Restart SSH
|
||||||
|
|
||||||
|
- name: Disable password authentication
|
||||||
|
lineinfile:
|
||||||
|
path: /etc/ssh/sshd_config
|
||||||
|
regexp: '^PasswordAuthentication'
|
||||||
|
line: 'PasswordAuthentication no'
|
||||||
|
notify: Restart SSH
|
||||||
|
|
||||||
|
- name: Ensure non-root admin user exists
|
||||||
|
user:
|
||||||
|
name: cmmcadmin
|
||||||
|
shell: /bin/bash
|
||||||
|
groups: sudo
|
||||||
|
create_home: yes
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Add authorized SSH key for cmmcadmin
|
||||||
|
authorized_key:
|
||||||
|
user: cmmcadmin
|
||||||
|
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
- name: Install unattended-upgrades
|
||||||
|
apt:
|
||||||
|
name: unattended-upgrades
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Enable automatic security updates
|
||||||
|
copy:
|
||||||
|
dest: /etc/apt/apt.conf.d/20auto-upgrades
|
||||||
|
content: |
|
||||||
|
APT::Periodic::Update-Package-Lists "1";
|
||||||
|
APT::Periodic::Unattended-Upgrade "1";
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
- name: Ensure non-root user exists
|
||||||
|
user:
|
||||||
|
name: cmmcadmin
|
||||||
|
shell: /bin/bash
|
||||||
|
groups: sudo
|
||||||
|
state: present
|
||||||
|
create_home: yes
|
||||||
|
|
||||||
|
- name: Add authorized SSH key for cmmcadmin
|
||||||
|
authorized_key:
|
||||||
|
user: cmmcadmin
|
||||||
|
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
*** WARNING ***
|
||||||
|
|
||||||
|
This computer system is the property of {{ organization_name | default('Your Organization') }}. It is for authorized use only.
|
||||||
|
|
||||||
|
By accessing this system, you acknowledge and consent to the following:
|
||||||
|
- All information is subject to monitoring by authorized personnel.
|
||||||
|
- Unauthorized use may result in disciplinary action, civil penalties, or criminal prosecution.
|
||||||
|
- You agree to comply with all security and data handling policies.
|
||||||
|
|
||||||
|
This system is protected under CMMC Level 2 compliance controls.
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
---
|
||||||
|
- name: Test secure_ubuntu role on localhost
|
||||||
|
hosts: localhost
|
||||||
|
become: yes
|
||||||
|
gather_facts: true
|
||||||
|
|
||||||
|
vars:
|
||||||
|
secure_user: testadmin
|
||||||
|
ssh_pubkey_path: "~/.ssh/id_rsa.pub"
|
||||||
|
ssh_port: 22
|
||||||
|
|
||||||
|
roles:
|
||||||
|
- role: secure_ubuntu
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
- name: Harden Ubuntu for CMMC Stack
|
||||||
|
hosts: localhost
|
||||||
|
become: yes
|
||||||
|
roles:
|
||||||
|
- secure_ubuntu
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
---
|
||||||
|
- name: Apply baseline security and deploy OpenCMMC Stack
|
||||||
|
hosts: all
|
||||||
|
become: true
|
||||||
|
roles:
|
||||||
|
- role: secure_ubuntu
|
||||||
|
- role: identity
|
||||||
|
- role: podman_services
|
||||||
|
- role: file_storage
|
||||||
|
- role: monitoring
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 📌 Evidence – Scoping Documentation
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
This section documents the scoping boundaries for the OpenCMMC Stack environment. It includes diagrams, system inventory, and asset classification relevant to CMMC Level 2 compliance.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- Network/system diagrams
|
||||||
|
- Inventory list
|
||||||
|
- Boundary identification
|
||||||
|
- Cloud vs. on-prem segregation
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] Scope document reviewed by compliance officer
|
||||||
|
- [ ] Asset list includes all CUI-processing components
|
||||||
|
- [ ] Diagrams show trust boundaries and segmentation
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 🔐 Evidence – Identity and Access Management
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
This folder contains evidence showing how user accounts, roles, MFA, and authentication systems are managed via Keycloak and Tailscale.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- Realm export (`keycloak-realm-export.json`)
|
||||||
|
- Screenshots of MFA policy
|
||||||
|
- Group-to-role mapping export
|
||||||
|
- Tailscale ACL and device log
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] MFA enforced for all privileged users
|
||||||
|
- [ ] User roles mapped and validated
|
||||||
|
- [ ] Keycloak policies match SSP configuration
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 📋 Evidence – Ansible Execution Logs
|
||||||
|
|
||||||
|
## Description
|
||||||
|
This directory contains raw output of Ansible playbooks applied to the Ubuntu host.
|
||||||
|
|
||||||
|
## Artifacts
|
||||||
|
- `secure_ubuntu_run.log`
|
||||||
|
- `ansible-playbook-timestamped.json`
|
||||||
|
- Output showing configuration and user enforcement
|
||||||
|
|
||||||
|
## Reviewer Notes
|
||||||
|
Ensure playbook includes:
|
||||||
|
- SSH key enforcement
|
||||||
|
- Root login disabled
|
||||||
|
- Required auditd and aide tasks completed
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 🛡️ Evidence – System Hardening
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Evidence of host OS and container baseline security including hardened configurations, SSH controls, and auditd/aide logs.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- Ansible playbook logs
|
||||||
|
- Auditd rules and logs
|
||||||
|
- SSH daemon configs
|
||||||
|
- AIDE database init and scan result
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] Ansible logs show successful hardening
|
||||||
|
- [ ] Login banners and password policies verified
|
||||||
|
- [ ] Audit and integrity scans scheduled
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 📁 Evidence – File Sharing & Collaboration
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Evidence of Nextcloud AIO configuration for secure file sharing and internal team access controls.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- SAML config screenshots
|
||||||
|
- File Access Control rules
|
||||||
|
- Team Folder setup for CUI/FCI
|
||||||
|
- Antivirus scanner logs
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] Access control groups defined
|
||||||
|
- [ ] External sharing is blocked for CUI
|
||||||
|
- [ ] Antivirus scans for uploads are active
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# ✉️ Evidence – Secure Email Configuration
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Evidence related to the secure deployment and configuration of Mailcow for sending and receiving secure communications.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- TLS/DKIM/SPF reports
|
||||||
|
- SSO integration with Keycloak
|
||||||
|
- Mail logs for delivery success and rejection
|
||||||
|
- Email relay and filter rules
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] DKIM keys configured and tested
|
||||||
|
- [ ] TLS enforced on all SMTP/IMAP traffic
|
||||||
|
- [ ] Mailcow access restricted via Tailscale ACLs
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 📡 Evidence – Monitoring & SIEM Integration
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Evidence supporting logging, alerting, and forensic readiness using Wazuh and system-level audit mechanisms.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- Wazuh agent and server logs
|
||||||
|
- SIEM dashboard screenshots
|
||||||
|
- Custom alert rules
|
||||||
|
- Log forwarding rules (if applicable)
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] Agent deployment logs available
|
||||||
|
- [ ] Alerts fire on auth failures, sudo, etc.
|
||||||
|
- [ ] Central log retention meets policy
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 💾 Evidence – Backups & Recovery Testing
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Documentation of backup routines, tools (Restic/Borg), encrypted vaults, and restore verification processes.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- Restic/Borg configuration files
|
||||||
|
- Restore logs and diffs
|
||||||
|
- Encryption key storage policy
|
||||||
|
- Backup rotation reports
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] Encryption is enabled at rest
|
||||||
|
- [ ] Monthly restore test logs present
|
||||||
|
- [ ] Offsite backup location validated
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# 📜 Evidence – Policies and Administrative Controls
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
This section contains administrative control evidence including signed policies, role assignments, and procedure documents.
|
||||||
|
|
||||||
|
## Included Artifacts
|
||||||
|
- Access control policy (AC-1)
|
||||||
|
- Incident response plan
|
||||||
|
- User onboarding/offboarding procedures
|
||||||
|
- Policy acceptance logs
|
||||||
|
|
||||||
|
## Review Checklist
|
||||||
|
- [ ] Policies approved and version controlled
|
||||||
|
- [ ] All users have acknowledged relevant policies
|
||||||
|
- [ ] Procedures align with technical implementation
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/bash
|
||||||
|
apt update && apt install -y git python3-pip curl ufw
|
||||||
|
pip3 install ansible
|
||||||
|
ufw allow OpenSSH
|
||||||
|
ufw --force enable
|
||||||
|
git clone https://github.com/mtkell/open-cmmc-stack.git /opt/open-cmmc-stack
|
||||||
|
cd /opt/open-cmmc-stack/ansible
|
||||||
|
ansible-playbook -i localhost, secure_ubuntu.yml
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
provider "digitalocean" {
|
||||||
|
token = var.do_token
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "digitalocean_droplet" "secure_host" {
|
||||||
|
name = "cmmc-hardened"
|
||||||
|
region = "nyc3"
|
||||||
|
size = "s-2vcpu-4gb"
|
||||||
|
image = "ubuntu-22-04-x64"
|
||||||
|
ssh_keys = [var.ssh_fingerprint]
|
||||||
|
user_data = file("${path.module}/bootstrap.sh")
|
||||||
|
|
||||||
|
tags = ["cmmc", "secure-host"]
|
||||||
|
}
|
||||||
|
|
||||||
|
output "droplet_ip" {
|
||||||
|
value = digitalocean_droplet.secure_host.ipv4_address
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
do_token = "your_digitalocean_token_here"
|
||||||
|
ssh_fingerprint = "your_local_ssh_key_fingerprint"
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
variable "do_token" {
|
||||||
|
description = "DigitalOcean API token"
|
||||||
|
type = string
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "ssh_fingerprint" {
|
||||||
|
description = "Your public SSH key fingerprint registered with DigitalOcean"
|
||||||
|
type = string
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue