#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: #php #cron #docker #alpine crond: can't set groups: Operation not permitted

Bounty: 50

This morning I upgraded my PHP version to 7.1 and am seeing an issue when cron tries to run php /var/www/html/artisan schedule:run (a simple PHP command) I see the output:

3/3/2017 10:39:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:39:00 AMcrond: USER www-data pid 1562 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:40:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:40:00 AMcrond: USER www-data pid 1563 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:41:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:41:00 AMcrond: USER www-data pid 1564 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:42:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:42:00 AMcrond: USER www-data pid 1565 cmd php /var/www/html/artisan schedule:run
3/3/2017 10:43:00 AMcrond: can't set groups: Operation not permitted
3/3/2017 10:43:00 AMcrond: USER www-data pid 1566 cmd php /var/www/html/artisan schedule:run

The command being run is a Laravel artisan command. It’s run every minute allowing other scheduled work to be completed within the application itself. There’s nothing in this command that writes to any files or anything like that. The scheduled work talks to a database and sends some email. Application logs are sent to stdout since it’s a Docker container.

cron is run in a container with the command crond -f -d 8. Here’s the Dockerfile:

# This container should be used for any/all CLI processes
# including cron, queues, etc.
FROM php:7.1-alpine

# Copy the application files to the container
ADD . /var/www/html

WORKDIR /var/www/html

# fix permissions in CI
RUN sed -ri 's/^www-data:x:82:82:/www-data:x:1000:1000:/' /etc/passwd 
    && sed -ri 's/^www-data:x:82:/www-data:x:1000:/' /etc/group

# Install Composer dependencies
RUN apk add --update --no-cache git zip unzip 

        # needed for spatie/laravel-backup
        mysql-client 

        # needed for gd
        libpng-dev libjpeg-turbo-dev 

    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN docker-php-ext-install pdo_mysql gd 

        # needed for forking processes in laravel queues as of Laravel 5.3
        pcntl

# Ownership of the app dir for www-data
RUN chown -R www-data:www-data /var/www/html /home/www-data/

# Put php artisan schedule:run in a crontab
RUN echo "*       *       *       *       *       php /var/www/html/artisan schedule:run" > /etc/crontabs/www-data

# Make sure when users get into the container they aren't root
USER www-data

I’ve ruled out that php artisan schedule:run is the cause since I can run it manually and everything’s fine. This means it’s something within cron.

What is cron doing under the covers that could cause this error?


Get this bounty!!!

#StackBounty: Laravel – Revised Authentication Controller

Bounty: 50

I’m developing a Social Engineering Awareness Training Application. This is the focus of my thesis for my undergraduate degree. This will be a multi-part review request, however, if you want to see the entire application, it can be found on GitHub. For this request, I’m looking to see how my revised AuthController (initial request) is set up and how effective you think it might be. I open to any and all suggestions about any facet of the code.

One question I still have, though, is there any benefit to having my application almost completely static?

Keep in mind that this application is nearly to testing, however, there are a few pieces that might not be polished.

AuthController

<?php

namespace AppHttpControllers;

use AppLibrariesCryptor;
use AppLibrariesErrorLogging;
use AppLibrariesRandomObjectGeneration;
use AppModelsSessions;
use AppModelsTwo_Factor;
use AppModelsUser;
use AppModelsUser_Permissions;
use IlluminateDatabaseQueryException;
use IlluminateHttpRequest;
use LeagueFlysystemException;

class AuthController extends Controller
{
/**
 * create
 * Create a new user instance after a valid registration.
 *
 * @param   Request         $request
 * @return  User
 */
public static function create(Request $request) {
    try {
        if($request->input('emailText') != $request->input('confirmEmailText')) {
            return redirect()->route('register');
        }

        $email = $request->input('emailText');
        $username = $request->input('usernameText');
        $password = RandomObjectGeneration::random_str(intval(getenv('DEFAULT_LENGTH_PASSWORDS')),true);

        $user = User::create([
            'username' => $username,
            'email' => $email,
            'first_name' => $request->input('firstNameText'),
            'last_name' => $request->input('lastNameText'),
            'middle_initial' => $request->input('middleInitialText'),
            'password' => password_hash($password,PASSWORD_DEFAULT),
            'two_factor_enabled' => 0,
        ]);

        EmailController::sendNewAccountEmail($user,$password);
        return redirect()->route('users');

    } catch(QueryException $qe) {
        if(strpos($qe->getMessage(),"1062 Duplicate entry 'admin'") !== false) {
            return redirect()->route('register'); //return with username exists error
        }
        return redirect()->route('register'); //return with unknown error

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * authenticate
 * Authenticates the user against the user's database object. Submits to 2FA if they have
 * the option enabled, otherwise logs the user in.
 *
 * @param   Request         $request
 * @return  IlluminateHttpRedirectResponse
 */
public static function authenticate(Request $request) {
    try {
        $user = User::where('username',$request->input('usernameText'))->first();
        $password = $request->input('passwordText');
        if(empty($user) || !password_verify($password,$user->password)) {
            return redirect()->route('login');
        }

        User::updateUser($user,$user->email,password_hash($password,PASSWORD_DEFAULT),$user->two_factor_enabled);

        $session = Sessions::where('user_id',$user->id)->first();
        if(!empty($session)) {
            $session->delete();
        }

        $ip = $_SERVER['REMOTE_ADDR'];
        $cryptor = new Cryptor();

        if($user->two_factor_enabled === 1) {
            $twoFactor = Two_Factor::where([
                'user_id' => $user->id, 'ip_address' => $ip
            ])->first();
            if(!empty($twoFactor)) {
                $twoFactor->delete();
            }

            $code = RandomObjectGeneration::random_str(6,false,'1234567890');
            $twoFactor = Two_Factor::create([
                'user_id' => $user->id,
                'ip_address' => $_SERVER['REMOTE_ADDR'],
                'code' => password_hash($code,PASSWORD_DEFAULT)
            ]);

            EmailController::sendTwoFactorEmail($user,$code);

            $newSession = Sessions::create([
                'user_id' => $user->id,
                'ip_address' => $ip,
                'two_factor_id' => $twoFactor->id,
                'authenticated' => 0
            ]);

            $encryptedSession = $cryptor->encrypt($newSession->id);
            Session::put('sessionId',$encryptedSession);

            return redirect()->route('2fa');
        }

        $newSession = Sessions::create([
            'user_id' => $user->id,
            'ip_address' => $ip,
            'authenticated' => 1
        ]);

        $encryptedSession = $cryptor->encrypt($newSession->id);
        Session::put('sessionId',$encryptedSession);

        $intended = Session::pull('intended');
        if($intended) {
            return redirect()->to($intended);
        }
        return redirect()->route('authHome');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * generateTwoFactorPage
 * Route for generating the 2FA page.
 *
 * @return IlluminateHttpRedirectResponse | IlluminateViewView
 */
public static function generateTwoFactorPage() {
    try {
        if(Session::has('sessionId')) {
            $cryptor = new Cryptor();

            $sessionId = $cryptor->decrypt(Session::get('sessionId'));
            $session = Sessions::where('id',$sessionId)->first();

            $sessionCheck = self::activeSessionCheck($session);
            if(!is_null($sessionCheck)) {
                return $sessionCheck;
            }

            if(!is_null($session->two_factor_id)) {
                return view('auth.2fa');
            }
        }
        return redirect()->route('login');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * twoFactorVerify
 * Validates the 2FA code to authenticate the user.
 *
 * @param   Request         $request
 * @return  IlluminateHttpRedirectResponse
 */
public static function twoFactorVerify(Request $request) {
    try {
        if(!Session::has('sessionId')) {
            return redirect()->route('login');
        }
        $cryptor = new Cryptor();

        $sessionId = $cryptor->decrypt(Session::get('sessionId'));
        $session = Sessions::where('id',$sessionId)->first();

        $sessionCheck = self::activeSessionCheck($session);
        if(!is_null($sessionCheck)) {
            return $sessionCheck;
        }

        $twoFactor = Two_Factor::where([
            'user_id' => $session->user_id, 'ip_address' => $_SERVER['REMOTE_ADDR']
        ])->first();

        if(!password_verify($request->input('codeText'),$twoFactor->code)) {
            return redirect()->route('2fa');
        }

        $session->update([
            'two_factor_id' => null,
            'authenticated' => 1
        ]);

        $twoFactor->delete();

        $intended = Session::pull('intended');
        if($intended) {
            return redirect()->to($intended);
        }
        return redirect()->route('authHome');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * resend2FA
 * Generates and sends a new 2FA code.
 *
 * @return  IlluminateHttpRedirectResponse
 */
public static function resend2FA() {
    try {
        if(!Session::has('sessionId')) {
            return redirect()->route('login');
        }
        $cryptor = new Cryptor();

        $sessionId = $cryptor->decrypt(Session::get('sessionId'));
        $session = Sessions::where('id',$sessionId)->first();

        $sessionCheck = self::activeSessionCheck($session);
        if(!is_null($sessionCheck)) {
            return $sessionCheck;
        }

        $user = User::where('id',$session->user_id)->first();
        if(empty($user)) {
            return self::logout();
        }

        $twoFactor = Two_Factor::where([
            'user_id' => $session->user_id, 'ip_address' => $_SERVER['REMOTE_ADDR']
        ])->first();
        if(!empty($twoFactor)) {
            $twoFactor->delete();
        }

        $code = RandomObjectGeneration::random_str(6, '1234567890');
        Two_Factor::create([
            'user_id' => $session->user_id,
            'ip_address' => $_SERVER['REMOTE_ADDR'],
            'code' => password_hash($code,PASSWORD_DEFAULT)
        ]);

        EmailController::sendTwoFactorEmail($user,$code);
        return redirect()->route('2fa');

    } catch(Exception $e) {
        ErrorLogging::logError($e);
        return abort('500');
    }
}

/**
 * activeSessionCheck
 * Helper function to check session objects.
 *
 * @param   Sessions    $session            The session to check.
 * @return  IlluminateHttpRedirectResponse | null
 */
private static function activeSessionCheck(Sessions $session) {
    if($session->ip_address !== $_SERVER['REMOTE_ADDR']) {
        $session->delete();
        Session::forget('sessionId');
        return redirect()->route('login');
    }

    if($session->authenticated === 1) {
        return redirect()->route('authHome');
    }
    return null;
}

/**
 * check
 * Validates if the user is authenticated on this IP Address.
 *
 * @return  bool
 */
public static function check() {
    if(!Session::has('sessionId')) {
        return false;
    }
    $cryptor = new Cryptor();

    $sessionId = $cryptor->decrypt(Session::get('sessionId'));
    $session = Sessions::where('id', $sessionId)->first();

    if($session->ip_address !== $_SERVER['REMOTE_ADDR']) {
        $session->delete();
        Session::forget('sessionId');
        return false;
    }
    return true;
}

/**
 * adminCheck
 * Validates if the user is an authenticated admin user.
 *
 * @return bool
 */
public static function adminCheck() {
    $check = self::check();
    if(!$check) {
        return $check;
    }

    $cryptor = new Cryptor();

    $sessionId = $cryptor->decrypt(Session::get('sessionId'));
    $session = Sessions::where('id', $sessionId)->first();

    $user = User::where('id',$session->user_id)->first();
    if(empty($user)) {
        $session->delete();
        Session::forget('sessionId');
        return false;
    }

    if($user->user_type !== 1) {
        return false;
    }
    return true;
}

/**
 * logout
 * Removes session variables storing the authenticated account.
 *
 * @return  IlluminateHttpRedirectResponse
 */
public static function logout() {
    $cryptor = new Cryptor();

    $sessionId = $cryptor->decrypt(Session::get('sessionId'));
    Sessions::where('id', $sessionId)->first()->delete();
    Session::forget('sessionId');

    return redirect()->route('login');
}

/**
 * generateLogin
 * Generates the login page.
 *
 * @return IlluminateHttpRedirectResponse | IlluminateViewView
 */
public static function generateLogin() {
    if(self::check()) {
        return redirect()->route('authHome');
    }
    return view('auth.login');
}

/**
 * generateRegister
 * Generates the register page if the user is an admin.
 *
 * @return IlluminateHttpRedirectResponse | IlluminateViewView
 */
public static function generateRegister() {
    if(self::adminCheck()) {
        $permissions = User_Permissions::all();
        $variables = array('permissions'=>$permissions);
        return view('auth.register')->with($variables);
    }
    return abort('401');
}

/**
 * authRequired
 * Adds session variable for return redirect and then redirects to login page.
 *
 * @return  IlluminateHttpRedirectResponse
 */
public static function authRequired() {
    Session::put('intended',$_SERVER['REQUEST_URI']);
    return redirect()->route('login');
}
}

Random Object Generation Library

<?php

namespace AppLibraries;

use DoctrineInstantiatorExceptionInvalidArgumentException;


class RandomObjectGeneration
{
const KEYSPACE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
const PASSWORD_KEYSPACE = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%&';

/**
 * random_str
 * Generates a random string.
 *
 * @param   int                         $length         Length of string to be returned
 * @param   bool                        $passwordFlag   Boolean flag identifying whether string will be a password
 * @param   string                      $keyspace       Allowed characters to be used in string
 * @throws  InvalidArgumentException
 * @return  string
 */
public static function random_str($length, $passwordFlag = false, $keyspace = RandomObjectGeneration::KEYSPACE)
{
    if($passwordFlag) {
        $keyspace = RandomObjectGeneration::PASSWORD_KEYSPACE;
    }
    if(empty($length) || !is_int($length) || $length < 0) {
        $message = 'Random String Generation: Length is Invalid. Length must be a positive integer. Value Provided: ' .
            var_export($length);
        throw new InvalidArgumentException($message);
    }
    if(empty($keyspace) || !is_string($keyspace)) {
        $message = 'Random String Generation: Invalid Keyspace';
        throw new InvalidArgumentException($message);
    }
    $str = '';
    $max = mb_strlen($keyspace) - 1;
    for ($i = 0; $i < $length; ++$i) {
        $str .= $keyspace[random_int(0, $max)];
    }
    return $str;
}
}

Sessions Model

<?php

namespace AppModels;

use IlluminateDatabaseEloquentModel;

class Sessions extends Model
{
protected $table = 'sessions';

protected $primaryKey = 'id';

protected $fillable = ['user_id',
    'ip_address',
    'two_factor_id',
    'authenticated'
];
}

ErrorLogging

<?php

namespace AppLibraries;


use IlluminateSupportFacadesLog;

class ErrorLogging
{
public static function logError(Exception $e) {
    $message = $e->getCode() . ': ' . $e->getMessage() . PHP_EOL;
    $message .= $e->getTraceAsString() . PHP_EOL;
    $message .= str_repeat('-',100) . PHP_EOL . PHP_EOL;
    Log::error($message);
}
}


Get this bounty!!!

Create Virtual Hosts with Apache

Apache is very flexible, and it’s easy to configure Apache to handle several domains even when your Web server only has one IP address to share between them. You can use this to host multiple sites, or just to provide a sandbox for development rather than making changes on your live site. This weekend, we’ll learn how to create virtual hosts with Apache.

Setting up virtual hosts might seem like a big challenge, but it’s not. In fact, you can set up a virtual host with just a few edits to Apache’s configuration and by setting up additional directories for the documents. For this how to, I want to use an Apache installation on a Ubuntu server. Please be aware, the instructions for this may require modification if being done on a non-Debian distribution because of the way that Apache is packaged. However, the Apache directives should be standard across distributions and should work even if Apache isn’t running on Linux.

Creating the Directory Structure

Before the configurations can be tackled, the directory structure for the virtual site must be created. We are going to be working with Apache as installed on a Ubuntu server, so the Apache document root will be/var/www. The directory structure for the new Web site can be created anywhere. Some create those directories in their home (~/) directory, some create them in /usr/local/apache, and other, various locations. For the sake of simplicity, We are going to illustrate setting the virtual host in the document root of Apache (in Ubuntu that would be /var/www). By doing this, it will not be necessary to change ownership of the newly created directory or the parent directory housing the virtual host (since Apache must have access to the directories and files.)

We are going to set up the virtual host demosite.com. So to create the directories for the virtual host, the following commands must be run:

  • sudo mkdir /var/www/demosite.com
  • sudo chmod -R 755 /var/www/demosite.com

Now that the home directory for the virtual host is done, it’s time to start configuring Apache so it is aware of the new site. After configuring Apache, the site can then be built within /var/www/demosite.com.

Apache Configuration

The first step in the Apache configuration is to make sure Apache knows virtual hosts are enabled. In the Ubuntu set up look for a line (near the bottom) of /etc/apache/apache2.conf that looks like:

Include sites-enabled/

Make sure that line is not commented out (does not begin with a ‘#‘ character). That sites-enabled include points to /etc/apache/sites-enabled. A look in that directory will reveal a file called 000-default. That file should contain all of the directory containers needed for virtual sites on the server. To create a new virtual host (to map the example demosite.com), create a new file within sites-available called /etc/apache/sites-available/demosite.com. The contents of that file will look something similar to this (depending upon the needs and application of the virtual host):


<VirtualHost test.domain.com>
   ServerAdmin webmaster@localhost
   #We want to be able to access the web site using www.test.domain.com or test.domain.com
   ServerAlias www.test.domain.com
   DocumentRoot /var/www/demosite.com
   #log file for this server
   CustomLog /var/log/apache2/www.test.domain.com-access.log combined
</VirtualHost>

The above code assumes that domain.com is the actual domain to be used (insert proper domain where necessary). It’s almost ready to fire up, but we have two simple steps left before restarting Apache. The first step is to create a link in /etc/apache/sites-enabled to the file we just created. This is done with the following steps:

  1. Change to the /etc/apache/sites-enabled directory with the command cd /etc/apache/sites-enabled .
  2. Create the link with the command sudo ln -s /etc/apache/sites-available demosite.com .

It is also possible to create the links automatically with the command sudo a2ensite demosite.com and then, should the virtual site need to be disabled, remove the link with the command sudo a2dissite demosite.com.

The last step is to make sure the server knows that our new virtual site is to be found on the server and not out on the Internet. For this, do the following:

  • Open up the /etc/hosts file in a text editor (with administrative rights).
  • Add a line like 127.0.0.1 localhost.localdomain localhost test.domain.com www.demosite.com .
  • Save and close that file.

Now it’s time to restart Apache with the command sudo /etc/init.d/apache2 restart and test virtual host by pointing a browser to the address.

Non-Debian Servers

If the server hosting the virtual sites is a non-Debian distribution, the steps are different for hosting virtual sites. Here’s how it works:

  1. Create the directory container for the virtual site in /etc/httpd/conf/httpd.conf. This container will look similar to that used for the Debian-based server.
  2. Make sure the Apache configuration file is aware of virtual hosts by making sure the line Include conf.d/*.conf is not commented out.
  3. Create the new virtual hosts file (we’ll call it vhosts.conf) in /etc/httpd/conf.d/ .
  4. Add the virtual site to the /etc/hosts file.
  5. Restart Apache with the command /etc/rc.d/init.d/httpd restart.

The directory container, for the non-Debian host, will look similar to the very basic container below:


<VirtualHost *:80>
   ServerName demosite.com
   DocumentRoot /var/www/html/demosite.com
</VirtualHost>

The virtual hosts file mentioned above, will need to look like this:


<VirtualHost 127.0.0.1> 
   DocumentRoot /var/http/www/demosite.com
   ServerName www.demosite.com
</VirtualHost>  

<VirtualHost 127.0.0.1>
   DocumentRoot /var/http/www/demosite.com
   ServerName test.demosite.com
</VirtualHost>

Building Time

Now that the virtual host is up and running, it is now possible to build the site within the/var/www/demosite.com directory.

You can do this for as many virtual hosts as you need (assuming the server can take the added load).

Source

Simple way to generate a random password in PHP

When creating web apps, there’s often a need to generate a random password for your users. There are a number of ways to do this, but in needing to do it recently I came up with this very simple function that will generate a password (or other random string) of whatever length you wish. It’s particularly useful when generating passwords for users that they will then change in the future. It uses PHP’s handy str_shuffle() function:

<?php
    function random_password( $length = 8 ) {
         $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_-=+;:,.?";
         $index=rand($length,$length*$length);
         $password='';
         for($i=0;$i<$index;$i++){
            $password = substr( str_shuffle( $chars.$password ), 0, $length );
         }
         return $password;
    }

?>
<?php $password = random_password(8); ?>

NOTE: This method is better than the on posted in the Source. It randomizes the password generation process enough to be safe from brute force or predictability.

When and how much to mix technologies for a project?

The main idea behind using a technology is to harness the power of code re-usability and libraries that have already been worked on and trusted to be working and functional with minimal or no issues.

The term “Technology” does not just refer to Java or C++ or JavaScript. It also refers to the frameworks that can be used to suffice some or the other requirements with minimum cost and minimal effort investment. One example can be any Application Development Framework Like Oracle ADF, Pega or Drupal, etc. The framework itself provides functionalities that are most common and also takes cares of the issues that people face while developing an application.

Any application which has to be developed from scratch needs a lot of work just to be useful enough to be used in Production environment. Basic Non-functional requirements such as MVC Architecture, Security safeguards, Application Performance, etc. are the basic and most common features of the application. In addition, Secure Login, User Registration and authentication, role mapping and similar features are also mandatory features of the application.

Most frameworks provide features such as configurable work flows, built in UI Elements, security aspects and many other features. Features such as SQL Escaping, HTML Tag Escaping and MVC Pattern architecture are generally already inbuilt to the framework. The developers can simply configure the workflows, create screens and corner out application logic and then the application is good to go.

But is that enough that we may need??

This the main question that we need to ask when trying to select technologies and try to mix them to achieve the application requirement. The Case study can be a sample B-2-B Application say Business-2-Go (B2G).

Advantage of Techs to be selected:

The B2G can be based on 3 major technology products namely an Identity Management System, an Application Development Framework, and a Content Management Service. The technologies in combination provide the architecture to harness the features out of the box.

The IDM would provide Session Maintenance, Role Mappings, Access Authentications and invalid access handling.

CMS on the other hand takes care of the static content of the application. This technology handles the application content which needs to be configurable but would be changed in very rare scenarios. The main usefulness lies in the fact that the CMS portal can be exposed to the customer admin team as well and be comfortable as the code base will not be touched by the Non Development User.

The ADF constitutes to the application flow of the B2G. All user interactions and other business logic is handled by this technology. The flexibility of the framework helps create applications quickly and more efficiently than the older technologies/frameworks such as J2EE Servlets/JSP or struts and so on.

Further technologies like JavaScript, jQuery, CSS have been used to achieve the look and feel that was decided by the client.

Disadvantages of Techs to be selected:

The disadvantages or rather limitations of the tech or the team using the tech is the one that decides whether the tech can be used or not.

The major factors can be:

  • Cost: The technology that has been perfected and supported may be in most cases be licensed. Thus incurring costs to the budget of the project. The alternative may be using Open Source technologies/frameworks. But there the problem exists of the credibility of the source, issue support and whether documentation is enough or not.
  • Resource Availability: Assuming that the cost barrier of the license has been overcome. Now the major concern is whether the resources for the technology are available or not. If not, then can existing resources be trained or can new resources can be acquired. Again the cost factor is affected in this concern.
  • Technology Limitations: Technologies have limitations in themselves also. The limitation may not be a feature that cannot be achieved, but the effort that may be involved in achieving the feature. A simple example may be a particular look and feel of a B2G. Many of the UI Elements may or may not be achievable with the selected core ADF. Or even if they are achievable, it is after a lot of R&D or with lot of hit and trials. Though this is not something that may rule out the technology itself, but may be enough to include other technologies like jQuery into the picture.
  • Interfacing efforts: While mixing technologies, spots/hooks need to be found where 1 tech may latch on to or may be placed in with the other. For example, jQuery is an Independent Tech and in the selected ADF, generally has an internal client side scripts are functioning on its own end. There may be provisions which execute scripts that achieve the UI functionalities. Similarly the CMS may not have stable out of the box connectors to code layer of the application. Thus interfaces are written to implement make this possible. This effort may also turn out to be a concern for using a tech.

An example of tech selection may be PHP. The technology PHP can also be used for creating a complete application and 99% of the same application can be achieved using PHP frameworks. In fact the cost of the tech is 0 (Open Source) and resource costing would be way lower than those of licensed application framework. But the efforts and timescale needed to achieve all the functionalities required will be humongous. Thus ruling out the tech.

Another concern that can be raised is how much the technologies can be mixed. Surely each of the frameworks will be providing some or the other comfort or a feature. Even if they are published in open source or you may have license available. Does that mean that all technologies should be mixed..??

Interfacing technologies uses effort. It also invokes limitations. An example may be the various attempts to integrate popular front-end framework like AngularJS with Oracle ADF. Oracle ADF is a mainly a Server Side Technology, maintaining all functionalities server side and providing a wide palette of features for an application. AngularJS on the other hand is a completely UI framework. It is completely Client Side Intensive Tech. Both frameworks are completely in the opposite directions. Both are unaware of the other. There are blogs showing way how to integrate both the technologies. But all can point out the issues in the integration. This is a small example, but scaling this, similar issues may be faced and thus may be counted as factors in Tech Selection.

In Conclusion, the trade-offs govern the selections of the technologies to be used in a project. Proper selections must be made in order to plan out the architecture. Improper selection may lead to issues, crashes, late deliveries or redundant costs.

References:

Image: https://www.systrends.com/sites/default/files/banner/appdev_banner2.jpg