--- /dev/null
+import ConfigParser
+
+import logging
+import os
+import sys
+import M2Crypto
+import time
+
+from keystoneauth1.identity import v3
+from keystoneauth1 import session
+from keystoneauth1.exceptions.http import Conflict
+from keystoneclient import utils
+from keystoneclient.v3 import client
+
+sys.path.append('{{ lib_source_folder }}')
+from access_management.db.amdb import AMDatabase
+from access_management.cryptohelper.decryptaaafiles import DecryptAAAFile
+
+
+def get_config():
+ config = ConfigParser.ConfigParser()
+ config.read("/{{ am_plugin_config_path }}")
+ config_dict = {s: dict(config.items(s)) for s in config.sections()}
+ return config_dict
+
+
+def set_logger():
+ logger = logging.getLogger("DBfiller")
+ shandler = logging.StreamHandler(sys.stdout)
+ shandler.setLevel(logging.DEBUG)
+ formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+ shandler.setFormatter(formatter)
+ logger.addHandler(shandler)
+ logger.info("logger set")
+ return logger
+
+
+def close_logger_handlers(logger):
+ for handler in logger.handlers:
+ logger.removeHandler(handler)
+
+
+def read_files():
+ users = []
+ roles = []
+ permissions = []
+ user_roles = []
+ role_permissions = []
+ dir = "{{ am_server_values_dir }}"
+ for encrypted_file in os.listdir(dir):
+ if os.stat(os.path.join(dir, encrypted_file)).st_uid is not 0:
+ print "--- File: ", encrypted_file, "is not of root, skipping"
+ continue
+ try:
+ crypter = DecryptAAAFile("{{ am_server_temp_dir }}/am_pri_key.pem")
+ jsoned_content = crypter.decrypt_file(os.path.join(dir, encrypted_file))
+ for user in jsoned_content["users"]:
+ users.append(user)
+ for role in jsoned_content["roles"]:
+ roles.append(role)
+ for permission in jsoned_content["permissions"]:
+ permissions.append(permission)
+ for user_role in jsoned_content["user_roles"]:
+ user_roles.append(user_role)
+ for role_permission in jsoned_content["role_permissions"]:
+ role_permissions.append(role_permission)
+ except M2Crypto.RSA.RSAError as ex:
+ print "Failed to decrypt file: {}, {}".format(encrypted_file, str(ex))
+ except Exception as ex:
+ print "File {} failed with error: {}".format(encrypted_file, str(ex))
+ users = map(list, set(map(tuple, users)))
+ roles = map(list, set(map(tuple, roles)))
+ permissions = map(list, set(map(tuple, permissions)))
+ user_roles = map(list, set(map(tuple, user_roles)))
+ role_permissions = map(list, set(map(tuple, role_permissions)))
+ return {"users": users, "roles": roles, "permissions": permissions, "user_roles": user_roles, "role_permissions": role_permissions}
+
+
+def get_db_content(db):
+ db.create_tables()
+ users = db.get_user_table()
+ roles = db.get_role_table()
+ permissions = db.get_resource_table()
+ user_roles = db.get_user_role_table()
+ role_permissions = db.get_role_resource_table()
+ return {"users": users, "roles": roles, "permissions": permissions, "user_roles": user_roles, "role_permissions": role_permissions}
+
+
+def compare_contents(db_content, files_content):
+ update_needed = {"roles":[], "permissions":[]}
+ adding_needed = {"users":[], "roles":[], "permissions":[], "user_roles":[], "role_permissions":[]}
+ for file_user in files_content["users"]:
+ if check_user_value(file_user, db_content["users"]):
+ print "User " + file_user[0] + " is ok"
+ else:
+ print "User " + file_user[0] + " needs to be added"
+ adding_needed["users"].append(file_user)
+
+ for file_role in files_content["roles"]:
+ result = check_role_value(file_role, db_content["roles"])
+ if result == "update":
+ if file_role[2] == "True":
+ file_role[2] = 1
+ if file_role[2] == "False":
+ file_role[2] = 0
+ update_needed["roles"].append(file_role)
+ elif result == "add":
+ print "Role " + file_role[0] + " needs to be added"
+ if file_role[2] == "True":
+ file_role[2] = 1
+ if file_role[2] == "False":
+ file_role[2] = 0
+ adding_needed["roles"].append(file_role)
+ if file_role[2] == 1:
+ adding_needed["role_permissions"].append([file_role[0],"am/users/keys","POST"])
+ adding_needed["role_permissions"].append([file_role[0],"am/users/keys","DELETE"])
+ print "am/users/keys permissions also needs to be added for role " + file_role[0]
+ else:
+ print "Role " + file_role[0] + " is ok"
+
+ for file_permission in files_content["permissions"]:
+ result = check_permission_value(file_permission,db_content["permissions"])
+ if result == "update":
+ print "Permission " + file_permission[0] + ":" + file_permission[1] + " needs update due to changed description"
+ update_needed["permissions"].append(file_permission)
+ elif result == "add":
+ print "Permission " + file_permission[0] + ":" + file_permission[1] + " needs to be added"
+ adding_needed["permissions"].append(file_permission)
+ else:
+ print "Permission " + file_permission[0] + ":" + file_permission[1] + " is ok"
+
+ for file_user_role in files_content["user_roles"]:
+ if not check_user_role_value(file_user_role, db_content["user_roles"]):
+ adding_needed["user_roles"].append(file_user_role)
+
+ for file_role_permission in files_content["role_permissions"]:
+ if not check_role_permission_value(file_role_permission, db_content["role_permissions"]):
+ adding_needed["role_permissions"].append(file_role_permission)
+
+ return (update_needed, adding_needed)
+
+
+def check_user_value(file_content, db_content):
+ for db_user in db_content:
+ if file_content[0] == db_user["name"]:
+ return True
+ return False
+
+
+def check_permission_value(file_content, db_content):
+ for db_permission in db_content:
+ if file_content[0] == db_permission["path"] and file_content[1] == db_permission["op"]:
+ if file_content[2] == db_permission["desc"]:
+ return "ok"
+ else:
+ return "update"
+ return "add"
+
+
+def check_role_permission_value(file_content, db_content):
+ for db_role_permission in db_content:
+ if file_content[0] == db_role_permission["name"] and file_content[1] == db_role_permission["path"] and file_content[2] == db_role_permission["op"]:
+ print "Role_permission " + file_content[0] + ":" + file_content[1] + ":" + file_content[2] + " is ok"
+ return True
+ print "Role_permission " + file_content[0] + ":" + file_content[1] + ":" + file_content[2] + " needs to be added"
+ return False
+
+
+def check_user_role_value(file_content, db_content):
+ for db_user_role in db_content:
+ if file_content[0] == db_user_role["user_name"] and file_content[1] == db_user_role["role_name"]:
+ print "User_role " + file_content[0] + ":" + file_content[1] + " is ok"
+ return True
+ print "User_role " + file_content[0] + ":" + file_content[1] + " needs to be added"
+ return False
+
+
+def check_role_value(file_content, db_content):
+ for db_role in db_content:
+ if file_content[0] == db_role["name"]:
+ if file_content[1] != db_role["desc"]:
+ print "Role " + file_content[0] + " needs update due to changed description"
+ return "update"
+ if file_content[2] != str(db_role["is_chroot"]):
+ print "Role " + file_content[0] + " needs update due to changed is_chroot"
+ return "update"
+ return "ok"
+ return "add"
+
+
+def update_tables(db, update_needed):
+ try:
+ for row in update_needed["roles"]:
+ db.set_role_param(row[0],row[1],row[2])
+ print "Role {} updated".format(row[0])
+ for row in update_needed["permissions"]:
+ db.update_resource(row[0],row[1],row[2])
+ print "Permission {0}:{1} updated".format(row[0], row[1])
+ except Exception as ex:
+ print ex
+ return False
+ return True
+
+
+def add_into_tables(db, adding_needed, config):
+ try:
+ keystone = make_keystone_auth(config)
+ for row in adding_needed["users"]:
+ uuid = get_resource_id(keystone, "users", row[0])
+ create_db_user(db, uuid, row[0])
+ for row in adding_needed["roles"]:
+ try:
+ role_id = keystone.roles.create(row[0])
+ print "Role {} created in Keystone".format(row[0])
+ except Conflict as ex:
+ print "Role {} already in Keystone".format(row[0])
+ db.create_role(row[0],row[1],row[2])
+ print "Role {} created in DB".format(row[0])
+ for row in adding_needed["permissions"]:
+ db.create_resource(row[0],row[1],row[2])
+ print "Permission {} created in DB".format(row[0])
+ for row in adding_needed["user_roles"]:
+ try:
+ project_id = get_resource_id(keystone, "projects", "{{ am_project_name }}")
+ role_id = get_resource_id(keystone, "roles", row[1])
+ uuid = db.get_user_uuid(row[0])
+ if row[1] == "infrastructure_admin":
+ admin_project_id = get_resource_id(keystone, "projects", "admin")
+ admin_role_id = get_resource_id(keystone, "roles", "admin")
+ heat_role_id = get_resource_id(keystone, "roles", "heat_stack_owner")
+ keystone.roles.grant(admin_role_id, user=uuid, project=admin_project_id)
+ keystone.roles.grant(heat_role_id, user=uuid, project=admin_project_id)
+ keystone.roles.grant(role_id, user=uuid, project=project_id)
+ print "Role {} added to user {} in Keystone".format(row[1], row[0])
+ except Conflict as ex:
+ print "Role {} already at user {} in Keystone".format(row[1], row[0])
+ db.add_user_role(uuid, row[1])
+ print "Role {0} added to user {1} in DB".format(row[1], row[0])
+ for row in adding_needed["role_permissions"]:
+ db.add_resource_to_role(row[0], row[1], row[2])
+ print "Permission {0}:{1} added to role {2} in DB".format(row[1], row[2], row[0])
+ except Exception as ex:
+ print ex
+ print type(ex)
+ return False
+ return True
+
+
+def create_db_user(db, uuid, name):
+ if name == "{{ infrastructure_admin_user_name }}" or name == "admin":
+ db.create_user(uuid, name)
+ else:
+ db.create_user(uuid, name, service=True)
+ print "User {} created in DB".format(name)
+
+
+def get_resource_id(keystone, resource_type, resource_name):
+ res_type = getattr(keystone,resource_type)
+ resource = utils.find_resource(res_type, resource_name)
+ return resource.id
+
+
+def make_keystone_auth(config):
+ auth = v3.Password(
+ auth_url="{{ keystone_service_internalurl }}",
+ username="{{ keystone_admin_user_name }}",
+ password="{{ keystone_auth_admin_password }}",
+ project_name="{{ keystone_admin_tenant_name }}",
+ project_domain_id="{{ am_project_domain }}",
+ user_domain_id="{{ am_project_domain }}")
+ sess = session.Session(auth=auth)
+ keystone = client.Client(session=sess)
+ print "+++ Keystone authentication OK"
+ return keystone
+
+
+def main():
+ config = get_config()
+ logger = set_logger()
+ logger.info("logger set")
+ db = AMDatabase(db_name=config["DB"]["name"], db_addr=config["DB"]["addr"],
+ db_port=int(config["DB"]["port"]), db_user=config["DB"]["user"],
+ db_pwd=config["DB"]["pwd"], logger=logger, management_mode=True)
+ db.connect()
+ thime = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
+ print "*** Start time " + thime + " ***"
+ print "+++ Connection to database successful"
+ db_content = get_db_content(db)
+ print "+++ DB dump acquired"
+ files_content = read_files()
+ print "+++ Value files read"
+ update_needed, adding_needed = compare_contents(db_content, files_content)
+ print "+++ Comparation done"
+ result = update_tables(db, update_needed)
+ if result:
+ print "+++ Updating tables completed"
+ else:
+ print "--- Problem during updating tables"
+ result = add_into_tables(db, adding_needed, config)
+ if result:
+ print "+++ Adding to tables completed"
+ else:
+ print "--- Problem during table additions"
+ db.close()
+ print "+++ Aaand done"
+ thime = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime())
+ print "*** End time " + thime + " ***"
+ close_logger_handlers(logger)
+
+
+if __name__ == '__main__':
+ main()