-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjoin-ad.py
More file actions
154 lines (130 loc) · 4.31 KB
/
Copy pathjoin-ad.py
File metadata and controls
154 lines (130 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env python3
'''
Author: Craig Wilson
Copyright: Gattancha Computer Services
Created: 2025-10-22
Last Modified: 2025-10-22 by Craig Wilson
Version: 2510.22.0
Description:
This module automates the process of joining a linux server to an Active Directory Domain
When run the user will need to provide some information as shown in the example
Example:
#> ./join-ad.py
AD Administrator: domain-admin-1
Password for 'domain-admin-1': Password123!
FQDN Domain Name: test.lan
OU Path: Computers/Servers/Linux
<script output here>
'''
#Import Statements
import os
import subprocess
import csv
import pathlib
from pprint import pprint
import getpass
import re
#Define Variables
#User entered Variables
ad_username = input("AD Administrator: ")
ad_password = getpass.getpass(f"Password for {ad_username}: ")
domain_name = input("FQDN Domain Name: ").lower()
org_unit = input("OU Path: ")
# TODO: Possible User vars..
sudo_group_name = "G-Linux-Allow-Sudo"
ssh_group_name = "G-Linux-Allow-Login"
#Generated System Variables
short_domain = domain_name.split(".")[0].upper()
realm_name = domain_name.upper()
os_release = pathlib.Path("/etc/os-release")
dnf_packages = ["realmd","oddjob","oddjob-mkhomedir","sssd","adcli"]
fqdn_username = ad_username+"@"+realm_name
sudo_users = f"\"%{short_domain}\\{sudo_group_name}\" ALL=(ALL) ALL"
sssd_file = f"""[sssd]
domains = {domain_name}
config_file_version = 2
services = nss, pam, ssh
default_domain_suffix = {realm_name}
[domain/{domain_name}]
default_shell = /bin/bash
krb5_store_password_if_offline = True
cache_credentials = True
krb5_realm = {realm_name}
realmd_tags = manages-system joined-with-adcli
id_provider = ad
full_name_format = %1$s
override_homedir = /home/%u
fallback_homedir = /home/%u@%d
ad_domain = {domain_name}
use_fully_qualified_names = True
ldap_id_mapping = True
access_provider = simple
simple_allow_groups = {ssh_group_name}
"""
#Define Functions
def get_os_name():
with open(os_release) as stream:
reader = csv.reader(stream, delimiter="=")
for index, row in enumerate(reader):
if index == 0:
os_name = row[1]
return os_name
def run_command(*args):
try:
result = subprocess.run(
list(args),
check=True,
capture_output=True,
text=True
)
except subprocess.CalledProcessError as e:
print(f"Error: ", e.stderr)
def enable_svc(service):
print(f"Enabling service: {service}")
run_command("systemctl","enable","--now",service)
def dnf_install(*packages):
for package in list(packages):
print(f"Installing: {package}")
run_command("sudo", "dnf", "install", "-y", package, "-q")
def join_domain():
os_name = get_os_name()
send_password = subprocess.Popen(["/usr/bin/echo", ad_password],stdout=subprocess.PIPE,text=True)
do_adjoin = subprocess.Popen(["realm", "-v", "join", domain_name,"-U", fqdn_username,f"--computer-ou={full_ou_path}",f"--os-name={os_name}"],
stdin=send_password.stdout,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)
send_password.stdout.close()
stdout, stderr = do_adjoin.communicate()
rc = do_adjoin.returncode
if rc == 0:
print(f"Welcome to {realm_name}")
else:
print(f"Failed to join {realm_name}")
return rc, stdout, stderr
def configure_domain():
run_command("realm", "deny", "--all")
run_command("realm","permit","-g","'"+sudo_group_name+"'")
update_sssd_conf()
def format_as_dn(ou_path, domain):
parts = re.split(r"[\\/]", ou_path)
ou_string = ",".join(f"OU={p}" for p in reversed(parts))
dc_string = ",".join(f"DC={d}" for d in domain.split("."))
full_ou_path = ou_string+","+dc_string
return full_ou_path
def update_sssd_conf():
sssd_path = "/etc/sssd/sssd.conf"
with open(sssd_path, 'w') as f:
for line in sssd_file:
f.write(line)
def update_sudoers():
sudoers_path = "/etc/sudoers.d/domainusers"
with open(sudoers_path, 'w') as f:
for line in sudo_users:
f.write(line)
#Run our code
full_ou_path = format_as_dn(org_unit,domain_name)
dnf_install(*dnf_packages)
join_domain()
configure_domain()
update_sudoers()
enable_svc("sssd")
enable_svc("oddjobd")
print(f"\nComputer has successfully joined the {domain_name} Domain\nPlease reboot the system now")