shadow文件的格式就不說了。就說說它的第二列——密碼列。python
一般,passwd直接爲用戶指定密碼就ok了。但在某些狀況下,要爲待建立的用戶事先指定密碼,還要求是加密後的密碼,例如kickstart文件中的rootpw指令,ansible建立用戶時提早指定密碼等,這時候不得不手動生成合理的密碼。算法
先說說shadow文件中第二列的格式,它是加密後的密碼,它有些玄機,不一樣的特殊字符表示特殊的意義:shell
目前基本上都使用sha-512算法的,但不管是md5仍是sha-256都仍然支持。$salt$是加密時使用的salt,hashed纔是真正的密碼部分。dom
下文都以生成明文"123456"對應的加密密碼爲例。ssh
要生成md5算法的密碼,使用openssl便可。工具
openssl passwd -1 '123456' openssl passwd -1 -salt 'abcdefg' '123456'
生成密碼後,直接將其拷貝或替換到shadow文件的第二列便可。例如:替換root用戶的密碼this
shell> field=$(awk -F ':' '/^root/{print $2}' /etc/shadow) shell> password=$(openssl passwd -1 123456) shell> sed -i '/^root/s%'$field'%'$password'%' /etc/shadow
但openssl passwd不支持生成sha-256和sha-512算法的密碼。在CentOS 6上,能夠藉助grub提供的密碼生成工具grub-crypt生成。加密
[root@server1 ~]# grub-crypt -h Usage: grub-crypt [OPTION]... Encrypt a password. -h, --help Print this message and exit -v, --version Print the version information and exit --md5 Use MD5 to encrypt the password --sha-256 Use SHA-256 to encrypt the password --sha-512 Use SHA-512 to encrypt the password (default) Report bugs to <bug-grub@gnu.org>. EOF
[root@server1 ~]# grub-crypt --sha-512 Password: Retype password: $6$nt4hMDAYqYjudvfo$AKIZ3Z0o6/6HV6GKXqq21VEmh.ADFAZUQw2mvbIlplKx7gu9MQiEWjdmHnF2YPnYzgce1cP/bzDguVnUkMg/N.
grub-crypt實際上是一個python腳本,交互式生成密碼。如下是grub-crypt文件的內容。spa
[root@server1 ~]# cat /sbin/grub-crypt #! /usr/bin/python '''Generate encrypted passwords for GRUB.''' import crypt import getopt import getpass import sys def usage(): '''Output usage message to stderr and exit.''' print >> sys.stderr, 'Usage: grub-crypt [OPTION]...' print >> sys.stderr, 'Try `$progname --help\' for more information.' sys.exit(1) def gen_salt(): # 生成隨機的salt '''Generate a random salt.''' ret = '' with open('/dev/urandom', 'rb') as urandom: while True: byte = urandom.read(1) if byte in ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' './0123456789'): ret += byte if len(ret) == 16: break return ret def main(): '''Top level.''' crypt_type = '$6$' # SHA-256 try: opts, args = getopt.getopt(sys.argv[1:], 'hv', ('help', 'version', 'md5', 'sha-256', 'sha-512')) except getopt.GetoptError, err: print >> sys.stderr, str(err) usage() if args: print >> sys.stderr, 'Unexpected argument `%s\'' % (args[0],) usage() for (opt, _) in opts: if opt in ('-h', '--help'): print ( '''Usage: grub-crypt [OPTION]... Encrypt a password. -h, --help Print this message and exit -v, --version Print the version information and exit --md5 Use MD5 to encrypt the password --sha-256 Use SHA-256 to encrypt the password --sha-512 Use SHA-512 to encrypt the password (default) Report bugs to <bug-grub@gnu.org>. EOF''') sys.exit(0) elif opt in ('-v', '--version'): print 'grub-crypt (GNU GRUB 0.97)' sys.exit(0) elif opt == '--md5': crypt_type = '$1$' elif opt == '--sha-256': crypt_type = '$5$' elif opt == '--sha-512': crypt_type = '$6$' else: assert False, 'Unhandled option' password = getpass.getpass('Password: ') password2 = getpass.getpass('Retype password: ') if not password: print >> sys.stderr, 'Empty password is not permitted.' sys.exit(1) if password != password2: print >> sys.stderr, 'Sorry, passwords do not match.' sys.exit(1) salt = crypt_type + gen_salt() print crypt.crypt(password, salt) # 生成最終的加密密碼 if __name__ == '__main__': main()
很不幸,CentOS 7上默認安裝的是grub2,它不提供grub-crypt。所以參照grub-crypt內容,使用下面的python語句簡單代替grub-crypt,這一樣也是交互式的。code
python -c 'import crypt,getpass;pw=getpass.getpass();print(crypt.crypt(pw) if (pw==getpass.getpass("Confirm: ")) else exit())'
若是不想交互式,再改爲以下形式:
python -c 'import crypt,getpass;pw="123456";print(crypt.crypt(pw))'
如今就方便多了,直接將結果賦值給變量便可。
[root@server1 ~]# a=$(python -c 'import crypt,getpass;pw="123456";print(crypt.crypt(pw))') [root@server1 ~]# echo $a $6$uKhnBg5A4/jC8KaU$scXof3ZwtYWl/6ckD4GFOpsQa8eDu6RDbHdlFcRLd/2cDv5xYe8hzw5ekYCV5L2gLBBSfZ.Uc166nz6TLchlp.
例如,ansible建立用戶並指定密碼:
a=$(python -c 'import crypt,getpass;pw="123456";print(crypt.crypt(pw))') ansible 192.168.100.55 -m user -a 'name=longshuai5 password="$a" update_password=always'