315
312
for statement in _SQL_CONSTRAINTS:
316
313
persister.exec_stmt(statement)
318
for user_id, username, password, protocol in _USERS:
319
FabricCredential.add_user(username, password, protocol,
315
for user_id, username, protocol, password in _USERS:
316
User.add_user(username, password, protocol,
324
321
for permission_id, subsystem, component, function, description in \
326
FabricCredential.add_permission(
327
324
subsystem, component, function, description,
328
325
permission_id=permission_id, persister=persister)
330
327
for role_id, name, description in _ROLES:
331
FabricCredential.add_role(name, description, role_id=role_id,
328
User.add_role(name, description, role_id=role_id,
334
331
for role_id, permissions in _ROLE_PERMISSIONS.items():
335
332
for permission_id in permissions:
336
FabricCredential.add_role_permission(
333
User.add_role_permission(
337
334
role_id, permission_id, persister=persister)
339
336
for user_id, role_id in _USER_ROLES:
340
FabricCredential.add_user_role(user_id, role_id,
337
User.add_user_role(user_id, role_id,
344
341
def drop(persister=None):
513
509
if not user.password:
514
510
protocols.append(tmp)
512
# Try setting password for 'admin' user from configuration file
513
for protocol in protocols:
514
section = 'protocol.' + protocol
516
username = config.get(section, 'user')
517
except _config.NoOptionError:
520
# If there is no password, we have to ask for one.
522
password = config.get(section, 'password')
523
except _config.NoOptionError:
524
# No password, so we have to ask for one
529
if username != 'admin':
530
_LOGGER.info("Adding user %s/%s", username, protocol)
531
user_id = User.add_user(username, password, protocol,
534
_LOGGER.info("Initial password for %s/%s set", username,
536
_change_password(username, password, protocol, config,
538
except _errors.CredentialError as error:
539
print "Setting password cancelled."
540
_LOGGER.debug(str(error))
546
"Password set for {user}/{protocol} from configuration file."
547
).format(user=username, protocol=protocol)
551
if username != 'admin':
552
print "Note: {user}/{protocol} has no roles set!".format(
553
user=username, protocol=protocol
556
# No need to ask for password later for this protocol
557
protocols.remove(protocol)
516
559
if not protocols:
517
560
# Passwords are set
520
print("Finishing initial setup")
521
print("=======================")
522
print("Password for admin user is not yet set.")
563
if check_only and protocols:
565
"\nPassword for admin user is empty. Please run\n\n"
566
" shell> mysqlfabric user password admin\n\n"
567
"Make sure the password is empty or commented in section\n"
568
"[protocol.xmlrpc] of the configuration file before executing the\n"
571
raise _errors.CredentialError("Check empty admin password failed")
573
print "Finishing initial setup"
574
print "======================="
575
print "Password for admin user is not yet set."
526
password = _get_password("Password for {user}: ".format(user='admin'))
579
password = _get_password("Password for {user}/{protocol}: ".format(
580
user='admin', protocol='xmlrpc'))
537
update = ("UPDATE users SET password = %s WHERE username = %s "
540
585
for protocol in protocols:
541
hashed = _hash_password('admin', password, protocol, config)
542
options['params'] = (hashed, 'admin', protocol)
543
persister.exec_stmt(update, options)
587
_change_password('admin', password, protocol, config,
589
except _errors.CredentialError as error:
590
print "Setting password cancelled."
591
_LOGGER.debug(str(error))
594
print "Password set."
546
596
# Making sure password is set and there is an error message
547
597
raise _errors.CredentialError(
548
"Password for admin can not be empty.")
598
"Password for admin can not be empty. Use `user password` command.")
550
600
persister.commit()
714
766
name, role_desc, permissions = roles[role_id]
715
print(role_fmt.format(role_id=role_id, name=name, desc=role_desc,
767
print role_fmt.format(role_id=role_id, name=name, desc=role_desc,
717
769
for perm in permissions:
718
print(fmt_perm.format(perm=perm))
721
def _role_selection(message=None, persister=None):
770
print fmt_perm.format(perm=perm)
773
def _role_selection(message=None, choices=None, persister=None):
722
774
"""Offers user to select roles on the console
724
776
:param persister: A valid handle to the state store.
725
777
:param message: Message shown just before prompt.
778
:param choices: Do not ask, just process choices (string or sequence).
726
779
:return: List of role IDs or role names.
728
781
:raises errors.CredentialError: if invalid role was given
829
def _change_password(username, password, protocol, config, persister):
830
"""Change password of a Fabric user
832
:param username: Username of Fabric user.
833
:param password: Password to which we change.
834
:param protocol: Protocol for this user.
835
:param config: Fabric configuration.
836
:param persister: A valid handle to the state store.
838
:raise _errors.CredentialError: if any error occurs while updating data
848
update = ("UPDATE users SET password = %s WHERE username = %s"
849
" AND protocol = %s")
850
hashed = _hash_password(username, password, protocol,
852
options['params'] = (hashed, username, protocol)
853
persister.exec_stmt(update, options)
854
except Exception as error:
855
# We rollback and re-raise
857
raise _errors.CredentialError("Error updating password: {0}".format(
773
863
def validate_username(username, allow_empty=False):
774
864
"""Validates a username
891
985
"User {user}/{protocol} already exists".format(
892
986
user=username, protocol=protocol))
894
password = _get_password('Password:')
988
password = _get_password('Password: ')
897
991
raise _errors.CredentialError("Can not set empty password")
900
self.persister.begin()
901
user_id = FabricCredential.add_user(username, password, protocol)
902
print("\nSelect role(s) for new user")
995
role_list = [role.strip() for role in roles.split(',')]
997
print "\nSelect role(s) for new user"
904
roles = _role_selection(persister=self.persister)
906
print("You can always assign roles later using the "
907
"'user addrole' command")
999
role_list = _role_selection(persister=self.persister, choices=role_list)
1002
self.persister.begin()
1003
user_id = User.add_user(username, password, protocol)
1005
print ("You can always assign roles later using the "
1006
"'user addrole' command")
909
for role_id in roles:
910
FabricCredential.add_user_role(user_id, int(role_id))
1008
for role_id in role_list:
1009
User.add_user_role(user_id, int(role_id))
911
1010
except Exception:
912
1011
# Whatever happens, we rollback and re-raise
913
1012
self.persister.rollback()
914
print("Adding user cancelled.")
1013
print "Adding user cancelled."
917
1016
self.persister.commit()
918
print("Fabric user added.")
1017
print "Fabric user added."
921
1020
class UserDelete(UserCommand):
923
"""Delete a Fabric user"""
1022
"""Delete a Fabric user.
1024
* protocol: Protocol of the user (for example 'xmlrpc')
1025
* force: Do not ask for confirmation
925
1029
command_name = 'delete'
926
1030
description = 'Delete a Fabric user'
976
1084
"No user {user}/{protocol}".format(
977
1085
user=username, protocol=protocol))
979
password = _get_password('New password:')
1087
password = _get_password('New password: ')
983
self.persister.begin()
990
update = ("UPDATE users SET password = %s WHERE username = %s"
991
" AND protocol = %s")
992
hashed = _hash_password(username, password, protocol,
994
options['params'] = (hashed, username, protocol)
995
self.persister.exec_stmt(update, options)
997
# We rollback and re-raise
998
print("Changing password cancelled.")
1000
self.persister.commit()
1001
print("Password changed.")
1091
_change_password(username, password, protocol, self.config,
1093
except _errors.CredentialError as error:
1094
print "Changing password cancelled."
1095
_LOGGER.debug(str(error))
1098
print "Password changed."
1003
1100
raise _errors.CredentialError("Can not set empty password")
1006
1103
class UserRoles(UserCommand):
1008
"""Change roles for a Fabric user"""
1105
"""Change roles for a Fabric user
1107
* protocol: Protocol of the user (for example 'xmlrpc')
1108
* roles: Comma separated list of roles, IDs or names (see `role list`)
1010
1112
command_name = 'roles'
1011
1113
description = 'Change roles for a Fabric user'
1013
def execute(self, username, protocol=None):
1115
def execute(self, username, protocol=None, roles=None):
1014
1116
"""Change roles for a Fabric user
1016
1118
username, password, protocol = self._ask_credentials(
1017
username, ask_password=True)
1119
username, ask_password=False)
1019
1121
# Check if user exists
1020
1122
user = get_user(username, protocol)
1023
1125
"No user {user}/{protocol}".format(user=username,
1024
1126
protocol=protocol))
1026
self.persister.begin()
1030
"params": (user.user_id,),
1033
cur = self.persister.exec_stmt(
1034
"SELECT role_id FROM user_roles WHERE user_id = %s",
1036
current_roles = [row.role_id for row in cur]
1039
self.persister.begin()
1040
print("\nSelect new role(s) for user, replacing current roles.")
1041
print("Current roles are marke with an X.")
1128
exit_text_removed = (
1129
"Roles for {user}/{protocol} removed."
1130
).format(user=username, protocol=protocol)
1131
exit_text_updated = (
1132
"Roles for {user}/{protocol} updated."
1133
).format(user=username, protocol=protocol)
1141
"params": (user.user_id,),
1144
cur = self.persister.exec_stmt(
1145
"SELECT role_id FROM user_roles WHERE user_id = %s",
1147
current_roles = [row.role_id for row in cur]
1149
print "\nSelect new role(s) for user, replacing current roles."
1150
print "Current roles are marke with an X."
1042
1151
_role_listing(selected=current_roles)
1043
roles = _role_selection(persister=self.persister)
1152
role_list = _role_selection(persister=self.persister)
1046
confirm_text = "Remove all roles of user {username}?"
1047
exit_text = "Fabric user roles removed."
1156
"Remove all roles of user {user}/{protocol}?"
1157
).format(user=username, protocol=protocol)
1158
exit_text = exit_text_removed
1050
confirm_text = "Replace roles of user {username}?"
1051
exit_text = "Fabric user roles updated."
1162
"Replace roles of user {user}/{protocol}?"
1163
).format(user=username, protocol=protocol)
1164
exit_text = exit_text_updated
1054
if confirm(confirm_text.format(username=user.username),
1167
confirmed = confirm(confirm_text.format(username=user.username),
1170
# From command line option --roles
1172
if roles.strip() == "0":
1173
exit_text = exit_text_removed
1176
exit_text = exit_text_updated
1177
role_list = [role.strip() for role in roles.split(',')]
1179
role_list = _role_selection(persister=self.persister,
1184
self.persister.begin()
1188
"params": (user.user_id,),
1056
1191
self.persister.exec_stmt(
1057
1192
"DELETE FROM user_roles WHERE user_id = %s", options)
1058
for role_id in roles:
1059
FabricCredential.add_user_role(user.user_id, int(role_id))
1193
for role_id in role_list:
1194
User.add_user_role(user.user_id, int(role_id))
1196
# Whatever happens, we rollback and re-raise
1197
self.persister.rollback()
1198
print "Changing roles for user cancelled."
1061
exit_text = "Changing roles for user cancelled."
1064
# Whatever happens, we rollback and re-raise
1065
self.persister.rollback()
1066
print("Changing roles for user cancelled.")
1201
self.persister.commit()
1069
self.persister.commit()
1204
print "Changing roles cancelled."
1207
class UserList(UserCommand):
1208
"""List users and their roles
1212
command_name = 'list'
1213
description = 'List roles and their permissions'
1216
"""Display list of users
1218
persister = _persistence.current_persister()
1227
"SELECT u.username, u.protocol, r.name as role_name, "
1228
"r.description AS role_desc,"
1229
"p.permission_id, p.description AS perm_desc, p.subsystem, "
1230
"p.component, p.function "
1231
"FROM users as u LEFT JOIN user_roles AS ur USING (user_id) "
1232
"LEFT JOIN roles AS r USING (role_id) "
1233
"LEFT JOIN role_permissions USING (role_id) "
1234
"LEFT JOIN permissions AS p USING (permission_id) "
1235
"ORDER BY u.username, u.protocol"
1237
cur = persister.exec_stmt(role_perms, options)
1239
max_username_len = 0
1240
max_protocol_len = 0
1244
if len(row.username) > max_username_len:
1245
max_username_len = len(row.username)
1246
if len(row.protocol) > max_protocol_len:
1247
max_protocol_len = len(row.protocol)
1249
user_tuple = (row.username, row.protocol)
1250
if user_tuple not in user_info:
1251
user_info[user_tuple] = []
1252
if row.role_name and row.role_name not in user_info[user_tuple]:
1253
user_info[user_tuple].append(row.role_name)
1256
max_username_len = max(9, max_username_len)
1257
max_protocol_len = max(12, max_protocol_len)
1259
role_fmt = ("{{username:{userlen}}} {{protocol:{protlen}}} "
1260
"{{roles}}".format(userlen=max_username_len,
1261
protlen=max_protocol_len))
1263
header = role_fmt.format(username="Username", protocol="Protocol",
1266
print role_fmt.format(username='-' * max_username_len,
1267
protocol='-' * max_protocol_len,
1270
for user_tuple, roles in user_info.iteritems():
1271
username, protocol = user_tuple
1273
role_list = ', '.join(roles)
1275
role_list = '(no roles set)'
1276
print role_fmt.format(username=username,
1073
1281
class RoleList(UserCommand):
1075
"""List roles and their permissions"""
1282
"""List roles and associated permissions
1077
1285
group_name = 'role'
1078
1286
command_name = 'list'
1098
1306
section = 'protocol.' + protocol
1101
username = config.get(section, 'username')
1102
password = config.get(section, 'password')
1103
realm = config.get(section, 'realm', vars=FABRIC_PROTOCOL_DEFAULTS)
1308
username = config.get(section, 'user')
1309
password = config.get(section, 'password')
1310
realm = config.get(section, 'realm', vars=FABRIC_PROTOCOL_DEFAULTS)
1105
user = FabricCredential.fetch_user(username, protocol, config,
1106
password=password, realm=realm)
1312
user = User.fetch_user(username, protocol, config,
1313
password=password, realm=realm)
1110
traceback.print_exc()
1316
_LOGGER.info("Failed login for user %s/%s", username, protocol)
1111
1317
raise _errors.CredentialError("Login failed")
1112
1318
if not user.has_permission('core', group, command):
1319
_LOGGER.info("Permission denied for user %s/%s", username, protocol)
1113
1320
raise _errors.CredentialError("No permission")