Search code examples
apache.htaccessenvironmentrequest-uri

.htaccess migrator from apache 2.2 to apache 2.4


Im trying to migrate my .htaccess file from apache 2.2 to apache 2.4, but i'm having a hard time recreating these deny/allow rules.

#deny access to all files inside folders
SetEnvIf Request_URI "^/.+\.[a-z]+$" deny

SetEnvIf Request_URI "(\.gitignore|\.htaccess)" deny

# set acces to public accessible files in main admin folder
SetEnvIf Request_URI "^/admin/(index\.php|tmp)" allow

# set acces to public accessible files in module folders Admin and Site
SetEnvIf Request_URI "^/modules/[^/]+/(site/([^/]+/)?|admin/)(css|js|plugins|images|files|cache|fonts)/" allow

# set acces to public accessible files in uploads folder
SetEnvIf Request_URI "^/uploads" allow

SetEnvIf Request_URI "^/(.*\.xml|.*\.pdf|.*\.js|.*\.htm|.*\.asp|.*\.html|favicon\.ico|robots\.txt|index\.php|communicationlog\.png|sitemap-?([a-z]+)?\.xml\.?(gz)?$)" allow

Order deny,allow
Deny from env=deny
Allow from env=allow

These are the rules im currently struggling with. It seems very hard to recreate these with the <Require>, <RequireAll> and <RequireAny> directives. Can anyone help us out?

I tried just adding these rule with a <RequireAll> and <RequireAny> directives, but these basically deny the entire site and does not reproduce the same results.


Solution

  • Instead of having two variables deny and allow, I would have just one "allow" var, which is then unset (ie. !allow) as required, instead of setting deny. This "allow" variable should be set by default (inline with the Order deny,allow directive that defaults to allow if neither is set).

    By having just one variable allows you to grant access with a single Require directive.

    I would also call this variable something other than allow, to avoid any confusion with the allow directive. For the sake of this example I will call it ALLOW_ACCESS (convention dictates all uppercase).

    So, the rules would then become (SetEnvIf directives are pretty much the same, except for the additional "initialisation" one and use of env var):

    # Default is to allow access
    SetEnvIf ^ ^ ALLOW_ACCESS
    
    #deny access to all files inside folders
    SetEnvIf Request_URI "^/.+\.[a-z]+$" !ALLOW_ACCESS
    
    SetEnvIf Request_URI "(\.gitignore|\.htaccess)" !ALLOW_ACCESS
    
    # set acces to public accessible files in main admin folder
    SetEnvIf Request_URI "^/admin/(index\.php|tmp)" ALLOW_ACCESS
    
    # set acces to public accessible files in module folders Admin and Site
    SetEnvIf Request_URI "^/modules/[^/]+/(site/([^/]+/)?|admin/)(css|js|plugins|images|files|cache|fonts)/" ALLOW_ACCESS
    
    # set acces to public accessible files in uploads folder
    SetEnvIf Request_URI "^/uploads" ALLOW_ACCESS
    
    SetEnvIf Request_URI "^/(.*\.xml|.*\.pdf|.*\.js|.*\.htm|.*\.asp|.*\.html|favicon\.ico|robots\.txt|index\.php|communicationlog\.png|sitemap-?([a-z]+)?\.xml\.?(gz)?$)" ALLOW_ACCESS
    
    Require env ALLOW_ACCESS
    

    Note that since there is now just one "variable" to grant access, the order of the directives is now significant. Although they already happened to be in the correct order.

    If you have any other (deprecated) Order, Allow and Deny directives then they also need to be converted at the same time, to avoid any unexpected conflicts.


    Aside:

    #deny access to all files inside folders
    SetEnvIf Request_URI "^/.+\.[a-z]+$" !ALLOW_ACCESS
    
    SetEnvIf Request_URI "(\.gitignore|\.htaccess)" !ALLOW_ACCESS
    

    It looks like these two directives could be combined:

    SetEnvIf Request_URI "\.[a-z]+$" !ALLOW_ACCESS
    

    Which effectively blocks all dot-files (not just .gitignore and .htaccess), but that is usually desirable.