Coverage for /Users/davegaeddert/Developer/dropseed/plain/plain/plain/preflight/security.py: 49%

1 from plain.exceptions import ImproperlyConfigured

2 from plain.runtime import settings

3

4 from .messages import Warning

5 from .registry import register

6

7 SECRET_KEY_INSECURE_PREFIX = "plain-insecure-"

8 SECRET_KEY_MIN_LENGTH = 50

9 SECRET_KEY_MIN_UNIQUE_CHARACTERS = 5

10

11 SECRET_KEY_WARNING_MSG = (

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

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

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

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

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

17 f"vulnerable to attack."

18)

19

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

21

22

23 def _check_secret_key(secret_key):

24 return (

25 len(set(secret_key)) >= SECRET_KEY_MIN_UNIQUE_CHARACTERS

26 and len(secret_key) >= SECRET_KEY_MIN_LENGTH

27 and not secret_key.startswith(SECRET_KEY_INSECURE_PREFIX)

28 )

29

30

31@register(deploy=True)

32 def check_secret_key(package_configs, **kwargs):

33 try:

34 secret_key = settings.SECRET_KEY

35 except (ImproperlyConfigured, AttributeError):

36 passed_check = False

37 else:

38 passed_check = _check_secret_key(secret_key)

39 return (

40 []

41 if passed_check

42 else [

43 Warning(

44 SECRET_KEY_WARNING_MSG % "SECRET_KEY",

45 id="security.W009",

46 )

47 ]

48 )

49

50

51@register(deploy=True)

52 def check_secret_key_fallbacks(package_configs, **kwargs):

53 warnings = []

54 try:

55 fallbacks = settings.SECRET_KEY_FALLBACKS

56 except (ImproperlyConfigured, AttributeError):

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

58 else:

59 for index, key in enumerate(fallbacks):

60 if not _check_secret_key(key):

61 warnings.append(

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

63 )

64 return warnings

65

66

67@register(deploy=True)

68 def check_debug(package_configs, **kwargs):

69 passed_check = not settings.DEBUG

70 return (

71 []

72 if passed_check

73 else [

74 Warning(

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

76 id="security.W018",

77 )

78 ]

79 )

80

81

82@register(deploy=True)

83 def check_allowed_hosts(package_configs, **kwargs):

84 return (

85 []

86 if settings.ALLOWED_HOSTS

87 else [

88 Warning(

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

90 id="security.W020",

91 )

92 ]

93 )