Part IV looks at how to build up a guest VM with a base configuration that is going to be common to most of my VMs including providing access to lots of temporary storage via NFS and enabling LDAP authentication so I don't have to deal with local passwords on every VM. You may find other services are common for your purposes so add these to the mix during your build. Finally, I clone the image so we can build more copies later without going through the manual steps each time.
Updates, common packages and basic configuration
So we start by installing a few packages and potentially running some configuration scripts. Accessing the VMs via ssh is important so I'll add that along with the NFS client. I also want to make sure the timezone is set correctly as this may not have been established during the unattended image installation process.
01
02
03
04
05
06
07
08
09
10
11
12
13
| # make sure the image has the latest updates root@goat-lin001:~> apt-get update root@goat-lin001:~> apt-get dist-upgrade # add whatever common packages you want in the base build root@goat-lin001:~> apt-get install ssh root@goat-lin001:~> apt-get install nfs-client # if required, fix your timezone settings, try one of the following: root@goat-lin001:~> dpkg-reconfigure tzdata # or this with the applicable timezone substituted root@goat-lin001:~> ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime |
# make sure the image has the latest updates root@goat-lin001:~> apt-get update root@goat-lin001:~> apt-get dist-upgrade # add whatever common packages you want in the base build root@goat-lin001:~> apt-get install ssh root@goat-lin001:~> apt-get install nfs-client # if required, fix your timezone settings, try one of the following: root@goat-lin001:~> dpkg-reconfigure tzdata # or this with the applicable timezone substituted root@goat-lin001:~> ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtimeAdd the configuration for the NFS mount per your local configuration and test the mount comes up and all should be well on the next reboot.
01
02
03
04
05
06
07
08
09
10
| root@goat-lin001:~> vi /etc/fstab # /etc/fstab: static file system information. # # <file system> <mount point> <type> <options> <dump> <pass> proc /proc proc defaults 0 0 devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=620 0 0 /dev/xvda1 / ext4 noatime,nodiratime,errors=remount-ro 0 1 192.168.1.2: /volume2/Scratch /mnt/scratch nfs auto,noatime,nolock, bg ,nfsvers=4,intr,tcp,actimeo=1800 0 0 root@goat-lin001:~> mount /mnt/scratch |
root@goat-lin001:~> vi /etc/fstab # /etc/fstab: static file system information. # # <file system> <mount point> <type> <options> <dump> <pass> proc /proc proc defaults 0 0 devpts /dev/pts devpts rw,noexec,nosuid,gid=5,mode=620 0 0 /dev/xvda1 / ext4 noatime,nodiratime,errors=remount-ro 0 1 192.168.1.2:/volume2/Scratch /mnt/scratch nfs auto,noatime,nolock,bg,nfsvers=4,intr,tcp,actimeo=1800 0 0 root@goat-lin001:~> mount /mnt/scratch
LDAP server configuration
An LDAP service provides a way for the guest VMs OS to authenticate users against a centralised database, and also to check for group membership amongst other things. The main purpose here is to avoid using local password databases across our VMs which would be difficult to maintain over time. I won't cover how to set up users and groups in the LDAP server since this will depend on what you have available in your setup and there are generally decent tutorials that will help you accomplish this. I will instead focus on configuring the guest VM.I have created a couple of groups on the LDAP server:
- unixusers: membership required to log in to a VM Guest
- sudo: membership required for ability for specific users to elevate privileges via sudo cmd
Note that you may not want some of your accounts to be able to log in remotely or to elevate privileges (such as service accounts you may set up to run an application). So the above is a fairly simple way to implement these restrictions.
You will need the following packages installed, with an optional package for testing ldap connectivity and set-up with the ldapsearch utility (it's really quite useful):
1
2
3
4
| root@goat-lin001:~> apt-get install ldap-auth-client nscd # For ldapsearch util (testing): root@goat-lin001:~> apt-get install ldap-utils |
root@goat-lin001:~> apt-get install ldap-auth-client nscd # For ldapsearch util (testing): root@goat-lin001:~> apt-get install ldap-utils
A starting point for LDAP configuration on Ubuntu can be found here, but I found a range of other useful resources that may help you extend my simple configuration or diagnose problems. The package installer will ask for a number of inputs that will handle most of the configuration. An overview of this is provided here.
Configure the LDAP profile for NSS by running:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| root@goat-lin001:~> sudo auth-client-config -t nss -p lac_ldap root@goat-lin001:~> cat /etc/nsswitch .conf # Example configuration of GNU Name Service Switch functionality. # If you have the `glibc-doc-reference' and `info' packages installed, try: # `info libc "Name Service Switch"' for information about this file. # pre_auth-client-config # passwd: compat systemd passwd : files ldap # pre_auth-client-config # group: compat systemd group: files ldap # pre_auth-client-config # shadow: compat shadow: files ldap gshadow: files hosts: files dns networks: files protocols: db files services: db files ethers: db files rpc: db files # pre_auth-client-config # netgroup: nis netgroup: nis |
root@goat-lin001:~> sudo auth-client-config -t nss -p lac_ldap root@goat-lin001:~> cat /etc/nsswitch.conf # Example configuration of GNU Name Service Switch functionality. # If you have the `glibc-doc-reference' and `info' packages installed, try: # `info libc "Name Service Switch"' for information about this file. # pre_auth-client-config # passwd: compat systemd passwd: files ldap # pre_auth-client-config # group: compat systemd group: files ldap # pre_auth-client-config # shadow: compat shadow: files ldap gshadow: files hosts: files dns networks: files protocols: db files services: db files ethers: db files rpc: db files # pre_auth-client-config # netgroup: nis netgroup: nisTo enable home directory creation on login:
1
2
3
4
5
6
7
| root@goat-lin001:~> vi /usr/share/pam-configs/my_mkhomedir Name: activate mkhomedir Default: yes Priority: 900 Session-Type: Additional Session: required pam_mkhomedir.so umask =0022 skel= /etc/skel |
root@goat-lin001:~> vi /usr/share/pam-configs/my_mkhomedir Name: activate mkhomedir Default: yes Priority: 900 Session-Type: Additional Session: required pam_mkhomedir.so umask=0022 skel=/etc/skelIn this case /etc/skel would contain the full contents of the user's home directory.
You may want the default shell for users to be something other than /bin/sh, so fix that by editing /etc/default/useradd and changing: SHELL=/bin/sh to whatever suits your taste. You can use chsh or edit /etc/passwd to change the shell if it's already been set. Note that this works for local users, but not LDAP users, and we'll look at how to deal with that a bit later.
1
2
3
4
5
6
7
| root@goat-lin001:~> vi /usr/share/pam-configs/my_groups Name: activate /etc/security/group .conf Default: yes Priority: 900 Auth-Type: Primary Auth: required pam_group.so use_first_pass |
root@goat-lin001:~> vi /usr/share/pam-configs/my_groups Name: activate /etc/security/group.conf Default: yes Priority: 900 Auth-Type: Primary Auth: required pam_group.so use_first_passThese changes now need to be activated. You may see many more options in the PAM configuration screen than those shown, there is generally one profile to confirm enablement per module you enable.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| root@goat-lin001:~ # pam-auth-update Package configuration ┌───────────────────────────┤ PAM configuration ├───────────────────────────┐ │ Pluggable Authentication Modules (PAM) determine how authentication, │ │ authorization, and password changing are handled on the system, as well │ │ as allowing configuration of additional actions to take when starting │ │ user sessions. │ │ │ │ Some PAM module packages provide profiles that can be used to │ │ automatically adjust the behavior of all PAM-using applications on the │ │ system. Please indicate which of these behaviors you wish to enable . │ │ │ │ PAM profiles to enable : │ │ │ │ [*] activate mkhomedir │ │ [*] activate /etc/security/group .conf │ │ [*] Unix authentication │ │ │ │ │ │ <Ok> <Cancel> │ │ │ └───────────────────────────────────────────────────────────────────────────┘ root@goat-lin001:~ # /etc/init.d/nscd restart Restarting nscd (via systemctl): nscd.service. |
root@goat-lin001:~# pam-auth-update Package configuration ┌───────────────────────────┤ PAM configuration ├───────────────────────────┐ │ Pluggable Authentication Modules (PAM) determine how authentication, │ │ authorization, and password changing are handled on the system, as well │ │ as allowing configuration of additional actions to take when starting │ │ user sessions. │ │ │ │ Some PAM module packages provide profiles that can be used to │ │ automatically adjust the behavior of all PAM-using applications on the │ │ system. Please indicate which of these behaviors you wish to enable. │ │ │ │ PAM profiles to enable: │ │ │ │ [*] activate mkhomedir │ │ [*] activate /etc/security/group.conf │ │ [*] Unix authentication │ │ │ │ │ │ <Ok> <Cancel> │ │ │ └───────────────────────────────────────────────────────────────────────────┘ root@goat-lin001:~# /etc/init.d/nscd restart Restarting nscd (via systemctl): nscd.service.
There are other configuration options for PAM which you can read about here.
If you find difficulties with the LDAP configuration you can edit /etc/ldap.conf or use dpkg-reconfigure to re-run the installation script, or run it directly /usr/sbin/pam-auth-update.
1
2
3
4
5
| root@goat-lin001:~> ls -al /etc/ldap .secret -rw-r--r-- 1 root root 5 Apr 21 01:06 /etc/ldap .secret root@goat-lin001:~> chmod 600 /etc/ldap .secret root@goat-lin001:~> ls -al /etc/ldap .secret -rw------- 1 root root 5 Apr 21 01:06 /etc/ldap .secret |
root@goat-lin001:~> ls -al /etc/ldap.secret -rw-r--r-- 1 root root 5 Apr 21 01:06 /etc/ldap.secret root@goat-lin001:~> chmod 600 /etc/ldap.secret root@goat-lin001:~> ls -al /etc/ldap.secret -rw------- 1 root root 5 Apr 21 01:06 /etc/ldap.secret
Add the following as the last line of /etc/security/access.conf
- -:ALL EXCEPT root (unixusers):ALL
Recall that we created unixusers as a group in the LDAP server.
Add the
highlighted line to
/etc/pam.d/common-account
to get
PAM to use
/etc/security/access.conf config above.
1
2
| account required pam_permit.so account required pam_access.so |
account required pam_permit.so account required pam_access.so
LDAP troubleshooting
I found that a fair bit of digging and trial and error was required to get my LDAP configuration up and running with the various tweaks I was interested in having working. Some of the documentation is unclear or incomplete, and there are some interesting side-effects of switching to LDAP. I've included a few insights I got below in the hope that they may assist you in troubleshooting your own configuration.
Testing LDAP queries with ldapsearch
Sometimes you may not be sure that the LDAP configuration or data are correct. One way to get direct feedback on this is to use the ldapsearch utility.
01
02
03
04
05
06
07
08
09
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
| root@goat-lin010: /etc/pam .d> ldapsearch -x -h ldap.webber.net -D "uid=root,cn=users,dc=ldap,dc=webber,dc=net" -w none -b "dc=ldap,dc=webber,dc=net" -s sub "(uid=gsw)" # extended LDIF # # LDAPv3 # base <dc=ldap,dc=webber,dc=net> with scope subtree # filter: (uid=gsw) # requesting: ALL # # gsw, users, ldap.webber.net dn: uid=gsw,cn= users , dc =ldap, dc =webber, dc =net objectClass: top objectClass: posixAccount objectClass: shadowAccount objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: apple-user objectClass: sambaSamAccount objectClass: sambaIdmapEntry objectClass: extensibleObject cn: gsw uid: gsw uidNumber: 1000001 gidNumber: 1000001 loginShell: /bin/sh homeDirectory: /home/gsw shadowLastChange: 16921 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 shadowExpire: -1 shadowInactive: 0 shadowFlag: 0 sn: gsw authAuthority: ;basic; sambaSID: S-1-5-21-13ABC813-33DEF77G36-21ZCR119X5-1092 sambaNTPassword: 283****C149 sambaLMPassword: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX sambaPasswordHistory: 00000000000000000000000000000000000000000000000000000000 00000000 sambaPwdLastSet: 1461995430 sambaAcctFlags: [U ] displayName: gsw userPassword:: e0NSWVBU***************************hhLldFbl*****ahFYXov memberOf: cn=administrators,cn= groups , dc =ldap, dc =webber, dc =net memberOf: cn= users ,cn= groups , dc =ldap, dc =webber, dc =net memberOf: cn=unixusers,cn= groups , dc =ldap, dc =webber, dc =net gecos: This is a description # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 # numResponses: 1 |
root@goat-lin010:/etc/pam.d> ldapsearch -x -h ldap.webber.net -D "uid=root,cn=users,dc=ldap,dc=webber,dc=net" -w none -b "dc=ldap,dc=webber,dc=net" -s sub "(uid=gsw)" # extended LDIF # # LDAPv3 # base <dc=ldap,dc=webber,dc=net> with scope subtree # filter: (uid=gsw) # requesting: ALL # # gsw, users, ldap.webber.net dn: uid=gsw,cn=users,dc=ldap,dc=webber,dc=net objectClass: top objectClass: posixAccount objectClass: shadowAccount objectClass: person objectClass: organizationalPerson objectClass: inetOrgPerson objectClass: apple-user objectClass: sambaSamAccount objectClass: sambaIdmapEntry objectClass: extensibleObject cn: gsw uid: gsw uidNumber: 1000001 gidNumber: 1000001 loginShell: /bin/sh homeDirectory: /home/gsw shadowLastChange: 16921 shadowMin: 0 shadowMax: 99999 shadowWarning: 7 shadowExpire: -1 shadowInactive: 0 shadowFlag: 0 sn: gsw authAuthority: ;basic; sambaSID: S-1-5-21-13ABC813-33DEF77G36-21ZCR119X5-1092 sambaNTPassword: 283****C149 sambaLMPassword: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX sambaPasswordHistory: 00000000000000000000000000000000000000000000000000000000 00000000 sambaPwdLastSet: 1461995430 sambaAcctFlags: [U ] displayName: gsw userPassword:: e0NSWVBU***************************hhLldFbl*****ahFYXov memberOf: cn=administrators,cn=groups,dc=ldap,dc=webber,dc=net memberOf: cn=users,cn=groups,dc=ldap,dc=webber,dc=net memberOf: cn=unixusers,cn=groups,dc=ldap,dc=webber,dc=net gecos: This is a description # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1 # numResponses: 1
Testing user and group membership
You can see whether your user is getting looked up via LDAP. You are looking for Ids that match those set up in LDAP rather than your local system - in the example above the entry uidNumber: 1000001 matches what the id command returns for the user gsw.
1
2
| root @goat -lin010:/etc/pam.d# id gsw uid= 1000001 (gsw) gid= 1000001 (users) groups= 1000001 (users), 1000002 (administrators) |
root@goat-lin010:/etc/pam.d# id gsw uid=1000001(gsw) gid=1000001(users) groups=1000001(users),1000002(administrators)
Persist local user configuration
You may notice that setting user shells and other config locally doesn't work once you've enabled LDAP. Many of these settings are now controlled by LDAP configuration. In the following example, an LDIF file is created to change the login shell of a user, which is applied with the ldapmodify command.
01
02
03
04
05
06
07
08
09
10
11
| root@goat-lin001:~> cat test1.shellchange.ldif dn: uid=test1,cn= users , dc =ldap, dc =webber, dc =net changetype: modify replace: loginShell loginShell: /bin/bash root@goat-lin001:~> ldapmodify -f test1.shellchange.ldif -h ldap.webber.net -D "uid=root,cn=users,dc=ldap,dc=webber,dc=net" -W Enter LDAP Password: modifying entry "uid=test1,cn=users,dc=ldap,dc=webber,dc=net" root@goat-lin001:~> ldapsearch -x -h ldap.webber.net -D "uid=root,cn=users,dc=ldap,dc=webber,dc=net" -w none -b "dc=ldap,dc=webber,dc=net" -s sub "(uid=test1)" | grep loginShell loginShell: /bin/bash |
root@goat-lin001:~> cat test1.shellchange.ldif dn: uid=test1,cn=users,dc=ldap,dc=webber,dc=net changetype: modify replace: loginShell loginShell: /bin/bash root@goat-lin001:~> ldapmodify -f test1.shellchange.ldif -h ldap.webber.net -D "uid=root,cn=users,dc=ldap,dc=webber,dc=net" -W Enter LDAP Password: modifying entry "uid=test1,cn=users,dc=ldap,dc=webber,dc=net" root@goat-lin001:~> ldapsearch -x -h ldap.webber.net -D "uid=root,cn=users,dc=ldap,dc=webber,dc=net" -w none -b "dc=ldap,dc=webber,dc=net" -s sub "(uid=test1)" | grep loginShell loginShell: /bin/bash
There seemed to be some flakeyness in my setup which meant this didn't always work, so an alternative for lab environments might just be to add the following to /etc/ldap.conf:
- nss_override_attribute_value loginShell /bin/bash
Help! id -a and getent show different data for the same users
Another
issue I encountered was that running id -a and getent groups would show
different groups. It seems that some of the data is looked up and cached and needs to be invalidated. This is normally done in /etc/init.d/nscd which calls nscd --invalidate=<element> at shutdown but if you're testing your configuration out and making live updates to both the LDAP server and your local configuration you may find that you need to force a new lookup to see the latest data. The following example shows how adding a user to a group in the LDAP server isn't immediately reflected on the local LDAP client.
1
2
3
4
5
| root@goat-lin001:~> id gsw uid=1000001(gsw) gid=1000001( users ) groups =1000001( users ) root@goat-lin001:~> nscd --invalidate=group root@goat-lin001:~> id gsw uid=1000001(gsw) gid=1000001( users ) groups =1000001( users ),1000002(administrators),1000003(unixusers),1000004( sudo ) |
root@goat-lin001:~> id gsw uid=1000001(gsw) gid=1000001(users) groups=1000001(users) root@goat-lin001:~> nscd --invalidate=group root@goat-lin001:~> id gsw uid=1000001(gsw) gid=1000001(users) groups=1000001(users),1000002(administrators),1000003(unixusers),1000004(sudo)
No comments:
Post a Comment