Compare commits
74 Commits
26dd315bc0
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b5e2352bc | |||
| 14e11a40db | |||
| 505271fcba | |||
| 6107513f72 | |||
| 4c18590881 | |||
| a6bdc70932 | |||
| 47cdaee59c | |||
| af20d1dd86 | |||
| 809be488f2 | |||
| e9b75e9972 | |||
| c30201da11 | |||
| 51a15d5e04 | |||
| 8d740e77a6 | |||
| 6a926da12a | |||
| b6eb405236 | |||
| 7fdf0e95e3 | |||
| 3b08c991cd | |||
| 8e7a4e4b5d | |||
| 82dc88e827 | |||
| 8c3adc6cf9 | |||
| e0389aae85 | |||
| b4408b2dfe | |||
| 7f560f7653 | |||
| 2b97e9b61b | |||
| 89e5606a4a | |||
| 43f0ef58e7 | |||
| b5b3d9384f | |||
| b87ab88f52 | |||
| 6db8e3d015 | |||
| 1bf10307a6 | |||
| 257d4b925d | |||
| bb99d469fe | |||
| bfdd2d07b3 | |||
| e74f9bdb31 | |||
| 9cad7d3b64 | |||
| fc0aeb908e | |||
| a48b146e81 | |||
| 38858590f8 | |||
| 7205d9870e | |||
| b9355e6539 | |||
| 0d6e747ba8 | |||
| 767ebb022b | |||
| 6afc14a362 | |||
| e19c0f8b48 | |||
| a8a18f93df | |||
| c76545e816 | |||
| e70b483274 | |||
| e150a3306d | |||
| 69e83cb83a | |||
| 79fccba876 | |||
| 47b0eef15d | |||
| a95fbd4822 | |||
| 3e62e137da | |||
| e9382d195f | |||
| 7374c1fb52 | |||
| 7fd16e195f | |||
| 07d516d8ea | |||
| ba75d48ea6 | |||
| 42da69befb | |||
| f85c420c14 | |||
| 92f2c4eb4b | |||
| d1961671d2 | |||
| d7efdd1d9a | |||
| 497cb6cbf5 | |||
| 7e7c8a4b2d | |||
| 8406e1eab6 | |||
| 50dcdfdfbe | |||
| 36a4ac99ed | |||
| e6e7f22592 | |||
| 570500c886 | |||
| 843ebd52a8 | |||
| 6078e8d9b9 | |||
| 6c75e2910b | |||
| 0104e69124 |
161
README.md
161
README.md
@@ -1,86 +1,145 @@
|
|||||||
# Ansible Role: samba_ad_dc
|
# Ansible Role: samba_ad_dc
|
||||||
|
|
||||||
Ansible role to **install**, **provision**, and optionally **remove** a Samba Active Directory Domain Controller (AD DC) on **Debian-based systems** (e.g., Debian, Ubuntu).
|
Ansible role to **install**, **provision**, and optionally **remove** a Samba Active Directory Domain Controller (AD DC) on **Debian‑based systems** (Debian, Ubuntu, etc.).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ✅ Features
|
## ✅ Features
|
||||||
|
|
||||||
- Installs and configures Samba as an AD Domain Controller
|
* Installs & configures Samba as an AD DC
|
||||||
- Uses `samba-tool` to provision the domain
|
* Provisions the domain with `samba-tool`
|
||||||
- Idempotent: Won't re-provision if already set up
|
* Idempotent – skips provisioning if the domain is already present
|
||||||
- Reversible: Set `state: absent` to cleanly remove Samba AD DC
|
* Reversible – `state: absent` cleans up the DC
|
||||||
- Sets up `/etc/hosts` and DNS resolver
|
* Sets up `/etc/hosts` + a **static** `/etc/resolv.conf`
|
||||||
- Separate Kerberos configuration
|
* Disables services that would otherwise overwrite `/etc/resolv.conf`
|
||||||
- Logging of provisioning
|
(systemd‑resolved, `resolvconf`, `NetworkManager` DNS, `dhclient`)
|
||||||
- Molecule tests included for both `present` and `absent` states
|
* Configures a local NTP daemon (`ntp.conf` + `ntp_signd`) for time‑sync
|
||||||
|
* Keeps a **per‑host backup** of the Samba config files
|
||||||
|
* Molecule tests cover both `present` and `absent` states
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Role Variables
|
## 📦 Role Variables
|
||||||
|
|
||||||
### Main Variables
|
### Core Samba / Kerberos variables
|
||||||
|
|
||||||
| Variable | Description | Default |
|
| Variable | Description | Default value |
|
||||||
|--------------------------|----------------------------------------------|----------------------|
|
|-------------------------|---------------------------------------------|-----------------------------|
|
||||||
| `samba_ad_dc_state` | `present` to install, `absent` to remove | `present` |
|
| `samba_ad_dc_state` | `present` → install, `absent` → remove | `present` |
|
||||||
| `samba_realm` | Kerberos Realm (e.g., `EXAMPLE.COM`) | `EXAMPLE.COM` |
|
| `samba_realm` | Kerberos realm (e.g., `CORP.EXAMPLE.COM`) | `EXAMPLE.COM` |
|
||||||
| `samba_domain` | NetBIOS domain name (e.g., `EXAMPLE`) | `EXAMPLE` |
|
| `samba_domain` | NetBIOS domain name (e.g., `CORP`) | `EXAMPLE` |
|
||||||
| `samba_admin_password` | Admin password for the domain | `StrongAdminPassword123!` |
|
| `samba_admin_password` | Password for the domain administrator | `StrongAdminPassword123!` |
|
||||||
| `samba_dns_backend` | DNS backend (`SAMBA_INTERNAL`, `BIND9_DLZ`) | `SAMBA_INTERNAL` |
|
| `samba_dns_backend` | DNS backend (`SAMBA_INTERNAL`/`BIND9_DLZ`) | `SAMBA_INTERNAL` |
|
||||||
| `samba_hostname` | Hostname for the server | `inventory_hostname` |
|
| `samba_hostname` | Hostname that will appear in `smb.conf` | `inventory_hostname` |
|
||||||
|
|
||||||
|
### Extended configuration variables (see `defaults/main.yml`)
|
||||||
|
|
||||||
|
| Variable | Description | Default value |
|
||||||
|
|-----------------------|-------------------------------------------------|---------------|
|
||||||
|
| `samba_packages` | Packages to install when `state: present`. Includes the full list needed for a Debian/Ubuntu AD DC. | *See the YAML block below* |
|
||||||
|
| `location_internal_dns` | Internal DNS server used in `/etc/resolv.conf` | `192.168.1.1` |
|
||||||
|
| `location_external_dns` | External (fallback) DNS server | `8.8.8.8` |
|
||||||
|
| `backup_path` | Directory where the role will store a backup of
|
||||||
|
`/etc/samba`, `/etc/krb5.conf`, and other files. | `"/path/to/your/backup/directory"` |
|
||||||
|
|
||||||
|
> **NOTE** – the `samba_packages` block is kept for clarity, but it is *not* an
|
||||||
|
> **Ansible variable** you set on the host; it simply holds the list that
|
||||||
|
> `tasks/install.yml` uses.
|
||||||
|
|
||||||
|
### NTP configuration
|
||||||
|
|
||||||
|
The role also deploys an NTP daemon (file: `tasks/ntpd.yml`):
|
||||||
|
|
||||||
|
* **`/etc/ntp.conf`** is rendered from `templates/ntp.conf.j2`
|
||||||
|
* The NTP service is enabled & started automatically
|
||||||
|
* The handler `Restart ntp service` is called whenever the config changes
|
||||||
|
|
||||||
|
### DNS‑prep
|
||||||
|
|
||||||
|
`tasks/preparing.yml` performs the following important housekeeping steps
|
||||||
|
before any Samba configuration:
|
||||||
|
|
||||||
|
1. Stops and disables `systemd-resolved` (if present).
|
||||||
|
2. Removes `/etc/resolv.conf` when it is a symlink to the resolver.
|
||||||
|
3. Creates a **static** `/etc/resolv.conf` that contains both your internal
|
||||||
|
and external nameservers (`location_internal_dns`, `location_external_dns`).
|
||||||
|
4. Uninstalls the `resolvconf` package (if it is installed).
|
||||||
|
5. Prevents NetworkManager from writing DNS entries by editing
|
||||||
|
`/etc/NetworkManager/NetworkManager.conf`.
|
||||||
|
6. Prevents `dhclient` from touching `/etc/resolv.conf` (implementation left
|
||||||
|
to the user – you can add a `blockinfile` task or a similar file‑lock).
|
||||||
|
|
||||||
|
> **Tip** – if you ever run into “no DNS resolution” on the host *after* the role has finished, double‑check that
|
||||||
|
> `systemd-resolved` is truly disabled and that `/etc/resolv.conf` is **not** a symlink.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🧰 Example Playbook
|
## 📁 Included Task Files
|
||||||
|
|
||||||
```yaml
|
| File | Purpose |
|
||||||
- hosts: samba
|
|--------------------------|---------|
|
||||||
become: true
|
| `tasks/install.yml` | Installs packages, configures NTP & DNS, then provisions Samba |
|
||||||
roles:
|
| `tasks/remove.yml` | Stops & removes Samba packages + cleans up files |
|
||||||
- role: samba_ad_dc
|
| `tasks/kerberos.yml` | Copies `krb5.conf.j2` → `/etc/krb5.conf` |
|
||||||
vars:
|
| `tasks/verify.yml` | Runs `samba-tool` checks + `kinit` tests |
|
||||||
samba_realm: "CORP.EXAMPLE.COM"
|
| `tasks/dns_hosts.yml` | Ensures `/etc/hosts` contains the DC record |
|
||||||
samba_domain: "CORP"
|
| `tasks/logging.yml` | Stores provisioning output to a log file |
|
||||||
samba_admin_password: "SuperSecretPassw0rd!"
|
| `tasks/preparing.yml` | Disables `systemd-resolved`, `resolvconf`, `NetworkManager`, and creates a static `/etc/resolv.conf` |
|
||||||
|
| `tasks/ntpd.yml` | Configures NTP (template `ntp.conf.j2`) and ensures it is running |
|
||||||
|
|
||||||
❌ Remove Samba AD DC
|
---
|
||||||
- hosts: samba
|
|
||||||
become: true
|
|
||||||
roles:
|
|
||||||
- role: samba_ad_dc
|
|
||||||
vars:
|
|
||||||
samba_ad_dc_state: absent
|
|
||||||
|
|
||||||
📁 Included Tasks
|
## 🧩 Compatibility
|
||||||
|
|
||||||
install.yml: Installs and provisions Samba AD
|
* **Operating systems**: Debian 10/11/12 + , Ubuntu 20.04/22.04+
|
||||||
|
* **Ansible**: 2.9 + (the role uses only core modules)
|
||||||
|
|
||||||
remove.yml: Stops and removes Samba AD
|
---
|
||||||
|
|
||||||
kerberos.yml: Configures Kerberos (/etc/krb5.conf)
|
## 🔒 Security Notes
|
||||||
|
|
||||||
verify.yml: Validates the installation (samba-tool, kinit)
|
* Store `samba_admin_password` in Ansible Vault in production.
|
||||||
|
* The role backs up the Samba configuration to the directory defined by
|
||||||
|
`backup_path` – see `tasks/logging.yml` for how the backup is created.
|
||||||
|
|
||||||
dns_hosts.yml: Ensures /etc/hosts and DNS resolvers are set
|
---
|
||||||
|
|
||||||
logging.yml: Logs provisioning output
|
## 📄 Templates
|
||||||
|
|
||||||
📄 Templates
|
| Template | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `templates/smb.conf.j2` | Samba configuration for the AD DC |
|
||||||
|
| `templates/krb5.conf.j2` | Kerberos client config |
|
||||||
|
| `templates/resolv.conf.j2` | Static `/etc/resolv.conf` (search domain + nameserver) |
|
||||||
|
| `templates/ntp.conf.j2` | NTP configuration used by `tasks/ntpd.yml` |
|
||||||
|
|
||||||
smb.conf.j2: Samba configuration
|
---
|
||||||
|
|
||||||
krb5.conf.j2: Kerberos configuration
|
## 🛠️ Troubleshooting
|
||||||
|
|
||||||
🔒 Security Notes
|
| Issue | What to check |
|
||||||
|
|-------|---------------|
|
||||||
|
| `samba-tool domain provision` fails with a password error | Verify `samba_admin_password` is correct and **no‑log** (`no_log: true`) is set. |
|
||||||
|
| DNS resolution fails on the DC itself | Ensure `samba_iface` contains `lo` **and** the NIC (e.g., `lo eth0`) and that `/etc/resolv.conf` is not a symlink. |
|
||||||
|
| Time skew on the DC | Verify NTP service is running (`systemctl status ntp`). |
|
||||||
|
| Backup directory missing | Check that `backup_path` is writable by the user running the playbook. |
|
||||||
|
|
||||||
Passwords should be stored in Ansible Vault for production.
|
---
|
||||||
|
|
||||||
DNS and Kerberos configuration assumes internal AD DNS — adjust for external resolvers if needed.
|
## 📥 Install via Ansible Galaxy
|
||||||
|
|
||||||
🧩 Compatibility
|
```bash
|
||||||
|
ansible-galaxy init samba_ad_dc
|
||||||
|
```
|
||||||
|
|
||||||
OS: Debian 10/11/12+, Ubuntu 20.04/22.04+
|
After adding this file, run:
|
||||||
|
|
||||||
Ansible: 2.9+
|
```bash
|
||||||
|
ansible-galaxy collection install samba_ad_dc
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
Feel free to submit PRs – just keep the variable documentation in sync with the files you modify. Happy automating!
|
||||||
@@ -1,25 +1,55 @@
|
|||||||
samba_ad_dc_state: present # or 'absent'
|
|
||||||
|
|
||||||
# AD Provisioning details
|
# AD Provisioning details
|
||||||
samba_realm: "EXAMPLE.COM"
|
# Hostname = DC1
|
||||||
samba_domain: "EXAMPLE"
|
addc_hostname: 'DC1'
|
||||||
samba_admin_password: "StrongAdminPassword123!"
|
# DC local IP Address = 10.99.0.1
|
||||||
samba_dns_backend: "SAMBA_INTERNAL"
|
addc_ansible_host: '10.99.0.1'
|
||||||
samba_hostname: "{{ inventory_hostname }}"
|
# NetBIOS domain name (Workgroup).
|
||||||
|
addc_netbios_domain: 'SAMDOM'
|
||||||
|
# Top level Domain = EXAMPLE.COM
|
||||||
|
addc_tld: 'EXAMPLE.COM'
|
||||||
|
# Authentication Domain = SAMDOM.EXAMPLE.COM
|
||||||
|
addc_auth_domain: '{{ addc_netbios_domain | upper }}.{{ addc_tld | upper }}'
|
||||||
|
|
||||||
samba_log_dir: /var/log/samba
|
addc_admin_password: 'Passw0rd'
|
||||||
samba_provision_log_file: "{{ samba_log_dir }}/ad_provision.log"
|
addc_dns_backend: 'SAMBA_INTERNAL'
|
||||||
|
addc_server_role: 'dc'
|
||||||
|
|
||||||
# allows skipping verification when needed
|
addc_ip_network_prefix: "{{ addc_ansible_host.split('.')[:3] | join('.') }}"
|
||||||
samba_verify: true
|
addc_ip_last_octet: "{{ addc_ansible_host.split('.')[-1] }}"
|
||||||
|
addc_reverse_zone_name: "{{ addc_ip_network_prefix.split('.') | reverse | join('.') }}.in-addr.arpa"
|
||||||
|
|
||||||
|
samba_domain_info:
|
||||||
|
realm: '{{ addc_auth_domain | upper }}'
|
||||||
|
domain: '{{ addc_netbios_domain | upper }}'
|
||||||
|
server_role: "{{ addc_server_role | default('dc') }}"
|
||||||
|
dns_backend: "{{ addc_dns_backend | default('SAMBA_INTERNAL') }}"
|
||||||
|
adminpass: '{{ addc_admin_password }}'
|
||||||
|
interfaces: "{{ samba_iface_list | join(' ') }}"
|
||||||
|
bind_interfaces_only: 'yes'
|
||||||
|
|
||||||
|
samba_iface_list:
|
||||||
|
- lo
|
||||||
|
- eth0
|
||||||
|
|
||||||
|
samba_packages:
|
||||||
|
- acl
|
||||||
|
- attr
|
||||||
|
- samba
|
||||||
|
- winbind
|
||||||
|
- libpam-winbind
|
||||||
|
- libnss-winbind
|
||||||
|
- krb5-config
|
||||||
|
- krb5-user
|
||||||
|
- bind9-dnsutils
|
||||||
|
# - dnsutils
|
||||||
|
- python3-setproctitle
|
||||||
|
# - smbclient
|
||||||
|
- samba-ad-dc
|
||||||
|
- smbclient # Debian/Ubuntu
|
||||||
|
- samba-client # RHEL family (it will skip if not available)
|
||||||
|
|
||||||
# template for /etc/resolv.conf
|
# template for /etc/resolv.conf
|
||||||
samba_dns_nameservers:
|
location_internal_dns: 192.168.1.1
|
||||||
- 127.0.0.1
|
location_external_dns: 8.8.8.8
|
||||||
- 8.8.8.8
|
|
||||||
samba_resolv_conf_backup_path: /etc/resolv.conf.ansible.bak
|
|
||||||
|
|
||||||
# Internal state tracking
|
|
||||||
samba_samdb_path: "/var/lib/samba/private/sam.ldb"
|
|
||||||
samba_conf_path: "/etc/samba/smb.conf"
|
|
||||||
|
|
||||||
|
backup_path: '/path/to/your/backup/directory'
|
||||||
@@ -1,5 +1,15 @@
|
|||||||
---
|
---
|
||||||
|
- name: Restart NetworkManager
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: NetworkManager
|
||||||
|
state: restarted
|
||||||
|
|
||||||
- name: Restart Samba AD DC
|
- name: Restart Samba AD DC
|
||||||
service:
|
ansible.builtin.service:
|
||||||
name: samba-ad-dc
|
name: samba-ad-dc
|
||||||
state: restarted
|
state: restarted
|
||||||
|
|
||||||
|
- name: Restart ntp service
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: ntp
|
||||||
|
state: restarted
|
||||||
12
meta/main.yml
Normal file
12
meta/main.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: Jose
|
||||||
|
description: Setup Samba AD DC
|
||||||
|
# license: MIT
|
||||||
|
# min_ansible_version: 2.9
|
||||||
|
# platforms:
|
||||||
|
# - name: Debian
|
||||||
|
# versions:
|
||||||
|
# - buster
|
||||||
|
# - bullseye
|
||||||
|
dependencies: []
|
||||||
56
tasks/0backupcheck.yml
Normal file
56
tasks/0backupcheck.yml
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
- name: Check if backup directory exists
|
||||||
|
stat:
|
||||||
|
path: '{{ backup_path }}'
|
||||||
|
register: backup_dir_stat
|
||||||
|
|
||||||
|
- name: Check if backup directory is not empty
|
||||||
|
find:
|
||||||
|
paths: '{{ backup_path }}'
|
||||||
|
file_type: any
|
||||||
|
recurse: false
|
||||||
|
when: backup_dir_stat.stat.exists and backup_dir_stat.stat.isdir
|
||||||
|
register: backup_dir_contents
|
||||||
|
|
||||||
|
|
||||||
|
- name: Check if each required file exists
|
||||||
|
stat:
|
||||||
|
path: '{{ dir_path }}/{{ item }}'
|
||||||
|
loop: '{{ backup_required_files }}'
|
||||||
|
register: required_file_stats
|
||||||
|
|
||||||
|
- name: Determine missing files
|
||||||
|
set_fact:
|
||||||
|
missing_files: >-
|
||||||
|
{{ required_file_stats.results
|
||||||
|
| selectattr('stat.exists', 'equalto', false)
|
||||||
|
| map(attribute='item')
|
||||||
|
| list }}
|
||||||
|
|
||||||
|
- name: Set fact if all required files are present
|
||||||
|
set_fact:
|
||||||
|
all_required_files_present: true
|
||||||
|
when: missing_files | length == 0
|
||||||
|
|
||||||
|
- name: Debug - Show status
|
||||||
|
debug:
|
||||||
|
msg: >-
|
||||||
|
{% if all_required_files_present | default(false) %}
|
||||||
|
All required files are present.
|
||||||
|
{% else %}
|
||||||
|
Missing required files: {{ missing_files }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
- name: Set fact if backup directory exists and is not empty
|
||||||
|
set_fact:
|
||||||
|
backup_dir_valid: true
|
||||||
|
when:
|
||||||
|
- backup_dir_stat.stat.exists
|
||||||
|
- backup_dir_stat.stat.isdir
|
||||||
|
- backup_dir_contents.matched | int > 0
|
||||||
|
- all_required_files_present
|
||||||
|
|
||||||
|
- name: Debug - Show final result
|
||||||
|
debug:
|
||||||
|
msg: 'Backup directory exists and is not empty.'
|
||||||
|
when: backup_dir_valid | default(false)
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Backup original /etc/resolv.conf if not already backed up
|
|
||||||
copy:
|
|
||||||
src: /etc/resolv.conf
|
|
||||||
dest: "{{ samba_resolv_conf_backup_path }}"
|
|
||||||
remote_src: yes
|
|
||||||
force: no
|
|
||||||
when:
|
|
||||||
- samba_ad_dc_state == "present"
|
|
||||||
- ansible_virtualization_type != "docker"
|
|
||||||
|
|
||||||
- name: Template /etc/resolv.conf with custom DNS nameservers
|
|
||||||
template:
|
|
||||||
src: resolv.conf.j2
|
|
||||||
dest: /etc/resolv.conf
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: '0644'
|
|
||||||
when:
|
|
||||||
- samba_ad_dc_state == "present"
|
|
||||||
- ansible_virtualization_type != "docker"
|
|
||||||
|
|
||||||
- name: Set /etc/hosts entry for Samba AD DC
|
|
||||||
lineinfile:
|
|
||||||
path: /etc/hosts
|
|
||||||
line: "{{ ansible_default_ipv4.address }} {{ samba_hostname }}.{{ samba_realm | lower }} {{ samba_hostname }}"
|
|
||||||
state: present
|
|
||||||
create: yes
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Restore original /etc/resolv.conf from backup
|
|
||||||
copy:
|
|
||||||
src: "{{ samba_resolv_conf_backup_path }}"
|
|
||||||
dest: /etc/resolv.conf
|
|
||||||
remote_src: yes
|
|
||||||
force: yes
|
|
||||||
when:
|
|
||||||
- samba_ad_dc_state == "absent"
|
|
||||||
- ansible_virtualization_type != "docker"
|
|
||||||
- samba_resolv_conf_backup_path is defined
|
|
||||||
@@ -1,47 +1,161 @@
|
|||||||
---
|
---
|
||||||
|
# - name: Install pexpect # required for verify.yml
|
||||||
|
# ansible.builtin.apt:
|
||||||
|
# pkg: pexpect
|
||||||
|
# state: latest
|
||||||
|
|
||||||
- name: Install required packages
|
- name: Install required packages
|
||||||
apt:
|
ansible.builtin.apt:
|
||||||
name:
|
pkg: '{{ samba_packages }}'
|
||||||
- samba
|
state: latest
|
||||||
- krb5-config
|
# update_cache: yes
|
||||||
- krb5-user
|
autoclean: yes
|
||||||
- winbind
|
autoremove: yes
|
||||||
- smbclient
|
purge: true
|
||||||
- dnsutils
|
|
||||||
state: present
|
|
||||||
update_cache: yes
|
|
||||||
|
|
||||||
- name: Stop samba-ad-dc before provisioning (if running)
|
# - name: Install required packages
|
||||||
service:
|
# ansible.builtin.package:
|
||||||
name: samba-ad-dc
|
# name: '{{ samba_packages }}'
|
||||||
|
# state: latest
|
||||||
|
|
||||||
|
# - name: Stop samba-ad-dc before provisioning (if running)
|
||||||
|
# ansible.builtin.service:
|
||||||
|
# name: samba-ad-dc
|
||||||
|
# state: stopped
|
||||||
|
# enabled: no
|
||||||
|
# ignore_errors: true
|
||||||
|
|
||||||
|
# known regression in certain Samba 4.22.x builds
|
||||||
|
|
||||||
|
# - name: Check installed Samba version
|
||||||
|
# ansible.builtin.command: samba --version
|
||||||
|
# register: samba_version
|
||||||
|
# changed_when: false
|
||||||
|
# failed_when: false
|
||||||
|
|
||||||
|
# - name: Show installed Samba version
|
||||||
|
# ansible.builtin.debug:
|
||||||
|
# msg: "Samba version: {{ samba_version.stdout }}"
|
||||||
|
|
||||||
|
# - name: Warn if Samba version is 4.22.4
|
||||||
|
# ansible.builtin.debug:
|
||||||
|
# msg: "⚠️ Detected buggy Samba version 4.22.4 — upgrade recommended!"
|
||||||
|
# when: "'4.22.4' in samba_version.stdout"
|
||||||
|
|
||||||
|
# - name: Add Samba Team Debian GPG key (modern method)
|
||||||
|
# ansible.builtin.get_url:
|
||||||
|
# # url: https://pkg.samba.org/keys/samba-pubkey.asc
|
||||||
|
# url: https://download.samba.org/pub/samba/samba-pubkey.asc
|
||||||
|
# dest: /usr/share/keyrings/samba-team-archive-keyring.gpg
|
||||||
|
# mode: '0644'
|
||||||
|
# when: "'4.22.4' in samba_version.stdout"
|
||||||
|
|
||||||
|
# - name: Add Samba Team Debian repository (modern method)
|
||||||
|
# ansible.builtin.apt_repository:
|
||||||
|
# # repo: "deb [signed-by=/usr/share/keyrings/samba-team-archive-keyring.gpg] http://pkg.samba.org/packages/debian {{ ansible_lsb.codename | default('bookworm') }} samba-422"
|
||||||
|
# repo: "deb [signed-by=/usr/share/keyrings/samba-team-archive-keyring.gpg] http://download.samba.org/pub/samba/packages/debian {{ ansible_distribution_release }} samba-422"
|
||||||
|
# state: present
|
||||||
|
# filename: samba-team
|
||||||
|
# when: "'4.22.4' in samba_version.stdout"
|
||||||
|
|
||||||
|
# - name: Add Samba Team Debian GPG key (only if upgrade is needed)
|
||||||
|
# ansible.builtin.apt_key:
|
||||||
|
# url: https://pkg.samba.org/keys/samba-pubkey.asc
|
||||||
|
# state: present
|
||||||
|
# when: "'4.22.4' in samba_version.stdout"
|
||||||
|
|
||||||
|
# - name: Add Samba Team Debian repository (only if upgrade is needed)
|
||||||
|
# ansible.builtin.apt_repository:
|
||||||
|
# repo: "deb http://pkg.samba.org/packages/debian $(lsb_release -cs) samba-422"
|
||||||
|
# state: present
|
||||||
|
# filename: samba-team
|
||||||
|
# when: "'4.22.4' in samba_version.stdout"
|
||||||
|
|
||||||
|
# - name: Update APT cache (only if upgrade is needed)
|
||||||
|
# ansible.builtin.apt:
|
||||||
|
# update_cache: yes
|
||||||
|
# when: "'4.22.4' in samba_version.stdout"
|
||||||
|
|
||||||
|
# - name: Upgrade Samba packages if version is 4.22.4
|
||||||
|
# ansible.builtin.apt:
|
||||||
|
# name:
|
||||||
|
# - samba
|
||||||
|
# - samba-dsdb-modules
|
||||||
|
# - samba-common-bin
|
||||||
|
# - python3-samba
|
||||||
|
# state: latest
|
||||||
|
# when: "'4.22.4' in samba_version.stdout"
|
||||||
|
|
||||||
|
# - name: Verify installed Samba version
|
||||||
|
# ansible.builtin.command: samba --version
|
||||||
|
# register: samba_version
|
||||||
|
# changed_when: false
|
||||||
|
|
||||||
|
# - name: Display upgraded Samba version
|
||||||
|
# ansible.builtin.debug:
|
||||||
|
# msg: "✅ Samba version after upgrade: {{ samba_version.stdout }}"
|
||||||
|
|
||||||
|
# - name: Stop Samba services before provisioning
|
||||||
|
# ansible.builtin.service:
|
||||||
|
# name: '{{ item }}'
|
||||||
|
# state: stopped
|
||||||
|
# ignore_errors: true
|
||||||
|
# loop:
|
||||||
|
# - samba-ad-dc
|
||||||
|
# - smbd
|
||||||
|
# - nmbd
|
||||||
|
# - winbind
|
||||||
|
|
||||||
|
- name: Disable and stop regular Samba services
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: "{{ item }}"
|
||||||
|
enabled: false
|
||||||
state: stopped
|
state: stopped
|
||||||
enabled: no
|
masked: true
|
||||||
ignore_errors: yes
|
loop:
|
||||||
|
- smbd
|
||||||
|
- nmbd
|
||||||
|
- winbind
|
||||||
|
|
||||||
- name: Provision AD domain
|
- name: Unmask and enable Samba AD/DC service (but do not start it)
|
||||||
include_tasks: provision.yml
|
ansible.builtin.systemd:
|
||||||
|
|
||||||
- name: Deploy smb.conf
|
|
||||||
template:
|
|
||||||
src: smb.conf.j2
|
|
||||||
dest: "{{ samba_conf_path }}"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: '0644'
|
|
||||||
notify: Restart Samba AD DC
|
|
||||||
|
|
||||||
- name: Enable and start samba-ad-dc service
|
|
||||||
service:
|
|
||||||
name: samba-ad-dc
|
name: samba-ad-dc
|
||||||
state: started
|
masked: false
|
||||||
enabled: yes
|
enabled: true
|
||||||
|
state: stopped
|
||||||
|
|
||||||
- name: Configure Kerberos
|
|
||||||
include_tasks: kerberos.yml
|
|
||||||
|
|
||||||
- name: Set DNS resolver and hosts entry
|
|
||||||
include_tasks: dns_hosts.yml
|
|
||||||
|
|
||||||
- name: Run verification checks
|
|
||||||
include_tasks: verify.yml
|
|
||||||
when: samba_verify | bool
|
|
||||||
|
|
||||||
|
# - name: Check if backup exist
|
||||||
|
|
||||||
|
# - name: Provision AD domain
|
||||||
|
# include_tasks: provision.yml
|
||||||
|
|
||||||
|
# - name: Deploy smb.conf
|
||||||
|
# ansible.builtin.template:
|
||||||
|
# src: smb.conf.j2
|
||||||
|
# dest: '{{ samba_conf_path }}'
|
||||||
|
# owner: root
|
||||||
|
# group: root
|
||||||
|
# mode: '0644'
|
||||||
|
# notify: Restart Samba AD DC
|
||||||
|
|
||||||
|
# - name: Enable and start samba-ad-dc service
|
||||||
|
# ansible.builtin.service:
|
||||||
|
# name: samba-ad-dc
|
||||||
|
# state: started
|
||||||
|
# enabled: yes
|
||||||
|
|
||||||
|
# - name: Configure Kerberos
|
||||||
|
# include_tasks: kerberos.yml
|
||||||
|
|
||||||
|
# - name: Set DNS resolver and hosts entry
|
||||||
|
# include_tasks: dns_hosts.yml
|
||||||
|
|
||||||
|
# - name: Run verification checks
|
||||||
|
# include_tasks: verify.yml
|
||||||
|
# when: samba_verify | bool
|
||||||
|
|||||||
@@ -1,8 +1,50 @@
|
|||||||
---
|
---
|
||||||
- name: Configure Kerberos (krb5.conf)
|
- name: Extract absolute krb5.conf path from provision output
|
||||||
template:
|
ansible.builtin.set_fact:
|
||||||
src: krb5.conf.j2
|
krb5_conf_path: >-
|
||||||
|
{{
|
||||||
|
(
|
||||||
|
samba_provision_output.stdout
|
||||||
|
| regex_findall('(/[^\\s,"'']*/private/krb5\\.conf)')
|
||||||
|
| list
|
||||||
|
| default([])
|
||||||
|
)
|
||||||
|
| first
|
||||||
|
| default('/var/lib/samba/private/krb5.conf')
|
||||||
|
| trim
|
||||||
|
}}
|
||||||
|
when: samba_provision_output.stdout is defined
|
||||||
|
# the regex doesnt actually work
|
||||||
|
|
||||||
|
- name: Show extracted krb5.conf path
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Extracted krb5.conf path: {{ krb5_conf_path | default('N/A') }}"
|
||||||
|
|
||||||
|
- name: Check if krb5.conf exists on disk
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ krb5_conf_path }}"
|
||||||
|
register: krb5_conf_stat
|
||||||
|
when: krb5_conf_path != ''
|
||||||
|
|
||||||
|
- name: Validate krb5.conf presence
|
||||||
|
ansible.builtin.fail:
|
||||||
|
msg: "Kerberos configuration file was not found at {{ krb5_conf_path }}. Provision may have failed."
|
||||||
|
when:
|
||||||
|
- krb5_conf_path != ''
|
||||||
|
- not krb5_conf_stat.stat.exists | default(false)
|
||||||
|
|
||||||
|
- name: Confirm Kerberos configuration found
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Kerberos configuration verified: {{ krb5_conf_path }}"
|
||||||
|
when: krb5_conf_stat.stat.exists | default(false)
|
||||||
|
|
||||||
|
- name: Copy krb5.conf to /etc/krb5.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: '{{ krb5_conf_path }}'
|
||||||
dest: /etc/krb5.conf
|
dest: /etc/krb5.conf
|
||||||
|
remote_src: true
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: '0644'
|
mode: '0644'
|
||||||
|
# Only run this if the provision was successful (changed)
|
||||||
|
when: samba_provision_output.changed
|
||||||
@@ -1,9 +1,22 @@
|
|||||||
---
|
---
|
||||||
|
- name: Prepare for Samba AD DC
|
||||||
|
include_tasks: preparing.yml
|
||||||
|
|
||||||
- name: Install or remove Samba AD DC
|
- name: Install
|
||||||
include_tasks: install.yml
|
include_tasks: install.yml
|
||||||
when: samba_ad_dc_state == 'present'
|
|
||||||
|
|
||||||
- name: Remove Samba AD DC
|
- name: Provision
|
||||||
include_tasks: remove.yml
|
include_tasks: provision.yml
|
||||||
when: samba_ad_dc_state == 'absent'
|
|
||||||
|
- name: Setup DNS resolver
|
||||||
|
include_tasks: setupresolver.yml
|
||||||
|
|
||||||
|
- name: Configure Kerberos
|
||||||
|
include_tasks: kerberos.yml
|
||||||
|
|
||||||
|
- name: Testing Samba AD DC
|
||||||
|
include_tasks: verify.yml
|
||||||
|
|
||||||
|
# - name: Configure Time Synchronization
|
||||||
|
# include_tasks: ntpd.yml
|
||||||
|
|
||||||
54
tasks/ntpd.yml
Normal file
54
tasks/ntpd.yml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
---
|
||||||
|
- name: Ensure the ntp package is installed
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: ntpsec
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Search common Samba locations for the 'ntp_signd' directory
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths:
|
||||||
|
# Common paths for Samba installations
|
||||||
|
- /var/lib/samba/
|
||||||
|
- /usr/local/samba/
|
||||||
|
- /etc/samba/
|
||||||
|
pattern: ntp_signd
|
||||||
|
file_type: directory
|
||||||
|
register: find_ntp_signd
|
||||||
|
|
||||||
|
- name: Set the path variable, failing if not found
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
ntp_signd_path: '{{ find_ntp_signd.files[0].path }}'
|
||||||
|
# This conditional logic ensures the playbook stops if the directory is missing,
|
||||||
|
# or if more than one directory named 'ntp_signd' is found (which is unlikely/undesirable).
|
||||||
|
when: find_ntp_signd.matched == 1
|
||||||
|
failed_when: find_ntp_signd.matched != 1
|
||||||
|
|
||||||
|
- name: Verify permissions on the detected 'ntp_signd' directory
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: '{{ ntp_signd_path }}'
|
||||||
|
register: ntp_signd_stats
|
||||||
|
|
||||||
|
- name: Assert that the permissions allow read access
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
# Check if the directory exists and has permissions that grant read/execute to 'other' (r-x)
|
||||||
|
- ntp_signd_stats.stat.exists
|
||||||
|
- ntp_signd_stats.stat.mode is search('[rwx-]{2}[rwx-]{2}[4-7]')
|
||||||
|
fail_msg: 'FATAL: The detected ntp_signd directory ({{ ntp_signd_path }}) does not have necessary read permissions (mode: {{ ntp_signd_stats.stat.mode }}).'
|
||||||
|
success_msg: 'SUCCESS: Permissions on {{ ntp_signd_path }} are correctly configured.'
|
||||||
|
|
||||||
|
- name: Configure ntp.conf for Active Directory Domain Controller (AD DC)
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: templates/ntp.conf.j2 # Path to your NTP template file
|
||||||
|
dest: /etc/ntp.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
notify:
|
||||||
|
- Restart ntp service
|
||||||
|
|
||||||
|
- name: Enable and start the ntp service
|
||||||
|
ansible.builtin.service:
|
||||||
|
name: ntp
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
112
tasks/preparing.yml
Normal file
112
tasks/preparing.yml
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
---
|
||||||
|
# Disable tools, such as resolvconf, that automatically update your /etc/resolv.conf DNS resolver configuration file
|
||||||
|
- name: Stop and disable systemd-resolved if present
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: systemd-resolved
|
||||||
|
enabled: false
|
||||||
|
state: stopped
|
||||||
|
when: ansible_facts.services['systemd-resolved.service'] is defined
|
||||||
|
|
||||||
|
- name: Remove /etc/resolv.conf if it's a symlink to systemd-resolved
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: /etc/resolv.conf
|
||||||
|
state: absent
|
||||||
|
when: "'/run/systemd/resolve' in ansible_facts.lsb.description | default('')"
|
||||||
|
|
||||||
|
- name: Create static /etc/resolv.conf
|
||||||
|
ansible.builtin.copy:
|
||||||
|
dest: /etc/resolv.conf
|
||||||
|
content: |
|
||||||
|
nameserver {{ location_internal_dns }}
|
||||||
|
nameserver {{ location_external_dns }}
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
|
|
||||||
|
- name: Disable resolvconf package (if installed)
|
||||||
|
ansible.builtin.package:
|
||||||
|
name: resolvconf
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Disable DNS updates from NetworkManager (if present)
|
||||||
|
ansible.builtin.blockinfile:
|
||||||
|
path: /etc/NetworkManager/NetworkManager.conf
|
||||||
|
block: |
|
||||||
|
[main]
|
||||||
|
dns=none
|
||||||
|
notify: Restart NetworkManager
|
||||||
|
when: ansible_facts.services['NetworkManager.service'] is defined
|
||||||
|
|
||||||
|
- name: Prevent dhclient from modifying resolv.conf (if present)
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/dhcp/dhclient.conf
|
||||||
|
regexp: '^#?supersede domain-name-servers'
|
||||||
|
line: 'supersede domain-name-servers {{ location_internal_dns }}, {{ location_external_dns }};'
|
||||||
|
create: yes
|
||||||
|
|
||||||
|
# Verify that the /etc/hosts file on the DC correctly resolves the fully-qualified domain name (FQDN) and short host name to the LAN IP address of the DC
|
||||||
|
- name: Set /etc/hosts entry for Samba AD DC
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/hosts
|
||||||
|
line: '{{ addc_ansible_host }} {{ addc_hostname | upper }}.{{ addc_tld | lower }} {{ addc_hostname | upper }}'
|
||||||
|
state: present
|
||||||
|
create: yes
|
||||||
|
|
||||||
|
- name: Ensure '127.0.0.1 localhost' is present and nothing else on that line
|
||||||
|
ansible.builtin.lineinfile:
|
||||||
|
path: /etc/hosts
|
||||||
|
regexp: '^127\.0\.0\.1\s+'
|
||||||
|
line: '127.0.0.1 localhost'
|
||||||
|
state: present
|
||||||
|
|
||||||
|
# Remove any existing smb.conf file
|
||||||
|
- name: Get compiled default smb.conf path from smbd
|
||||||
|
ansible.builtin.shell: smbd -b | grep CONFIGFILE | awk '{print $2}'
|
||||||
|
register: smb_conf_path
|
||||||
|
changed_when: false
|
||||||
|
failed_when: smb_conf_path.rc != 0
|
||||||
|
|
||||||
|
- name: Remove smb.conf using discovered path
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: '{{ smb_conf_path.stdout }}'
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
# Remove all Samba database files, such as *.tdb and *.ldb files
|
||||||
|
- name: Get Samba directories from smbd -b
|
||||||
|
ansible.builtin.shell: smbd -b | egrep 'LOCKDIR|STATEDIR|CACHEDIR|PRIVATE_DIR' | awk '{print $2}'
|
||||||
|
register: samba_dirs
|
||||||
|
changed_when: false
|
||||||
|
failed_when: samba_dirs.rc != 0
|
||||||
|
|
||||||
|
- name: Filter existing directories
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths: '{{ item }}'
|
||||||
|
file_type: directory
|
||||||
|
recurse: no
|
||||||
|
loop: '{{ samba_dirs.stdout_lines }}'
|
||||||
|
register: existing_dirs
|
||||||
|
|
||||||
|
- name: Collect existing directories
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
valid_dirs: "{{ existing_dirs.results | selectattr('matched', '>', 0) | map(attribute='files') | sum(start=[]) | map(attribute='path') | list }}"
|
||||||
|
|
||||||
|
- name: Find *.tdb and *.ldb files
|
||||||
|
ansible.builtin.find:
|
||||||
|
paths: '{{ item }}'
|
||||||
|
patterns: '*.tdb,*.ldb'
|
||||||
|
recurse: yes
|
||||||
|
use_regex: false
|
||||||
|
loop: '{{ valid_dirs }}'
|
||||||
|
register: db_files
|
||||||
|
|
||||||
|
- name: Remove found tdb/ldb files
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: '{{ item.path }}'
|
||||||
|
state: absent
|
||||||
|
loop: "{{ db_files.results | map(attribute='files') | sum(start=[]) }}"
|
||||||
|
when: item.path is defined
|
||||||
|
|
||||||
|
- name: Report removed files
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: 'Removed: {{ item.path }}'
|
||||||
|
loop: "{{ db_files.results | map(attribute='files') | sum(start=[]) }}"
|
||||||
@@ -1,37 +1,36 @@
|
|||||||
---
|
---
|
||||||
---
|
- name: check if domain already provisioned
|
||||||
- name: Ensure Samba log directory exists
|
ansible.builtin.stat:
|
||||||
file:
|
path: /var/lib/samba/private/adsync.conf
|
||||||
path: "{{ samba_log_dir }}"
|
register: samba_provisioned
|
||||||
state: directory
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: '0755'
|
|
||||||
|
|
||||||
- name: Provision the Samba AD DC (with logging)
|
- name: Remove smb.conf if server role conflicts
|
||||||
command: >
|
ansible.builtin.shell: |
|
||||||
|
if grep -q 'server role = standalone server' /etc/samba/smb.conf 2>/dev/null; then
|
||||||
|
mv /etc/samba/smb.conf /etc/samba/smb.conf.bak.$(date +%s)
|
||||||
|
fi
|
||||||
|
args:
|
||||||
|
executable: /bin/bash
|
||||||
|
changed_when: false
|
||||||
|
when: not samba_provisioned.stat.exists
|
||||||
|
|
||||||
|
- name: Provision the Samba AD DC
|
||||||
|
ansible.builtin.command: >
|
||||||
samba-tool domain provision
|
samba-tool domain provision
|
||||||
--use-rfc2307
|
--use-rfc2307
|
||||||
--realm={{ samba_realm }}
|
--realm={{ samba_domain_info.realm }}
|
||||||
--domain={{ samba_domain }}
|
--domain={{ samba_domain_info.domain }}
|
||||||
--server-role=dc
|
--server-role={{ samba_domain_info.server_role }}
|
||||||
--dns-backend={{ samba_dns_backend }}
|
--dns-backend={{ samba_domain_info.dns_backend }}
|
||||||
--adminpass={{ samba_admin_password }}
|
--adminpass='{{ addc_admin_password }}'
|
||||||
args:
|
--option='interfaces={{ samba_domain_info.interfaces }}'
|
||||||
creates: "{{ samba_samdb_path }}"
|
--option='bind interfaces only={{ samba_domain_info.bind_interfaces_only }}'
|
||||||
|
when: not samba_provisioned.stat.exists
|
||||||
register: samba_provision_output
|
register: samba_provision_output
|
||||||
|
changed_when: samba_provision_output.rc == 0
|
||||||
no_log: false # You may toggle this if password should be hidden
|
no_log: false # You may toggle this if password should be hidden
|
||||||
|
|
||||||
- name: Write provisioning output to log
|
- name: print provision output
|
||||||
copy:
|
ansible.builtin.debug:
|
||||||
content: "{{ samba_provision_output.stdout }}"
|
msg: "Provisioning output: {{samba_provision_output}}"
|
||||||
dest: "{{ samba_provision_log_file }}"
|
|
||||||
owner: root
|
|
||||||
group: root
|
|
||||||
mode: '0644'
|
|
||||||
|
|
||||||
- name: Redact passwords in provisioning log (optional)
|
|
||||||
replace:
|
|
||||||
path: "{{ samba_provision_log_file }}"
|
|
||||||
regexp: "--adminpass=.*"
|
|
||||||
replace: "--adminpass=********"
|
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
---
|
|
||||||
- name: Stop Samba AD DC
|
|
||||||
service:
|
|
||||||
name: samba-ad-dc
|
|
||||||
state: stopped
|
|
||||||
enabled: no
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Remove Samba configuration
|
|
||||||
file:
|
|
||||||
path: "{{ samba_conf_path }}"
|
|
||||||
state: absent
|
|
||||||
|
|
||||||
- name: Remove Samba DB and related files
|
|
||||||
file:
|
|
||||||
path: "{{ item }}"
|
|
||||||
state: absent
|
|
||||||
loop:
|
|
||||||
- /var/lib/samba
|
|
||||||
- /etc/krb5.conf
|
|
||||||
- /etc/samba
|
|
||||||
- /var/cache/samba
|
|
||||||
- /var/log/samba
|
|
||||||
|
|
||||||
- name: Remove Samba-related packages
|
|
||||||
apt:
|
|
||||||
name:
|
|
||||||
- samba
|
|
||||||
- krb5-config
|
|
||||||
- krb5-user
|
|
||||||
- winbind
|
|
||||||
- smbclient
|
|
||||||
- dnsutils
|
|
||||||
state: absent
|
|
||||||
purge: yes
|
|
||||||
autoremove: yes
|
|
||||||
|
|
||||||
- name: Restore DNS config
|
|
||||||
include_tasks: dns_hosts_restore.yml
|
|
||||||
8
tasks/setupresolver.yml
Normal file
8
tasks/setupresolver.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
- name: Template /etc/resolv.conf with custom DNS nameservers
|
||||||
|
template:
|
||||||
|
src: resolv.conf.j2
|
||||||
|
dest: /etc/resolv.conf
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: '0644'
|
||||||
204
tasks/verify.yml
204
tasks/verify.yml
@@ -1,40 +1,180 @@
|
|||||||
---
|
---
|
||||||
- name: Verify Samba AD DC setup
|
- name: "Start the samba service"
|
||||||
when: samba_verify | bool
|
ansible.builtin.service:
|
||||||
block:
|
name: samba
|
||||||
|
state: started
|
||||||
|
enabled: true
|
||||||
|
|
||||||
- name: Run 'samba-tool domain info'
|
- name: "Show key variables"
|
||||||
command: samba-tool domain info 127.0.0.1
|
ansible.builtin.debug:
|
||||||
register: domain_info
|
msg: "{{ addc_reverse_zone_name }} {{ addc_ansible_host }} {{ addc_admin_password }} {{ addc_ip_last_octet }} {{ addc_hostname }} {{ addc_auth_domain }}"
|
||||||
changed_when: false
|
|
||||||
|
|
||||||
- name: Assert that the domain is provisioned
|
# - name: Ensure python3-pip is installed (optional)
|
||||||
assert:
|
# ansible.builtin.apt:
|
||||||
that:
|
# name: python3-pip
|
||||||
- "'Netbios name' in domain_info.stdout"
|
# state: present
|
||||||
- "'Server Role: ACTIVE DIRECTORY DOMAIN CONTROLLER' in domain_info.stdout"
|
# become: true
|
||||||
|
|
||||||
- name: Attempt kinit with administrator
|
- name: Ensure pexpect is installed (via apt)
|
||||||
command: echo "{{ samba_admin_password }}" | kinit administrator@{{ samba_realm }}
|
ansible.builtin.apt:
|
||||||
register: kinit_result
|
name: python3-pexpect
|
||||||
changed_when: false
|
state: present
|
||||||
failed_when: kinit_result.rc != 0
|
become: true
|
||||||
|
|
||||||
- name: Check Kerberos ticket
|
- name: "Create the reverse DNS zone {{ addc_reverse_zone_name }}"
|
||||||
command: klist
|
ansible.builtin.expect:
|
||||||
register: klist_result
|
command: "samba-tool dns zonecreate {{ addc_ansible_host }} {{ addc_reverse_zone_name }} -U Administrator"
|
||||||
changed_when: false
|
responses:
|
||||||
|
# Use the '(?i)' flag for case-insensitive matching of the prompt.
|
||||||
|
'(?i)password for.*:': "{{ addc_admin_password }}"
|
||||||
|
no_log: true # Highly recommended to prevent the password from appearing in logs
|
||||||
|
|
||||||
- name: Assert Kerberos ticket exists
|
- name: "Create the PTR (reverse) DNS record"
|
||||||
assert:
|
ansible.builtin.expect:
|
||||||
that:
|
# Command syntax: samba-tool dns add <server> <zone> <record_name> PTR <target_fqdn>
|
||||||
- "'krbtgt/{{ samba_realm }}@{{ samba_realm }}' in klist_result.stdout"
|
command: >
|
||||||
|
samba-tool dns add {{ addc_ansible_host }}
|
||||||
|
{{ addc_reverse_zone_name }}
|
||||||
|
{{ addc_ip_last_octet }} PTR
|
||||||
|
{{ addc_hostname | lower }}.{{ addc_auth_domain | lower }}
|
||||||
|
-U Administrator
|
||||||
|
responses:
|
||||||
|
# Expects the standard Samba password prompt
|
||||||
|
'(?i)password for.*:': "{{ addc_admin_password }}"
|
||||||
|
no_log: true # Hide sensitive data from logs
|
||||||
|
|
||||||
- name: Check Samba AD DC service status
|
|
||||||
service_facts:
|
|
||||||
|
|
||||||
- name: Assert samba-ad-dc service is active
|
- name: "Verify Samba file server by listing local shares"
|
||||||
assert:
|
ansible.builtin.command: smbclient -L localhost -N
|
||||||
that:
|
register: smbclient_output
|
||||||
- "'samba-ad-dc' in ansible_facts.services"
|
changed_when: false # This is a verification step, it doesn't change the host state
|
||||||
- ansible_facts.services['samba-ad-dc'].state == 'running'
|
|
||||||
|
- name: "Report the results of the smbclient verification"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: 'Samba Shares found: {{ smbclient_output.stdout }}'
|
||||||
|
|
||||||
|
- name: "Verify Samba AD authentication by accessing the netlogon share"
|
||||||
|
ansible.builtin.expect:
|
||||||
|
# Command to run: smbclient //localhost/netlogon -UAdministrator -c 'ls'
|
||||||
|
# The -c 'ls' command lists files on the share.
|
||||||
|
command: smbclient //localhost/netlogon -UAdministrator -c 'ls'
|
||||||
|
responses:
|
||||||
|
# Use the (?i) flag for case-insensitive matching of the prompt.
|
||||||
|
'(?i)password for.*:': "{{ addc_admin_password }}"
|
||||||
|
no_log: true # CRITICAL: Prevents the password from being logged
|
||||||
|
register: auth_verification
|
||||||
|
changed_when: false # This is a verification/check, not a change
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Verify LDAP Service Record (SRV _ldap._tcp)"
|
||||||
|
ansible.builtin.command: host -t SRV _ldap._tcp.{{ addc_auth_domain | lower }}.
|
||||||
|
register: ldap_srv_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: "'has SRV record' not in ldap_srv_check.stdout"
|
||||||
|
|
||||||
|
- name: "Debug - Show LDAP SRV check result"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: ldap_srv_check.stdout
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Verify Kerberos Service Record (SRV _kerberos._udp)"
|
||||||
|
ansible.builtin.command: host -t SRV _kerberos._udp.{{ addc_auth_domain | lower }}.
|
||||||
|
register: kerberos_srv_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: "'has SRV record' not in kerberos_srv_check.stdout"
|
||||||
|
|
||||||
|
- name: "Debug - Show Kerberos SRV check result"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: kerberos_srv_check.stdout
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Verify DC's A (Forward) Record"
|
||||||
|
ansible.builtin.command: host -t A {{ addc_hostname | lower }}.{{ addc_auth_domain | lower }}.
|
||||||
|
register: a_record_check
|
||||||
|
changed_when: false
|
||||||
|
failed_when: "'{{ addc_ansible_host }}' not in a_record_check.stdout"
|
||||||
|
|
||||||
|
- name: "Debug - Show A Record check result"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: a_record_check.stdout
|
||||||
|
|
||||||
|
|
||||||
|
- name: "Verify DC's PTR (Reverse) Record"
|
||||||
|
ansible.builtin.command: host -t PTR {{ addc_ansible_host }}
|
||||||
|
register: ptr_record_check
|
||||||
|
changed_when: false
|
||||||
|
# Assuming dc1.{{ addc_auth_domain }} is the expected output for the reverse record
|
||||||
|
failed_when: "'domain name pointer {{ addc_hostname | lower }}.{{ addc_auth_domain | lower }}' not in ptr_record_check.stdout"
|
||||||
|
|
||||||
|
- name: "Debug - Show PTR Record check result"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: ptr_record_check.stdout
|
||||||
|
|
||||||
|
- name: "Verify Kerberos authentication using kinit"
|
||||||
|
ansible.builtin.expect:
|
||||||
|
# Command to run: kinit administrator
|
||||||
|
command: kinit administrator
|
||||||
|
responses:
|
||||||
|
# Expects the standard Kerberos password prompt
|
||||||
|
# The (?i) flag ensures case-insensitive matching.
|
||||||
|
'(?i)password for administrator.*:': "{{ addc_admin_password }}"
|
||||||
|
no_log: true # CRITICAL: Prevents the password from being logged
|
||||||
|
register: kinit_check
|
||||||
|
changed_when: false # This is a verification/check, not a change
|
||||||
|
|
||||||
|
- name: "Debug - Show kinit verification result (should be empty on success)"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: 'Kerberos kinit verification successful. Output: {{ kinit_check.stdout }}'
|
||||||
|
|
||||||
|
- name: "Optional - Show the cached Kerberos ticket"
|
||||||
|
ansible.builtin.command: klist
|
||||||
|
register: klist_output
|
||||||
|
changed_when: false
|
||||||
|
when: kinit_check is succeeded
|
||||||
|
|
||||||
|
- name: "Debug - Show klist output"
|
||||||
|
ansible.builtin.debug:
|
||||||
|
var: klist_output.stdout
|
||||||
|
when: klist_output is defined
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# - name: Run 'samba-tool domain info'
|
||||||
|
# command: samba-tool domain info 127.0.0.1
|
||||||
|
# register: domain_info
|
||||||
|
# changed_when: false
|
||||||
|
|
||||||
|
# - name: Assert that the domain is provisioned
|
||||||
|
# assert:
|
||||||
|
# that:
|
||||||
|
# - ''Netbios name' in domain_info.stdout'
|
||||||
|
# - ''Server Role: ACTIVE DIRECTORY DOMAIN CONTROLLER' in domain_info.stdout'
|
||||||
|
|
||||||
|
# - name: Attempt kinit with administrator
|
||||||
|
# command: echo '{{ samba_admin_password }}' | kinit administrator@{{ samba_realm }}
|
||||||
|
# register: kinit_result
|
||||||
|
# changed_when: false
|
||||||
|
# failed_when: kinit_result.rc != 0
|
||||||
|
|
||||||
|
# - name: Check Kerberos ticket
|
||||||
|
# command: klist
|
||||||
|
# register: klist_result
|
||||||
|
# changed_when: false
|
||||||
|
|
||||||
|
# - name: Assert Kerberos ticket exists
|
||||||
|
# assert:
|
||||||
|
# that:
|
||||||
|
# - ''krbtgt/{{ samba_realm }}@{{ samba_realm }}' in klist_result.stdout'
|
||||||
|
|
||||||
|
# - name: Check Samba AD DC service status
|
||||||
|
# service_facts:
|
||||||
|
|
||||||
|
# - name: Assert samba-ad-dc service is active
|
||||||
|
# assert:
|
||||||
|
# that:
|
||||||
|
# - ''samba-ad-dc' in ansible_facts.services'
|
||||||
|
# - ansible_facts.services['samba-ad-dc'].state == 'running'
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
[libdefaults]
|
|
||||||
default_realm = {{ samba_realm }}
|
|
||||||
dns_lookup_realm = false
|
|
||||||
dns_lookup_kdc = true
|
|
||||||
ticket_lifetime = 24h
|
|
||||||
forwardable = yes
|
|
||||||
rdns = false
|
|
||||||
|
|
||||||
[realms]
|
|
||||||
{{ samba_realm }} = {
|
|
||||||
kdc = {{ samba_hostname }}
|
|
||||||
admin_server = {{ samba_hostname }}
|
|
||||||
}
|
|
||||||
|
|
||||||
[domain_realm]
|
|
||||||
.{{ samba_realm | lower }} = {{ samba_realm }}
|
|
||||||
{{ samba_realm | lower }} = {{ samba_realm }}
|
|
||||||
37
templates/ntp.conf.j2
Normal file
37
templates/ntp.conf.j2
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# This configuration file is managed by Ansible.
|
||||||
|
# It is configured to run as an Active Directory Domain Controller.
|
||||||
|
|
||||||
|
# Enable kernel time discipline (important for a DC)
|
||||||
|
tos maxclock 10
|
||||||
|
|
||||||
|
# Use your own local clock as a reliable fallback/default
|
||||||
|
# Local clock. Note that is not the "localhost" address!
|
||||||
|
server 127.127.1.0 # Undisciplined local clock
|
||||||
|
fudge 127.127.1.0 stratum 10
|
||||||
|
|
||||||
|
# Where to retrieve the time from
|
||||||
|
# Optionally, add external sources for greater accuracy (NTP pool)
|
||||||
|
# You should choose servers close to your location or use a reliable pool.
|
||||||
|
server 0.pool.ntp.org iburst prefer
|
||||||
|
server 1.pool.ntp.org iburst prefer
|
||||||
|
server 1.pool.ntp.org iburst prefer
|
||||||
|
|
||||||
|
# Drift file location
|
||||||
|
driftfile /var/lib/ntp/ntp.drift
|
||||||
|
logfile /var/log/ntp
|
||||||
|
ntpsigndsocket {{ ntp_signd_path }}
|
||||||
|
|
||||||
|
# Access control
|
||||||
|
# Default restriction: Allow clients only to query the time
|
||||||
|
restrict default kod nomodify notrap nopeer limited mssntp
|
||||||
|
|
||||||
|
# No restrictions for "localhost"
|
||||||
|
restrict 127.0.0.1
|
||||||
|
|
||||||
|
# Enable the time sources to only provide time to this host
|
||||||
|
restrict 0.pool.ntp.org mask 255.255.255.255 nomodify notrap nopeer noquery
|
||||||
|
restrict 1.pool.ntp.org mask 255.255.255.255 nomodify notrap nopeer noquery
|
||||||
|
restrict 2.pool.ntp.org mask 255.255.255.255 nomodify notrap nopeer noquery
|
||||||
|
|
||||||
|
# tell NTP not to panic and exit
|
||||||
|
tinker panic 0
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
# Managed by Ansible - Samba AD DC DNS
|
# Managed by Ansible - Samba AD DC DNS- DO NOT EDIT MANUALLY
|
||||||
|
search {{ addc_auth_domain | lower }}
|
||||||
{% for ns in samba_dns_nameservers %}
|
nameserver {{ addc_ansible_host }}
|
||||||
nameserver {{ ns }}
|
|
||||||
{% endfor %}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
[global]
|
|
||||||
workgroup = {{ samba_domain }}
|
|
||||||
realm = {{ samba_realm }}
|
|
||||||
netbios name = {{ samba_hostname | upper }}
|
|
||||||
server role = active directory domain controller
|
|
||||||
dns forwarder = 8.8.8.8
|
|
||||||
idmap_ldb:use rfc2307 = yes
|
|
||||||
|
|
||||||
[sysvol]
|
|
||||||
path = /var/lib/samba/sysvol
|
|
||||||
read only = no
|
|
||||||
|
|
||||||
[netlogon]
|
|
||||||
path = /var/lib/samba/sysvol/{{ samba_realm | lower }}/scripts
|
|
||||||
read only = no
|
|
||||||
Reference in New Issue
Block a user