Environment
Novell Open Enterprise Server 2 SP1 (OES2SP1)
Novell Open Enterprise Server 2 SP2 (OES2SP2)
Novell Open Enterprise Server 2 SP3 (OES2SP3)
DSFW
Citrix Xenserver 5.6
Situation
The Xenserver fails to join a DSfW domain.
Resolution
Below are the five attributes:
- PasswordExpirationInterval
- PasswordMinimumLength
- nspmConfigurationOptions
- nspmMinPasswordLifetime
- pwdInHistory
Run the following script to make the attributes readable. Copy and past the python script below into a text editor. Save the file as a python script, e.g. modify_attr.py
If the script was created on a Windows workstation run dos2unix to ensure extra characters are removed.
e.g. dos2unix modify_attry.py
Make the script executable, e.g. chmod 755 modify_attr.py
Run the script and it will make the necessary attributes readable. e.g. ./modify_attr.py
###########################################################################
#!/usr/bin/env python
import os
import commands
import random
#This Script will add ACLs for 5 Password Policy attributes namely
#1) PasswordExpirationInterval
#2) PasswordMinimumLength
#3) nspmConfigurationoptions
#4) nspmminPasswordlifetimE
#5) pwdInHistory
attr_already_exits = 20
effective_rights ={'PASSWORDEXPIRATIONINTERVAL': 3, 'PASSWORDMINIMUMLENGTH': 3,'NSPMCONFIGURATIONOPTIONS': 3, 'NSPMMINPASSWORDLIFETIME': 3, 'PWDINHISTORY': 3}
pwd_attrs = ['PASSWORDEXPIRATIONINTERVAL', 'PASSWORDMINIMUMLENGTH', 'NSPMCONFIGURATIONOPTIONS', 'NSPMMINPASSWORDLIFETIME', 'PWDINHISTORY']
#create a random file name
ldif_file_name = '/tmp/' + 'modify_pwd_attr' + str(random.random()) + '.ldif'
ldif_delete_acl = '/tmp/' + 'delete_pwd_attr' + str(random.random()) + '.ldif'
cmd_mod = 'LDAPCONF=/etc/opt/novell/xad/openldap/ldap.conf ldapmodify -c -Y EXTERNAL -f '+ ldif_file_name
cmd_delete = 'LDAPCONF=/etc/opt/novell/xad/openldap/ldap.conf ldapmodify -c -Y EXTERNAL -f '+ ldif_delete_acl
def getDomainName():
#do an ldapsearch and get the value of defaultNamingContext
domain_name = ""
cmd = 'LDAPCONF=/etc/opt/novell/xad/openldap/ldap.conf ldapsearch -LLL -Y EXTERNAL -b "" -s base defaultNamingContext'
commandOutput = commands.getstatusoutput(cmd)
if commandOutput[0] != 0:
print "Ldap Search Error:[",commandOutput[1],']'
else:
for obj in commandOutput[1].split('\n'):
if obj.split(':')[0] == 'defaultNamingContext':
domain_name = obj.split(':')[1].strip()
return domain_name
def searchExistingAttrs(domain_name):
#command to search for exising ACLs on "Domain Computers"
delete_reqd = 0
cmd_search = 'LDAPCONF=/etc/opt/novell/xad/openldap/ldap.conf ldapsearch -LLL -Y EXTERNAL -b '+ domain_name +' -s base ACL | sed " /^ / {; H; d; }; /^ /! {; x; s/\\n //; }; " | grep "Domain Computers"'
fileH = open(ldif_delete_acl,'w')
fileH.write('dn: '+ domain_name +'\n')
fileH.write('changetype: modify\n')
fileH.write('delete: ACL\n')
commandOutput = commands.getstatusoutput(cmd_search)
if commandOutput[0] != 0:
print 'No preexisting ACLs found during the search on "Domain Computers"'
else:
for obj in commandOutput[1].split('\n'):
if obj.split(':')[0] == 'ACL':
for attr in pwd_attrs:
if(obj.upper().find(attr) != -1):
rights_existing = int(obj.split(':')[1].split('#')[0])
if rights_existing != effective_rights[attr]:
acl_rights = effective_rights[attr]
effective_rights[attr] = acl_rights | rights_existing
fileH.write('ACL: '+str(rights_existing)+'#subtree#cn=Domain Computers,cn=Users,'+ domain_name +'#'+attr+'\n')
delete_reqd = 1
fileH.close()
return delete_reqd
def deleteExistingAttrs(domain_name):
#delete the attributes
#run ldapmodify with the ldif file as an argument
commandOutput = commands.getstatusoutput(cmd_delete)
if commandOutput[0] != 0:
print "Ldap Delete Error:[",commandOutput[1],']'
raise Exception('Error in ldapdelete')
os.system('rm -rf ' +ldif_delete_acl)
return
def updateNewAttrs(domain_name):
#create a random ldif file in /tmp dir
fileHandle = open(ldif_file_name,'w')
fileHandle.write('dn: '+ domain_name +'\n')
fileHandle.write('changetype: modify\n')
fileHandle.write('add: ACL\n')
fileHandle.write('ACL: '+str(effective_rights['PASSWORDEXPIRATIONINTERVAL'])+'#subtree#cn=Domain Computers,cn=Users,'+ domain_name +'#PasswordExpirationInterval\n')
fileHandle.write('\n');
fileHandle.write('dn: '+ domain_name +'\n')
fileHandle.write('changetype: modify\n')
fileHandle.write('add: ACL\n')
fileHandle.write('ACL: '+str(effective_rights['PASSWORDMINIMUMLENGTH'])+'#subtree#cn=Domain Computers,cn=Users,'+ domain_name +'#PasswordMinimumLength\n')
fileHandle.write('\n');
fileHandle.write('dn: '+ domain_name +'\n')
fileHandle.write('changetype: modify\n')
fileHandle.write('add: ACL\n')
fileHandle.write('ACL: '+str(effective_rights['NSPMCONFIGURATIONOPTIONS'])+'#subtree#cn=Domain Computers,cn=Users,'+ domain_name +'#nspmConfigurationOptions\n')
fileHandle.write('\n');
fileHandle.write('dn: '+ domain_name +'\n')
fileHandle.write('changetype: modify\n')
fileHandle.write('add: ACL\n')
fileHandle.write('ACL: '+str(effective_rights['NSPMMINPASSWORDLIFETIME'])+'#subtree#cn=Domain Computers,cn=Users,'+ domain_name +'#nspmMinPasswordLifetime\n')
fileHandle.write('\n');
fileHandle.write('dn: '+ domain_name +'\n')
fileHandle.write('changetype: modify\n')
fileHandle.write('add: ACL\n')
fileHandle.write('ACL: '+str(effective_rights['PWDINHISTORY'])+'#subtree#cn=Domain Computers,cn=Users,'+ domain_name +'#pwdInHistory\n')
fileHandle.write('\n');
fileHandle.close()
#run ldapmodify with the ldif file as an argument
commandOutput = commands.getstatusoutput(cmd_mod)
result = commandOutput[0]>> 8
if result != 0 and result != attr_already_exits:
print "Ldap Modify Error:[",commandOutput[1],']'
raise Exception('Error in ldapmodify')
os.system('rm -rf ' + ldif_file_name)
print "Update Sucessful"
return
# main starts here
try:
domain_name = getDomainName()
if searchExistingAttrs(domain_name):
deleteExistingAttrs(domain_name)
updateNewAttrs(domain_name)
except Exception,err:
print "Update Failed:Cannot continue...Reason-->[",err,"]"
os.system('rm -rf ' + ldif_file_name)