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

1 from plain.exceptions import ImproperlyConfigured

2 from plain.runtime import settings

3

4 from .. import Warning, register

5

6 SECRET_KEY_INSECURE_PREFIX = "plain-insecure-"

7 SECRET_KEY_MIN_LENGTH = 50

8 SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5

9

10 SECRET_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

20 W001 = 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

29 W008 = 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

38 W009 = Warning(

39 SECRET_KEY_WARNING_MSG % "SECRET_KEY",

40 id="security.W009",

41)

42

43 W018 = Warning(

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

45 id="security.W018",

46)

47

48 W020 = Warning(

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

50 id="security.W020",

51)

52

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

54

55

56 def _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)

65 def 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)

76 def 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)

92 def check_debug(package_configs, **kwargs):

93 passed_check = not settings.DEBUG

94 return [] if passed_check else [W018]

95

96

97@register(deploy=True)

98 def check_allowed_hosts(package_configs, **kwargs):

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