config.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. package security
  2. import (
  3. "errors"
  4. "fmt"
  5. "regexp"
  6. "github.com/imgproxy/imgproxy/v3/ensure"
  7. "github.com/imgproxy/imgproxy/v3/env"
  8. )
  9. var (
  10. IMGPROXY_ALLOW_SECURITY_OPTIONS = env.Describe("IMGPROXY_ALLOW_SECURITY_OPTIONS", "boolean")
  11. IMGPROXY_ALLOWED_SOURCES = env.Describe("IMGPROXY_ALLOWED_SOURCES", "comma-separated lists of regexes")
  12. IMGPROXY_KEYS = env.Describe("IMGPROXY_KEYS", "comma-separated list of hex strings")
  13. IMGPROXY_SALTS = env.Describe("IMGPROXY_SALTS", "comma-separated list of hex strings")
  14. IMGPROXY_SIGNATURE_SIZE = env.Describe("IMGPROXY_SIGNATURE_SIZE", "number between 1 and 32")
  15. IMGPROXY_TRUSTED_SIGNATURES = env.Describe("IMGPROXY_TRUSTED_SIGNATURES", "comma-separated list of strings")
  16. IMGPROXY_MAX_SRC_RESOLUTION = env.Describe("IMGPROXY_MAX_SRC_RESOLUTION", "number > 0")
  17. IMGPROXY_MAX_SRC_FILE_SIZE = env.Describe("IMGPROXY_MAX_SRC_FILE_SIZE", "number >= 0")
  18. IMGPROXY_MAX_ANIMATION_FRAMES = env.Describe("IMGPROXY_MAX_ANIMATION_FRAMES", "number > 0")
  19. IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION = env.Describe("IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION", "number > 0")
  20. IMGPROXY_MAX_RESULT_DIMENSION = env.Describe("IMGPROXY_MAX_RESULT_DIMENSION", "number > 0")
  21. )
  22. // Config is the package-local configuration
  23. type Config struct {
  24. AllowSecurityOptions bool // Whether to allow security-related processing options in URLs
  25. AllowedSources []*regexp.Regexp // List of allowed source URL patterns (empty = allow all)
  26. Keys [][]byte // List of the HMAC keys
  27. Salts [][]byte // List of the HMAC salts
  28. SignatureSize int // Size of the HMAC signature in bytes
  29. TrustedSignatures []string // List of trusted signature sources
  30. DefaultOptions Options // Default security options
  31. }
  32. // NewDefaultConfig returns a new Config instance with default values.
  33. func NewDefaultConfig() Config {
  34. return Config{
  35. DefaultOptions: Options{
  36. MaxSrcResolution: 50_000_000,
  37. MaxSrcFileSize: 0,
  38. MaxAnimationFrames: 1,
  39. MaxAnimationFrameResolution: 0,
  40. MaxResultDimension: 0,
  41. },
  42. AllowSecurityOptions: false,
  43. SignatureSize: 32,
  44. }
  45. }
  46. // LoadConfigFromEnv overrides configuration variables from environment
  47. func LoadConfigFromEnv(c *Config) (*Config, error) {
  48. c = ensure.Ensure(c, NewDefaultConfig)
  49. err := errors.Join(
  50. env.Bool(&c.AllowSecurityOptions, IMGPROXY_ALLOW_SECURITY_OPTIONS),
  51. env.Patterns(&c.AllowedSources, IMGPROXY_ALLOWED_SOURCES),
  52. env.Int(&c.SignatureSize, IMGPROXY_SIGNATURE_SIZE),
  53. env.StringSlice(&c.TrustedSignatures, IMGPROXY_TRUSTED_SIGNATURES),
  54. env.MegaInt(&c.DefaultOptions.MaxSrcResolution, IMGPROXY_MAX_SRC_RESOLUTION),
  55. env.Int(&c.DefaultOptions.MaxSrcFileSize, IMGPROXY_MAX_SRC_FILE_SIZE),
  56. env.Int(&c.DefaultOptions.MaxAnimationFrames, IMGPROXY_MAX_ANIMATION_FRAMES),
  57. env.MegaInt(&c.DefaultOptions.MaxAnimationFrameResolution, IMGPROXY_MAX_ANIMATION_FRAME_RESOLUTION),
  58. env.Int(&c.DefaultOptions.MaxResultDimension, IMGPROXY_MAX_RESULT_DIMENSION),
  59. env.HexSlice(&c.Keys, IMGPROXY_KEYS),
  60. env.HexSlice(&c.Salts, IMGPROXY_SALTS),
  61. )
  62. return c, err
  63. }
  64. // Validate validates the configuration
  65. func (c *Config) Validate() error {
  66. if c.DefaultOptions.MaxSrcResolution <= 0 {
  67. return IMGPROXY_MAX_SRC_RESOLUTION.ErrorZeroOrNegative()
  68. }
  69. if c.DefaultOptions.MaxSrcFileSize < 0 {
  70. return IMGPROXY_MAX_SRC_FILE_SIZE.ErrorNegative()
  71. }
  72. if c.DefaultOptions.MaxAnimationFrames <= 0 {
  73. return IMGPROXY_MAX_ANIMATION_FRAMES.ErrorZeroOrNegative()
  74. }
  75. if len(c.Keys) != len(c.Salts) {
  76. return fmt.Errorf("number of keys and number of salts should be equal. Keys: %d, salts: %d", len(c.Keys), len(c.Salts))
  77. }
  78. if len(c.Keys) == 0 {
  79. IMGPROXY_KEYS.Warn("No keys defined, signature checking is disabled")
  80. }
  81. if len(c.Salts) == 0 {
  82. IMGPROXY_SALTS.Warn("No salts defined, signature checking is disabled")
  83. }
  84. if c.SignatureSize < 1 || c.SignatureSize > 32 {
  85. return IMGPROXY_SIGNATURE_SIZE.Errorf("invalid size")
  86. }
  87. return nil
  88. }