Sunday, June 3, 2012

htaccess conditionals


I have setup htpasswd authentication on my live site and it works great, but I don't want to be asked for a password when I am working on the development environment.



In my httpd.conf file I have:




SetEnv APP_ENV "development"



In my .htaccess file I have:




AuthName "Restricted Area"
AuthType Basic
AuthUserFile /path/to/file/.htpasswd
AuthGroupFile /dev/null
require valid-user



I was wondering if there was anyway of putting a conditional around the htppasswd stuff so that when APP_ENV is development that I don't get prompted for a password.



Is this possible?


Source: Tips4all

5 comments:

  1. If you are able to, you should think about upgrading to Apache 2.4 (or the latest 2.3 beta build since 2.4 isn't quite released yet).

    One of the new features available are Authorization Containers - making it much simpler to define access requirements using the Require directive.

    You should end up with something like:

    AuthName "Restricted Area"
    AuthType Basic
    AuthUserFile /path/to/file/.htpasswd
    AuthGroupFile /path/to/file/groups

    SetEnv APP_ENV "development"

    <RequireAll>
    <RequireAny>
    <RequireAll>
    #main requirements
    Require group user
    #other conditions if needed for non-dev/non-local
    </RequireAll>

    <RequireAll>
    #allow direct if development
    Require env APP_ENV development
    </RequireAll>

    <RequireAll>
    <RequireAny>
    #allow loopback and local network
    Require ip 127.0.0.1
    Require ip 10.2
    </RequireAny>
    </RequireAll>
    <RequireAny>

    #other conditions if needed for everyone

    <RequireNone>
    #blacklist
    </RequireNone>
    </RequireAll>

    ReplyDelete
  2. Conditionals in Apache config work only once, when the configuration is [re]loaded.

    What I would do is create a second VirtualHost with the same root directory, and control access using Deny/Allow based on IP address there.

    ReplyDelete
  3. Add the following:

    Require valid-user
    Allow from <dev IP>
    Satisfy Any


    This will require that Require valid-user or Allow from <dev IP> applies.

    ReplyDelete
  4. One of the way of building if conditional blocks with env variables is using mod_macro module.
    I made an example previously here.

    In this particular case you would have on top of the VirtualHost file (before the VirtualHost definition):

    <Macro ConditionalBlockMacroSecurity_production>
    AuthName "Restricted Area"
    AuthType Basic
    AuthUserFile /path/to/file/.htpasswd
    AuthGroupFile /dev/null
    require valid-user
    </Macro>
    <Macro ConditionalBlockMacroSecurity_development >
    <IfModule mod_headers.c>
    Header set MyHeader "Hello this is DEVELOPMENT envirronment. It took %D microseconds for Apache to serve this request."
    </IfModule>
    </Macro>


    And inside the Virtualhost:

    Use ConditionalBlockMacroSecurity_${APP_ENV}


    where path to the htpassword file could also be set as a parameter of the macro.

    The downside of this solution is that you need to install mod_macro on the production server, it's not a commonly installed module and you will need some control of the production env to do that. On the other side, a simple solution is to have several version of your virtualhosts depending on the environment, and to add some comments on the Auth section. But if you are searching for a generic solution it certainly means it's a recurent problem and you want to avoid manual editing of files, in such cases mod_macro can become a very professional way of capitalizing your apache experiences, until your apache configurations becomes a single macro with parameters, calling a lot of other macros.

    ReplyDelete
  5. In your .htaccess file you can nest the blocks within the IfDefine directive, like:

    <IfDefine PROD>
    bla bla bla
    </IfDefine>


    Then make sure to pass -D PROD as argument when you start apache. This section would only run if PROD is defined. In Ubuntu you can do this by, for example, editing /etc/apache2/envvars and adding this line at the end:

    export APACHE_ARGUMENTS="-D PROD"


    You can "inverse" it by perhaps using something like <IfDefine !DEV> to only run when its not the development environment, and then pass -D DEV in that environment, and leave the production sites as is without having to edit envvars.

    Modify accordingly to suit your needs!

    ReplyDelete