Separate admin/editing from viewing or limit admin/editing by IP address

Permalink 1 user found helpful
I realize that Concrete5 is an integrated CMS out of the box but I committed to asking the community these two questions on the off chance someone has an idea or perhaps has experimented along these lines. :-D

1. We have a client that we were planning to use Concrete5 for that is asking about separating the viewing of a site from the administration/editing of the same site via a DMZ-like scenario. Is this even remotely possible to do with C5, by custom means or other?

2. Has anyone experimented with or successfully implemented custom login functionality that prevents access to admin/editing accounts by ip address? This would restrict access to the admin/editing functionality of a site to a particular location, i.e. the clients office.

Thanks in advance for any insite! I'd even be happy with 'not possible with C5' answers. Just looking for something to take back to our client.

- Dean

dwhillier
View Replies:
JohntheFish replied on at Permalink Reply
JohntheFish
If there are no C5 solutions, you should be able to do the admin part of this with .htaccess rules, restricting /dashboard paths to particular ip addresses.

It may not be clean, but you could certainly prevent editing from working by blocking critical .js files for ip addresses that were not on your editor ip list. Not a nice solution, but it would provide an extra layer of security.

This isn't something I have done, but its a classic example given in tutorials on mod_rewrite.
frz replied on at Permalink Reply
frz
for larger clients we've done things like limit editing to a specific server when there's load balancing going on.

You could build hooks into the login page to limit it to only accept logins from some IP's..

generally I'd ask if this was really that critical of a issue however. Points to some underlying concerns that may be valid but should probably just be addressed and corrected rather than catered to. I mean it IS in-line editing on a live site.
mkly replied on at Permalink Reply
mkly
#2. If you go to /concrete/controllers/login.php you will see the do_login method which is where I would put my code. Well, you would override login.php in /controllers/login.php and edit that, but anyway...

On line 161 of login.php you have
$u = new User($this->post('uName'), $this->post('uPassword'));

This gets us a user object. We can check this to determine if the user is a super user with
$u->isSuperUser()

or we can get a group and check if the user is in that group(or both)
$group = Group::getByName('Administrators of something');
$u->inGroup($group)

So we could combine that for
// check if login successful
if(!$u->isError()) {
  $remote_ip = $_SERVER['REMOTE_ADDR'];
  // check if they are not at admin ip
  if($remote_ip != ADMIN_ONLY_IP) {
    $group = Group::getByName('Administrators Group Name');
    // check if they're admin
    if($u->isSuperUser() || $u->inGroup($group)) {
      // oh uh!
      // let's log it so we can hunt them down
      $l = new Log('admin_access_attempt', true);
      $l->write('Admin login attempted from ' . $remote_ip);
      $l->close();
      throw new Exception(t('Unauthorized IP'));
    }

Then in /config/site.php
define('ADMIN_ONLY_IP', '240.1.1.1');


You'll probably want to modify that for your LAN subnet as opposed to one address, but you get the point. As for #1, if you are looking at it from a security standpoint admin of anything logins should only be from the lan subnet via local machines or VPN anyway.

Hope that helps a little.

EDIT: I should add as you are probably thinking, someone with a login cookie would be able to access the site from outside ips. There are some ways to deal with this as well, but not sure if this is enough or not.
RMDWebDesign replied on at Permalink Reply
RMDWebDesign
Hey folks,

The way to implement this has changed since v 5.6. You now need to extend the login function via an controller override. I'm not really a programmer so feel free to correct me if I'm wrong :)

I've used mkly's code from above.

Add this to [root]/controllers/login.php

<?php 
defined('C5_EXECUTE') or die("Access Denied.");
class LoginController extends Concrete5_Controller_Login { 
public function do_login() { 
      $ip = Loader::helper('validation/ip');
      $vs = Loader::helper('validation/strings');
      $loginData['success']=0;
      try {
         if (!$ip->check()) {            
            throw new Exception($ip->getErrorMessage());
         }
         if (OpenIDAuth::isEnabled() && $vs->notempty($this->post('uOpenID'))) {
            $oa = new OpenIDAuth();
            $oa->setReturnURL($this->openIDReturnTo);
            $return = $oa->request($this->post('uOpenID'));


Then add mkly's other bit of code to config/site.php

define('ADMIN_ONLY_IP', '240.1.1.1');




Hope this helps :)
RMDWebDesign replied on at Permalink Reply
RMDWebDesign
Here is the same script, but slightly modified for one of my clients.

This checks the users IP falls within the first 2 octets of one of two possible whitelisted class B domains. It also checks the IP against a blacklisted IP (all 4 octets). Thanks to mkly for the original code ;)


[root]/controllers/login.php:

<?php 
defined('C5_EXECUTE') or die("Access Denied.");
class LoginController extends Concrete5_Controller_Login { 
public function do_login() { 
      $ip = Loader::helper('validation/ip');
      $vs = Loader::helper('validation/strings');
      $loginData['success']=0;
      try {
         if (!$ip->check()) {            
            throw new Exception($ip->getErrorMessage());
         }
         if (OpenIDAuth::isEnabled() && $vs->notempty($this->post('uOpenID'))) {
            $oa = new OpenIDAuth();
            $oa->setReturnURL($this->openIDReturnTo);
            $return = $oa->request($this->post('uOpenID'));



And add this to your site.php:
define('ADMIN_ALLOW_IP1', '#.#.0.0'); //replace # with your Class B IP
define('ADMIN_ALLOW_IP2', '#.#.0.0');
define('ADMIN_DENY_IP1', '#.#.#.#');



It should be easy enough to modify to allow other IP classes. Hope this comes in handy for someone :)
wanderlust replied on at Permalink Reply
wanderlust
I might not be on the right message thread, but maybe someone could help me. Have a client whom we've created a group for their board members only. The navigation comes up only if you are logged in. I've restricted editing pages of the site to this group. However the client wants this group to be able to log out for security reasons. The only way I can get the sign-out to show up on these pages of the site is to check "Editing permissions" on those pages. Client only wants "sign-out" on the dashboard - no editing functions.
Can anyone help?

Thanks for taking a look at this.
wanderlust replied on at Permalink Reply
wanderlust
I might not be on the right message thread, but maybe someone could help me. Have a client whom we've created a group for their board members only. The navigation comes up only if you are logged in. I've restricted editing pages of the site to this group. However the client wants this group to be able to log out for security reasons. The only way I can get the sign-out to show up on these pages of the site is to check "Editing permissions" on those pages. Client only wants "sign-out" on the dashboard - no editing functions.
Can anyone help?

Thanks for taking a look at this.
RMDWebDesign replied on at Permalink Reply
RMDWebDesign
Hi Wanderlust,

Sorry for the late reply, just seen your message!

You should really start a new thread for this!

What I would do in your situation is create a logout link on the page that is only viewable to logged in users:

$u = new User();
if($u->inGroup(Group::getByName('Administrators'))){
  echo '<a href="http://www.YOURSITE.com/login/logout">Logout</a>';
}


Hope this helps :)