import argparse import random import string import boto3 from botocore.exceptions import ClientError import pymysql import snowflake.connector from snowflake.connector.errors import DatabaseError import config def generate_random_password(): """Generate a complex random password.""" password = "" while len(password) < config.PASSWORD_MIN_LENGTH: upper = random.choice(string.ascii_uppercase) lower = random.choice(string.ascii_lowercase) num = random.choice(string.digits) symbol = random.choice("#$%^()") chars = upper + lower + num + symbol password += "".join(random.sample(chars, len(chars))) return password def create_aws_iam_user(user, env, account_id): """Create AWS IAM user. Args: user (str): username env (str): environment account_id (str): aws account id number """ session = boto3.session.Session(profile_name=env) password = generate_random_password() aws_url = "https://{}.signin.aws.amazon.com/console".format(account_id) try: iam = session.client("iam") user = iam.create_user(UserName=user) iam.create_login_profile( UserName=user["User"]["UserName"], Password=password, PasswordResetRequired=False, ) except ClientError as error: if error.response["Error"]["Code"] == "EntityAlreadyExists": print("User already exists...") else: print("Unexpected error: {}".format(error)) default_iam_group = "generic-orchard-{}-group".format(env) iam.add_user_to_group( GroupName=default_iam_group, UserName=user["User"]["UserName"] ) keypair = iam.create_access_key(UserName=user["User"]["UserName"]) print( "url: {}\n" "login: {}\n" "password: {}\n" "access key: {}\n" "secret access key: {}\n".format( aws_url, user["User"]["UserName"], password, keypair["AccessKey"]["AccessKeyId"], keypair["AccessKey"]["SecretAccessKey"], ) ) def create_mysql_user(user, env, host): """Create MySQL user. Args: user (str): username env (str): environment host (str): hostname of database server """ password = generate_random_password() connection = pymysql.connect( host=host, read_default_group="mysql{}".format(host), read_default_file=config.DOT_MYCNF_FILE_PATH + ".my.cnf", ) with connection: with connection.cursor() as cursor: try: if env == "dev": create_user_sql = "CREATE USER '{}'@'%' IDENTIFIED BY '{}';".format( user, password ) cursor.execute(create_user_sql) add_grants_sql = ( "GRANT ALTER, ALTER ROUTINE, CREATE, CREATE ROUTINE, CREATE " "TEMPORARY TABLES, CREATE VIEW, DELETE, DROP, EXECUTE, FILE, INDEX, " "INSERT, LOCK TABLES, PROCESS, REFERENCES, SELECT, SHOW DATABASES, " "SHOW VIEW, TRIGGER, UPDATE ON *.* TO '{}'@'%';".format(user) ) cursor.execute(add_grants_sql) else: create_user_sql = "CREATE USER '{}'@'%' IDENTIFIED BY '{}';".format( user, password ) cursor.execute(create_user_sql) add_grants_sql = ( "GRANT SELECT, SHOW VIEW ON *.* TO '{}'@'%';".format(user) ) cursor.execute(add_grants_sql) print( "host: {}\n" "login: {}\n" "password: {}\n".format(host, user, password) ) except pymysql.err.OperationalError as error: print("User already exists: {}".format(error)) def create_snowflake_user(user, account): """Create Snowflake user. Args: user (str): username account (str): snowflake account name """ password = generate_random_password() connection = snowflake.connector.connect( account=account, user=config.SNOWFLAKE_USER, password=config.SNOWFLAKE_PASSWORD, role=config.SNOWFLAKE_ROLE, ) with connection: with connection.cursor() as cursor: try: create_user_sql = "CREATE USER {} display_name={} password='{}' default_warehouse = {} default_role = {} must_change_password = true;".format( str.upper(user), str.upper(user), password, config.USER_SNOWFLAKE_WAREHOUSE, config.USER_SNOWFLAKE_ROLE, ) cursor.execute(create_user_sql) grant_role_sql = "GRANT ROLE {} TO USER {};".format( config.USER_SNOWFLAKE_ROLE, user ) cursor.execute(grant_role_sql) print( "url: {}\n" "login: {}\n" "password: {}\n".format( account + ".snowflakecomputing.com", user, password ) ) except DatabaseError as error: print(error) def main(): parser = argparse.ArgumentParser() parser.add_argument("-u", "--user", required=True, help="Name of user to create.") parser.add_argument( "-a", "--dev-iam-user", action="store_true", required=False, help="Create an AWS Dev account user with " "default power user access.", ) parser.add_argument( "-b", "--prod-iam-user", action="store_true", required=False, help="Create an AWS Prod account user with " "default limited access.", ) parser.add_argument( "-c", "--reports-ar", action="store_true", required=False, help="Create a Prod art_relations database account.", ) parser.add_argument( "-d", "--reports-dd", action="store_true", required=False, help="Create a Prod direct_delivery database account.", ) parser.add_argument( "-e", "--qa-ar-db", action="store_true", required=False, help="Create a QA art_relations database account.", ) parser.add_argument( "-f", "--qa-dd-db", action="store_true", required=False, help="Create a QA direct_delivery database account.", ) parser.add_argument( "-g", "--dev-ar-db", action="store_true", required=False, help="Create a Dev art_relations database account.", ) parser.add_argument( "-s", "--snowflake", action="store_true", required=False, help="Create a Snowflake database account.", ) args = parser.parse_args() if args.dev_iam_user is True: create_aws_iam_user(args.user, "dev", config.DEV_AWS_ACCOUNT_ID) if args.prod_iam_user is True: create_aws_iam_user(args.user, "prod", config.PROD_AWS_ACCOUNT_ID) if args.reports_ar is True: create_mysql_user(args.user, "prod", config.REPORTSAR_HOST) create_mysql_user(args.user, "prod", config.REPORTSAR02_HOST) if args.reports_dd is True: create_mysql_user(args.user, "prod", config.REPORTSDD_HOST) create_mysql_user(args.user, "prod", config.REPORTSAR02_HOST) if args.qa_ar_db is True: create_mysql_user(args.user, "qa", config.QA_AR_DB_HOST) if args.qa_dd_db is True: create_mysql_user(args.user, "qa", config.QA_DD_DB_HOST) if args.dev_ar_db is True: create_mysql_user(args.user, "dev", config.DEV_AR_DB_HOST) if args.snowflake is True: create_snowflake_user(args.user, config.SNOWFLAKE_ACCOUNT) if __name__ == "__main__": main()