Thursday 28 September 2017

Python Example: Viewing members of a group with ldap3

Although the ldap3 module for python is well documented I didn't find many good examples - so I decided to publish this one for others:


from ldap3 import Server, Connection, ALL, NTLM, SUBTREE
import re
# Global varsBindUser = 'domain\\username'BindPassword = '<yourpassword>'SearchGroup = 'Domain Admins'ADServer = 'dc01.domain.tld'SearchBase = 'DC=domain,DC=tld'

def getUsersInGroup(username, password, group):
    server = Server(ADServer)
    conn = Connection(server, user=username, password=password, authentication=NTLM, auto_bind=True)
    conn.bind()

    conn.search(search_base=SearchBase,
                search_filter='(&(objectClass=GROUP)(cn=' + group +'))', search_scope=SUBTREE,
                attributes=['member'], size_limit=0)
    result = conn.entries

    conn.unbind()
    return result

def getUserDescription(username, password, userdn):
    server = Server(ADServer)
    conn = Connection(server, user=username, password=password, authentication=NTLM, auto_bind=True)
    conn.bind()

    conn.search(search_base=SearchBase,
                search_filter='(&(objectClass=person)(cn=' + userdn + '))', search_scope=SUBTREE,
                attributes=['description'], size_limit=0)
    result = conn.entries

    conn.unbind()
    return result

print('Querying group: ' + SearchGroup)

regex_short = r" +CN=([a-zA-Z ]+)" # extracts username onlyregex_long = r" +(?:[O|C|D][U|N|C]=[a-zA-Z ]+,?)+" # extracts complete DNmatches = re.findall(regex_short, str(getUsersInGroup(username=BindUser, password=BindPassword, group=SearchGroup)))

print('Found ' + str(len(matches)) + ' users associated with this group...')

for match in matches:
    print('Getting description for account: ' + match + '...')
    match_description = str(getUserDescription(username=BindUser, password=BindPassword, userdn=match))

    # check if user has a valid description    regex_desc = r"description:[ A-Za-z]+"    if re.search(regex_desc, match_description):
        print(re.search(regex_desc, match_description)

Wednesday 27 September 2017

Tuesday 26 September 2017

Changing a puppet master certificate

In the event you want to change a puppet server's hostname you will need to also generate a new certificate and re-issue a certificate to each of it's agents.

Firstly delete the existing certificate on the puppet master:

rm -Rf /etc/puppetlabs/puppet/ssl/

and on the puppetserver / CA issue:

sudo puppet cert destroy <puppetserver.tld>

and then on the puppetserver generate a new CA with:

puppet cert generate puppetserver.int --dns_alt_names=puppetserver,puppetdb

start the server:

puppet master --no-daemonize --debug

and on each puppet agent generate a new certificate - but firstly ensure existing old CA certs etc. have been removed.

Run the following on the master:

puppet cert clean client01

and the following on the client:

sudo service puppet stop
rm -Rf /etc/puppetlabs/puppet/ssl
rm -Rf /opt/puppetlabs/puppet/cache/client_data/catalog/client01.json
sudo service puppet start

puppet agent --test --dns_alt_names=puppetserver,puppetdb

And finally sign them on the puppet

puppet cert --list

puppet cert --allow-dns-alt-names sign puppetserver.int

puppet cert --allow-dns-alt-names sign puppetagent01.int

puppet cert --allow-dns-alt-names sign puppetagent02.int

and so on...

If you are using PuppetDB you will also need to ensure it's using the latest CA cert:

rm -Rf /etc/puppetlabs/puppetdb/ssl

puppetdb ssl-setup

Thursday 21 September 2017

Forwarding mail for the root user to an external address

Quite often I find mail such as those generated by cron jobs are sent to the user they are executed under - for example root.

Using the 'aliases' file we can instruct any mail destined for a specific user to be forwarded to another (internal or external) address - for example by adding the following to /etc/aliases:

sudo vi /etc/aliases

root: yourname@externalemail.com

and ensure those changes take effect by issuing:

sudo newaliases

and finally reloading the mail server:

sudo service postfix reload

Tuesday 19 September 2017

Installing / setting up Samba on CentOS 7

Firslty install the required packages:

sudo dnf install samba samba-client samba-common

We'll use /mnt/backup for the directory we wish to share:

mkdir -p /mnt/backup

Make a backup copy of the existing samba configuration:

sudo cp /etc/samba/smb.conf cp /etc/samba/smb.conf.orig

and adding the following into /etc/samba/smb.conf:

[global]
workgroup = WORKGROUP
netbios name = centos
security = user
[ARCHIVE]
comment = archive share
path = /mnt/backup
public = no
valid users = samba1, @sambausers
writable = yes
browseable = yes
create mask = 0765

*NOTE*: [ARCHIVE] is the share name!

Let's proceed by creating our samba user:

groupadd sambausers
useradd samba1
usermod -G sambausers samba1
smbpasswd -a samba1

Ensure the user / group has the relevant permissions:

chgrp -R sambausers /mnt/backup
chmod -R 0770 /mnt/backup

In my case this didn't work since this directory was a USB hard drive formatted with NTFS - so instead I had to set the group, owner and permissions as part of the mounting process in fstab - my fstab line looked something like:

UUID=XXXXXXXXXXXXXXX /mnt/backup ntfs umask=0077,gid=1001,uid=0,noatime,fmask=0027,dmask=0007 0 0

This ensures the group we created has access to the directory and that normal users do not have access to the files / directories. (You'll need to replace the 'gid' by obtaining the group id with getent or doing a cat /etc/group | grep "<group-name>")

If you have SELinux enabled you will want to change the security context on the directory you wish to export:

sudo dnf -y install policycoreutils-python
sudo chcon -R -t samba_share_t /mnt/backup
sudo semanage fcontext -a -t samba_share_t /mnt/backup
sudo setsebool -P samba_enable_home_dirs on

Enable and start the relevent services:

sudo systemctl enable nmbd
sudo systemctl enable smbd

sudo systemctl start nmbd
sudo systemctl start smbd

While smbd handles the file and printer sharing services, user authentiaction and data sharing; nmbd handles NetBIOS name service requests generated by Windows machines.

Add the relevent firewall rules in:

sudo iptables -t filter -A INPUT -i ethX -m state --state NEW -m udp -p udp --dport 137 -j ACCEPT
sudo iptables -t filter -A INPUT -i ethX -m state --state NEW -m udp -p udp --dport 138 -j ACCEPT
sudo iptables -t filter -A INPUT -i ethX -m state --state NEW -m tcp -p tcp --dport 139 -j ACCEPT
sudo iptables -t filter -A INPUT -i ethX -m state --state NEW -m tcp -p tcp --dport 445 -j ACCEPT

From a Windows client we can test the share with something like:

cmd.exe
net use \\SERVER\archive

or from *nix using the smbclient utility.

Erasing an MBR (or GPT) and / or partition table and data of a disk

This can performed with dd - in order to wipe the MBR (the first sector this is executed after the BIOS / hardware initialisation) we should issue:

sudo dd if=/dev/zero of=/dev/sdx bs=446 count=1

This wipes the first 446 bytes of the disk - while if we want to erase the MBR and the partition table we need to zero the first 512 bytes:

sudo dd if=/dev/zero of=/dev/sdx bs=512 count=1

And then to erase the data on the disk we can issue:

sudo dd if=/dev/zero of=/dev/sdx bs=4M count=1

Note: While strictly speaking the vast majority of modern drives actually have block sizes of 4096 bytes however the MBR and partition table are always restricted to the first 512.

GPT is slightly different - instead we need to ensure that the first 1024 bytes are zeroed:

sudo dd if=/dev/zero of=/dev/sdx bs=1024 count=1

and also be aware that a backup of the GPT table is also stored at the end of the disk - so we need to work out the last block as well.