Initial commit of users role
Change-Id: I808c990019b059e0a412986d9b4c010689255581
diff --git a/goodpassword.py b/goodpassword.py
new file mode 100755
index 0000000..29719dd
--- /dev/null
+++ b/goodpassword.py
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+#
+# SPDX-FileCopyrightText: © 2020 Open Networking Foundation <support@opennetworking.org>
+# SPDX-License-Identifier: Apache-2.0
+
+# goodpassword.py
+
+import getpass
+import sys
+import zxcvbn
+from passlib.hash import bcrypt, sha512_crypt
+
+MIN_LEN = 12
+REQ_SCORE = 4
+
+print("goodpassword.py - generates unix password hashes of high quality")
+pw = getpass.getpass()
+
+# reject short passwords
+pwlen = len(pw)
+if pwlen < MIN_LEN:
+ print(
+ "Passwords must be at least %d characters long (the one supplied was %d)."
+ % (MIN_LEN, pwlen)
+ )
+ sys.exit(1)
+
+# generate password score
+zxscore = zxcvbn.zxcvbn(pw)
+
+# Print any suggestions
+if zxscore["feedback"]["warning"]:
+ print("Warning: %s" % zxscore["feedback"]["warning"])
+
+if zxscore["feedback"]["suggestions"]:
+ print("Suggestions:")
+ for suggestion in zxscore["feedback"]["suggestions"]:
+ print(" - %s" % suggestion)
+
+print(
+ "This password had a complexity score of %d (must score at least %d)"
+ % (zxscore["score"], REQ_SCORE)
+)
+
+print(
+ "Time to crack: %s"
+ % zxscore["crack_times_display"]["offline_slow_hashing_1e4_per_second"]
+)
+
+years = 5
+min_crack_seconds = 60 * 60 * 24 * 365 * years # number of seconds per year
+# if the password crack time is too short
+if (
+ zxscore["crack_times_seconds"]["offline_slow_hashing_1e4_per_second"]
+ < min_crack_seconds
+):
+ print(
+ "This password was crackable in less than %d years, please make it longer/more complex"
+ % years
+ )
+ sys.exit(1)
+
+# if the password score is too low
+if zxscore["score"] < REQ_SCORE:
+ sys.exit(1)
+
+# password is high enough quality
+# this make take a short while so let the user know
+print("Generating password hashes...")
+print('bcrypt: "%s"' % bcrypt.using(rounds=16).hash(pw))
+print('sha512crypt: "%s"' % sha512_crypt.hash(pw))