Home |

Trigat

Ansible Playbook for Ubuntu 16.04/18.04 and Winbind

04-21-2019

There are 2 files here:

1. domain_playbook.yaml
2. domain-connect.sh

Save them both to your Ansible directory.

Language or Platform: Other

Code:

# Save this part as as domain_playbook.yaml 
# This playbook allows you to add servers to Active Directory
# Compatible with Ubuntu 16.04 & 18.04 Server/Desktop

# Make sure you update your AD username and password at the bottom of this playbook.
# !Also make sure you set your domain name and other info in domain-connect.sh below!

# Run with:
# sudo ansible-playbook domain_playbook.yaml --user REMOTEUSERNAME --ask-pass --ask-become-pass

- hosts: ubuntu-servers
#  become: yes
#  become_user: root
#  become_method: sudo

  tasks:
      
      # Adjust your timezone
    - name: Set timezone to US/Central
      become: true
      timezone:
        name: US/Central

    - name: Add multiverse repository                                                                                                         
      become: true
      shell: apt-add-repository multiverse -y
      args:
        executable: /bin/bash

    - name: Update and upgrade apt packages
      become: true
      apt:
        upgrade: yes
        update_cache: yes

    - name: Install Winbind and tools
      become: true
      apt: name={{ item }} state=present
      with_items:
        - samba
        - krb5-user
        - chrony
        - python-pip
        - python3-pip
        - winbind
        - libnss-winbind
        - libpam-winbind

    - pip:
        name: pexpect
      become: yes

    - name: Copy File
      copy: 
        src=domain-connect.sh 
        dest=~/domain-connect.sh 
        mode=0751
      
    - name: Execute script
      become: true
      script: domain-connect.sh

    - name: Case insensitive password string match
      become: true
      expect:
        # Use your Active Directory user and domain here
        command: net ads join -U USER@domain.local
        responses:
          # Use your Active Directory user password here
          (?i)password: "PASSWORD_HERE"
      # Don't show passwords in your log
      no_log: false

    - service:
        name: "{{ item }}"
        state: started
      with_items:
        - 'chrony'
        - 'smbd'
        - 'nmbd'

    - name: Start Winbind
      become: yes
      command: systemctl start winbind.service
      # A restart is required  
    - name: Restart services
      become: yes
      command: systemctl restart winbind.service

###########################################################
###########################################################
############### END OF PLAYBOOK ###########################


############### BEGINNING OF SCRIPT #######################
# Save this as domain-connect.sh

#!/bin/bash

######################################################################
# Author: Vepr                                                       #
# Script that adds Linux Computer to Active Directory using Winbind. #
#                                                                    #
# Filename: domain-connect.sh                                        #
#                                                                    #
# Usage:                                                             #
# $ chmod 755 domain-connect.sh                                      #
# $ sudo ./domain-connect.sh                                         #
#                                                                    #
# Make sure date/time on your servers are synced up.                 #
#                                                                    #
######################################################################

# This script is for newly installed systems.  It overwrites files
# /etc/samba/smb.conf, /etc/hosts, /etc/resolv.conf, /etc/nsswitch.conf,
# /etc/krb5.conf, /etc/pam.d/common-auth, and /etc/ntp.conf
# Make sure you backup these files if you have already edited them.

##########################
##### USER VARIABLES #####

# Type in your domain name: (example.local)
DOMAIN='domain.local'

# Type the fully qualified domain name for the domain controller:
DC='dc.domain.local'

# Type the domain controller IP address:
DCIP='192.168.70.1'

# Do you have a second domain controller?  Leave these blank if you do not.

# Type the fully qualified domain name for the second domain controller:
DC2=''

# Type the second domain controller IP address:
DC2IP=''

# If not done already, you will need to update /etc/hosts and possibly /etc/resolv.conf before running the rest of this script.
# Do you want this script to automatically update /etc/hosts and /etc/resolv.conf?
UPDATE_FILES='y'

##### END USER VARIABLES #####
#############################

# Remove extension from domain name
REMOVE_EXTENSION=${DOMAIN%.*}
# Change domain name to all caps with extension removed
REMOVE_EXTENSION_CAPS=${REMOVE_EXTENSION^^}
# Change complete domain to all caps
COMPLETE_DOMAIN_CAPS=${DOMAIN^^}

# Remove extension from domain controller 1 name
REMOVE_EXTENSION_DC1=${DC%.*}
SHORT_DC1=${REMOVE_EXTENSION_DC1%.*}

# Remove extension from domain controller 1 name
REMOVE_EXTENSION_DC2=${DC2%.*}
SHORT_DC2=${REMOVE_EXTENSION_DC2%.*}

# if user types 'y'
if [ $UPDATE_FILES = 'y' ];
then

##########################################
    ######### Update /etc/resolv.conf ####

    # comment out /etc/resolv.conf and add new lines
    cp /etc/resolv.conf /etc/resolv.conf.tmp
    sed 's/^/#/' /etc/resolv.conf.tmp > /etc/resolv.conf
    rm /etc/resolv.conf.tmp

    resolv=""
    resolv+="nameserver $DCIP \n"
    resolv+="search $DOMAIN \n"

    echo -e "\n$resolv" >> /etc/resolv.conf # -e allows the new line

    # Check if domain controller 2 variable is empty
    if [ -z "$DC2" ]
    then
        #echo "\$DC2 is empty."
        echo ' '
    else
    # If available, add domain controller 2 below primary domain controller in /etc/resolv.conf
        sed -i 'nameserver '$DCIP'/a \
         nameserver '$DC2IP /etc/resolv.conf
    fi

##########################################
    ### Update /etc/hosts ################

    hosts="\n$DCIP    $SHORT_DC1   $DC"
    echo -e "$hosts" >> /etc/hosts  # -e allows the new line

    # Check if domain controller 2 variable is empty
    if [ -z "$DC2" ]
    then
        #echo "\$DC2 is empty."
        echo ' '
    else
    # If available, add domain controller 2 below primary domain controller in /etc/hosts
        hosts2="$DC2IP    $SHORT_DC2    $DC2"
        echo -e "$hosts2" >> /etc/hosts
    fi
fi

echo ' '
echo 'Files updated.'

##########################################
    ######### Update /etc/krb5.conf ######

cp /etc/krb5.conf /etc/krb5.original
truncate -s0 /etc/krb5.conf

krb=""
krb+="[libdefaults] \n"
krb+="ticket_lifetime = 24000 \n"
krb+="default_realm = $COMPLETE_DOMAIN_CAPS \n"
krb+="default_tgs_enctypes = rc4-hmac des-cbc-md5 \n"
krb+="default_tkt_enctypes = rc4-hmac des-cbc-md5 \n"
krb+="permitted_enctypes = rc4-hmac des-cbc-md5 \n"
krb+="dns_lookup_realm = true \n"
krb+="dns_lookup_kdc = true \n"
krb+="dns_fallback = yes \n"
krb+=" \n"
krb+="[realms] \n"
krb+="$COMPLETE_DOMAIN_CAPS = { \n"
krb+="  kdc = $DC \n"
krb+="  default_domain = $DOMAIN \n"
krb+="} \n"
krb+=" \n"
krb+="[domain_realm] \n"
krb+=".$DOMAIN = $COMPLETE_DOMAIN_CAPS \n"
krb+="$DOMAIN = $COMPLETE_DOMAIN_CAPS \n"
krb+=" \n"
krb+="[appdefaults] \n"
krb+="pam = { \n"
krb+="   debug = false \n"
krb+="   ticket_lifetime = 36000 \n"
krb+="   renew_lifetime = 36000 \n"
krb+="   forwardable = true \n"
krb+="   krb4_convert = false \n"
krb+="} \n"
krb+=" \n"
krb+="[logging] \n"
krb+="default = FILE:/var/log/krb5libs.log \n"
krb+="kdc = FILE:/var/log/krb5kdc.log \n"
krb+="admin_server = FILE:/var/log/kadmind.log \n"

echo -en $krb >> /etc/krb5.conf

# Check if domain controller 2 variable is empty
if [ -z "$DC2" ]
then 
    #echo "\$DC2 is empty."
    echo ' '
else

# If available, add domain controller 2 below primary domain controller in /etc/krb5.conf
sed -i '/kdc = '$DC'/a \
 kdc = '$DC2 /etc/krb5.conf
fi

##################################################
    ######### Update /etc/pam.d/common-auth ######

cp /etc/pam.d/common-auth /etc/pam.d/common-auth.bkp.$(date --iso-8601=seconds)
truncate -s0 /etc/pam.d/common-auth

pam=""
pam+="auth    [success=3 default=ignore]      pam_krb5.so minimum_uid=1000 \n"
pam+="auth    [success=2 default=ignore]      pam_unix.so nullok_secure try_first_pass \n"
pam+="auth    [success=1 default=ignore]      pam_winbind.so krb5_auth krb5_ccache_type=FILE cached_login try_first_pass \n"
pam+="auth    requisite                       pam_deny.so \n"
pam+="auth    required                        pam_permit.so \n"

echo -en $pam >> /etc/pam.d/common-auth

#####################################################
    ######### Update /etc/pam.d/common-account ######

cp /etc/pam.d/common-account /etc/pam.d/common-account.bkp.$(date --iso-8601=seconds)
truncate -s0 /etc/pam.d/common-account

cmn=""
cmn+="account required                        pam_unix.so \n"
cmn+="account sufficient                      pam_winbind.so \n"

echo -en $cmn >> /etc/pam.d/common-account

##########################################
    ### Update /etc/chrony/chrony.conf ###

# Add line 'pool DC' above other pool lines in /etc/chrony/chrony.conf
sed -i '/pool ntp/i \
pool '$DC /etc/chrony/chrony.conf

# Check if domain controller 2 variable is empty
if [ -z "$DC2" ]
then
    #echo "\$DC2 is empty."
    echo ' '
else
# If available, add domain controller 2 below primary domain controller in /etc/chrony/chrony.conf
sed -i 'pool '$DC2'/a \
 pool '$DC2 /etc/chrony/chrony.conf
fi

#echo 'We will now try to create a token for a user in Active Directory.'
#echo 'Type in your domain user name: '
#read USERNAME

##########################################
    ######### Join User to Domain ########

#kinit $USERNAME

##########################################
    ######### Update /etc/samba/smb.conf #

smb=""
smb+="workgroup = $REMOVE_EXTENSION_CAPS \n"
smb+="  client signing = yes \n"
smb+="  client use spnego = yes \n"
smb+="  kerberos method = secrets and keytab \n"
smb+="  realm = $COMPLETE_DOMAIN_CAPS \n"
smb+="  security = ads \n"
smb+="  # Added for Windows A.D. access using Windbind \n"
smb+="  \n"
smb+="  idmap config *:range = 5000-100000 \n"
smb+="  \n"
smb+="  winbind allow trusted domains = no \n"
smb+="  winbind trusted domains only = no \n"
smb+="  winbind use default domain = yes \n"
smb+="  winbind enum users  = yes \n"
smb+="  winbind enum groups = yes \n"
smb+="  winbind refresh tickets = yes \n"
smb+="  \n"
smb+="  template shell = \\/bin\\/bash"

# search for workgroup line in smb.conf and replace with below:
sed -i "s/workgroup = WORKGROUP/$smb/g" /etc/samba/smb.conf

#########################################
    ######### Update /etc/nsswitch.conf #

# comment out /etc/nsswitch.conf and add new lines
cp /etc/nsswitch.conf /etc/nsswitch.conf.tmp
sed 's/^/#/' /etc/nsswitch.conf.tmp > /etc/nsswitch.conf
rm /etc/nsswitch.conf.tmp

ns=""
ns+="passwd:         files winbind \n"
ns+="group:          files winbind \n"
ns+="shadow:         files \n"
ns+="gshadow:        files \n"
ns+=" \n"
ns+="hosts:          files dns \n"
ns+="networks:       files \n"
ns+=" \n"
ns+="protocols:      db files \n"
ns+="services:       db files \n"
ns+="ethers:         db files \n"
ns+="rpc:            db files \n"
ns+=" \n"
ns+="netgroup:       nis \n"
ns+="sudoers:        files"

echo -e "\n$ns" >> /etc/nsswitch.conf # -e allows the new line

#sudo systemctl restart chrony.service
#sudo systemctl restart smbd.service nmbd.service
#sudo systemctl restart winbind.service

#echo ' '
#echo 'You can now join computer to domain.  First exit out of current terminal.'
#echo 'Log in to new terminal and type this command: '
#echo ' '
#echo 'sudo net ads join –k'
#echo ' '
#echo '(Type it.  Do not copy and past it.)'

# Or you could do something like:
# sudo net ads join -U user@DOMAIN.LOCAL

# - Troubleshooting - If you get this error, you may already be addeded to the domain:

# Failed to join domain: Failed to set machine spn: Constraint violation
# Do you have sufficient permissions to create machine accounts?

# - Other Commands -

# getent group
# wbinfo -u

Back