def create_master_secret(app, is_staging, created_app_name): """ Creates a master secret. :param app: app creating the secret :type app: str :param is_staging: whether app is a staging app :type is_staging: bool :param created_app_name: app to create master secret for :type created_app_name: str :return: tuple of two randomly generated 64-character secrets. """ if app != "buildserver" or is_staging: abort(403) # only buildserver running in prod can create new apps with connect_db() as db: out = db( "SELECT public_value, staging_value FROM secrets WHERE app=%s AND name='MASTER'", [created_app_name], ).fetchone() if out is not None: return list(out) out = new_secret(), new_secret() db( "INSERT INTO secrets (app, name, public_value, staging_value) VALUES (%s, %s, %s, %s)", [created_app_name, "MASTER", *out], ) return out
def create_master_secret(app, is_staging, created_app_name): if app != "buildserver" or is_staging: abort(403) # only buildserver running in prod can create new apps with connect_db() as db: out = db( "SELECT public_value, staging_value FROM secrets WHERE app=%s AND name='MASTER'", [created_app_name], ).fetchone() if out is not None: return list(out) out = new_secret(), new_secret() db( "INSERT INTO secrets (app, name, public_value, staging_value) VALUES (%s, %s, %s, %s)", [created_app_name, "MASTER", *out], ) return out
def submit(): caption = str(request.form["caption"]) if len(caption) > MAX_CAPTION_LEN: abort( 413, f"Your caption is too long - it should be at most {MAX_CAPTION_LEN} characters.", ) dice = loads(request.form["dice"]) dice_list = [] for svg in dice: if not isinstance(svg, str): abort(401) dice_list.append(svg) del dice if len(dice_list) != NUM_DICE: abort(401) group = get_group(get_endpoint("cs61a") + "/" + ASSIGNMENT) with connect_db() as db: for member in group: db("DELETE FROM designs WHERE email=(%s)", [member]) email = group[0] db( "INSERT INTO designs (id, created_time, email, caption, dice, endpoint) VALUES (%s, %s, %s, %s, %s, %s)", [ new_secret(), int(time()), email, caption, dumps(dice_list), get_endpoint("cs61a"), ], ) return dict(success=True, group=group)
def okpy_batch_grade_impl(): data = request.json subm_ids = data["subm_ids"] assignment = data["assignment"] access_token = data["access_token"] if assignment == "test": return "OK" assignment: Optional[Assignment] = Assignment.query.get(assignment) if not assignment or assignment.endpoint != get_endpoint( course=assignment.course ): abort(404, "Unknown Assignment") if len(subm_ids) / assignment.batch_size > 50: abort( 405, "Too many batches! Please set the batch_size so that there are <= 50 batches.", ) job_secrets = [new_secret() for _ in subm_ids] queue_time = int(time.time()) jobs = [ Job( assignment_secret=assignment.assignment_secret, backup=backup_id, status="queued", job_secret=job_secret, external_job_id=new_secret(), access_token=access_token, queued_at=queue_time, ) for backup_id, job_secret in zip(subm_ids, job_secrets) ] db.session.bulk_save_objects(jobs) db.session.commit() trigger_jobs( assignment_id=assignment.assignment_secret, jobs=job_secrets, noreply=True ) return dict(jobs=[job.external_job_id for job in jobs])
def gen_env_variables(app: App, pr_number: int): # set up and create database user database = app.name.replace("-", "_") with connect_db() as db: db_pw = db( "SELECT mysql_pw FROM mysql_users WHERE app=(%s)", [app.name] ).fetchone() if db_pw is None: db_pw = new_secret() # unable to use placeholders here, but it's safe because we control the app.name and db_pw db(f"CREATE DATABASE IF NOT EXISTS {database}") db(f'CREATE USER "{app.name}"@"%%" IDENTIFIED BY "{db_pw}";') db(f"GRANT ALL ON {database}.* TO '{app}'@'%%'") db("FLUSH TABLES mysql.user") db( "INSERT INTO mysql_users (app, mysql_pw) VALUES (%s, %s)", [app.name, db_pw], ) else: db_pw = db_pw[0] if app.config["deploy_type"] == "hosted": database_url = sqlalchemy.engine.url.URL( drivername="mysql", host=DB_IP_ADDRESS, username=app.name, password=db_pw, database=database, ).__to_string__(hide_password=False) elif app.config["deploy_type"] in CLOUD_RUN_DEPLOY_TYPES: database_url = sqlalchemy.engine.url.URL( drivername="mysql+pymysql", username=app.name, password=db_pw, database=database, query={"unix_socket": "{}/{}".format("/cloudsql", DB_INSTANCE_NAME)}, ).__to_string__(hide_password=False) else: database_url = None # set up the remaining secrets return dict( ENV="prod", DATABASE_URL=database_url, INSTANCE_CONNECTION_NAME=DB_INSTANCE_NAME, **( dict(APP_MASTER_SECRET=gen_master_secret(app, pr_number)) if "rpc" in app.config["permissions"] else {} ), **( load_all_secrets(created_app_name=app.name) if pr_number == 0 and "rpc" in app.config["permissions"] else {} ), )
def create_assignment_rpc(course, name, file, command, batch_size, grading_base): assignment: Assignment = Assignment.query.filter_by( name=name, course=course, endpoint=get_endpoint(course=course)).one_or_none() if not assignment: assignment = Assignment( name=name, assignment_secret=new_secret(), course=course, endpoint=get_endpoint(course=course), ) db.session.add(assignment) assignment.file = file assignment.command = command assignment.last_modified = int(time.time()) assignment.batch_size = batch_size assignment.grading_base = grading_base db.session.commit() return assignment.assignment_secret