Coverage for /Users/davegaeddert/Development/dropseed/plain/plain/plain/preflight/security/base.py: 54%

41 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-10-16 22:04 -0500

1from plain.exceptions import ImproperlyConfigured 

2from plain.runtime import settings 

3 

4from .. import Warning, register 

5 

6SECRET_KEY_INSECURE_PREFIX = "plain-insecure-" 

7SECRET_KEY_MIN_LENGTH = 50 

8SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5 

9 

10SECRET_KEY_WARNING_MSG = ( 

11 f"Your %s has less than {SECRET_KEY_MIN_LENGTH} characters, less than " 

12 f"{SECRET_KEY_MIN_UNIQUE_CHARACTERS} unique characters, or it's prefixed " 

13 f"with '{SECRET_KEY_INSECURE_PREFIX}' indicating that it was generated " 

14 f"automatically by Plain. Please generate a long and random value, " 

15 f"otherwise many of Plain's security-critical features will be " 

16 f"vulnerable to attack." 

17) 

18 

19# TODO 

20W001 = Warning( 

21 "You do not have 'plain.middleware.https.HttpsRedirectMiddleware' " 

22 "in your MIDDLEWARE so the SECURE_HSTS_SECONDS, " 

23 "SECURE_CONTENT_TYPE_NOSNIFF, SECURE_REFERRER_POLICY, " 

24 "SECURE_CROSS_ORIGIN_OPENER_POLICY, and HTTPS_REDIRECT_ENABLED settings will " 

25 "have no effect.", 

26 id="security.W001", 

27) 

28 

29W008 = Warning( 

30 "Your HTTPS_REDIRECT_ENABLED setting is not set to True. " 

31 "Unless your site should be available over both SSL and non-SSL " 

32 "connections, you may want to either set this setting True " 

33 "or configure a load balancer or reverse-proxy server " 

34 "to redirect all connections to HTTPS.", 

35 id="security.W008", 

36) 

37 

38W009 = Warning( 

39 SECRET_KEY_WARNING_MSG % "SECRET_KEY", 

40 id="security.W009", 

41) 

42 

43W018 = Warning( 

44 "You should not have DEBUG set to True in deployment.", 

45 id="security.W018", 

46) 

47 

48W020 = Warning( 

49 "ALLOWED_HOSTS must not be empty in deployment.", 

50 id="security.W020", 

51) 

52 

53W025 = Warning(SECRET_KEY_WARNING_MSG, id="security.W025") 

54 

55 

56def _check_secret_key(secret_key): 

57 return ( 

58 len(set(secret_key)) >= SECRET_KEY_MIN_UNIQUE_CHARACTERS 

59 and len(secret_key) >= SECRET_KEY_MIN_LENGTH 

60 and not secret_key.startswith(SECRET_KEY_INSECURE_PREFIX) 

61 ) 

62 

63 

64@register(deploy=True) 

65def check_secret_key(package_configs, **kwargs): 

66 try: 

67 secret_key = settings.SECRET_KEY 

68 except (ImproperlyConfigured, AttributeError): 

69 passed_check = False 

70 else: 

71 passed_check = _check_secret_key(secret_key) 

72 return [] if passed_check else [W009] 

73 

74 

75@register(deploy=True) 

76def check_secret_key_fallbacks(package_configs, **kwargs): 

77 warnings = [] 

78 try: 

79 fallbacks = settings.SECRET_KEY_FALLBACKS 

80 except (ImproperlyConfigured, AttributeError): 

81 warnings.append(Warning(W025.msg % "SECRET_KEY_FALLBACKS", id=W025.id)) 

82 else: 

83 for index, key in enumerate(fallbacks): 

84 if not _check_secret_key(key): 

85 warnings.append( 

86 Warning(W025.msg % f"SECRET_KEY_FALLBACKS[{index}]", id=W025.id) 

87 ) 

88 return warnings 

89 

90 

91@register(deploy=True) 

92def check_debug(package_configs, **kwargs): 

93 passed_check = not settings.DEBUG 

94 return [] if passed_check else [W018] 

95 

96 

97@register(deploy=True) 

98def check_allowed_hosts(package_configs, **kwargs): 

99 return [] if settings.ALLOWED_HOSTS else [W020]