s3.py 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. from flask import request, redirect, abort, jsonify, url_for
  2. from CTFd.models import db, Solves, Challenges, WrongKeys, Keys, Tags, Files
  3. from CTFd import utils
  4. import os
  5. import boto3
  6. import hashlib
  7. import string
  8. from werkzeug.utils import secure_filename
  9. def clean_filename(c):
  10. if c in string.ascii_letters + string.digits + '-' + '_' + '.':
  11. return True
  12. def get_s3_conn(app):
  13. access_key_id = utils.get_app_config('ACCESS_KEY_ID')
  14. secret_access_key = utils.get_app_config('SECRET_ACCESS_KEY')
  15. if access_key_id and secret_access_key:
  16. client = boto3.client(
  17. 's3',
  18. aws_access_key_id=access_key_id,
  19. aws_secret_access_key=secret_access_key
  20. )
  21. bucket = utils.get_app_config('BUCKET')
  22. return client, bucket
  23. else:
  24. client = boto3.client('s3')
  25. bucket = utils.get_app_config('BUCKET')
  26. return client, bucket
  27. def load(app):
  28. def upload_file(file, chalid):
  29. s3, bucket = get_s3_conn(app)
  30. filename = filter(clean_filename, secure_filename(file.filename).replace(' ', '_'))
  31. if len(filename) <= 0:
  32. return False
  33. md5hash = hashlib.md5(os.urandom(64)).hexdigest()
  34. key = md5hash + '/' + filename
  35. s3.upload_fileobj(file, bucket, key)
  36. db_f = Files(chalid, key)
  37. db.session.add(db_f)
  38. db.session.commit()
  39. return db_f.id, (md5hash + '/' + filename)
  40. def delete_file(filename):
  41. s3, bucket = get_s3_conn(app)
  42. f = Files.query.filter_by(id=filename).first_or_404()
  43. key = f.location
  44. s3.delete_object(Bucket=bucket, Key=key)
  45. db.session.delete(f)
  46. db.session.commit()
  47. return True
  48. def file_handler(path):
  49. f = Files.query.filter_by(location=path).first_or_404()
  50. chal = Challenges.query.filter_by(id=f.chal).first()
  51. s3, bucket = get_s3_conn(app)
  52. if utils.is_admin() or chal is None:
  53. key = f.location
  54. url = s3.generate_presigned_url('get_object', Params = {
  55. 'Bucket': bucket,
  56. 'Key': key, })
  57. return redirect(url)
  58. if utils.user_can_view_challenges():
  59. if not utils.ctftime():
  60. if not utils.view_after_ctf():
  61. abort(403)
  62. if chal.hidden:
  63. abort(403)
  64. key = f.location
  65. url = s3.generate_presigned_url('get_object', Params = {
  66. 'Bucket': bucket,
  67. 'Key': key, })
  68. return redirect(url)
  69. else:
  70. return redirect(url_for('auth.login'))
  71. utils.upload_file = upload_file
  72. utils.delete_file = delete_file
  73. app.view_functions['views.file_handler'] = file_handler