Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
lmajano committed Feb 12, 2021
2 parents 5e6291c + 31fe911 commit bd4e5e9
Show file tree
Hide file tree
Showing 12 changed files with 72 additions and 53 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ test-harness/logs/**
test-harness/modules/**

# log files
logs/**
logs/**

modules/**
2 changes: 1 addition & 1 deletion box.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name":"ColdBox Security",
"version":"2.9.0",
"version":"2.10.0",
"location":"https://downloads.ortussolutions.com/ortussolutions/coldbox-modules/cbsecurity/@build.version@/cbsecurity-@build.version@.zip",
"author":"Ortus Solutions.com <info@ortussolutions.com>",
"slug":"cbsecurity",
Expand Down
9 changes: 9 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

----

## [2.10.0] => 2021-FEB-12

### Added

* Moved the registration of the validator from the `configure()` to the `afterAspectsLoad()` interception point to allow for modules to declare the validator if needed.
* Moved handler bean to `afterAspectsLoad()` to allow for module based invalid events to work.

----

## [2.9.0] => 2020-DEC-11

### Fixed
Expand Down
40 changes: 19 additions & 21 deletions interceptors/Security.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ component accessors="true" extends="coldbox.system.Interceptor" {
* Configure the security firewall
*/
function configure(){
variables.onInvalidEventHandlerBean = javacast( "null", "" );
if ( len( variables.invalidEventHandler ) ) {
variables.onInvalidEventHandlerBean = handlerService.getHandlerBean( variables.invalidEventHandler );
}

// init the security modules dictionary
variables.securityModules = {};

Expand All @@ -49,10 +44,7 @@ component accessors="true" extends="coldbox.system.Interceptor" {
setProperty( "rules", variables.rulesLoader.loadRules( getProperties() ) );
}

// Load up the validator
registerValidator( getInstance( getProperty( "validator" ) ) );

// Coldbox version 5 (and lower) needs a little extra invalid event handler checking.
// Coldbox version 5 (and lower) needs a little extra invalid event handler checking.
variables.enableInvalidHandlerCheck = ( listGetAt( controller.getColdboxSettings().version, 1, "." ) <= 5 );
}

Expand All @@ -66,6 +58,10 @@ component accessors="true" extends="coldbox.system.Interceptor" {
prc,
buffer
){

// Register the validator
registerValidator( getInstance( getProperty( "validator" ) ) );

// Register cbSecurity modules so we can incorporate them.
controller
.getSetting( "modules" )
Expand All @@ -82,6 +78,12 @@ component accessors="true" extends="coldbox.system.Interceptor" {
// Register Module
registerModule( arguments.module, arguments.config.settings.cbSecurity );
} );

// Once ColdBox has loaded, load up the invalid event bean
variables.onInvalidEventHandlerBean = javacast( "null", "" );
if ( len( variables.invalidEventHandler ) ) {
variables.onInvalidEventHandlerBean = handlerService.getHandlerBean( variables.invalidEventHandler );
}
}

/**
Expand Down Expand Up @@ -241,14 +243,14 @@ component accessors="true" extends="coldbox.system.Interceptor" {
){
// Get handler bean for the current event
var handlerBean = variables.handlerService.getHandlerBean( arguments.event.getCurrentEvent() );

// Are we running Coldbox 5 or older?
// is an onInvalidHandlerBean configured?
// is the current handlerBean the configured onInvalidEventHandlerBean?
if (
variables.enableInvalidHandlerCheck &&
!isNull( variables.onInvalidEventHandlerBean ) &&
isInvalidEventHandlerBean( handlerBean )
if (
variables.enableInvalidHandlerCheck &&
!isNull( variables.onInvalidEventHandlerBean ) &&
isInvalidEventHandlerBean( handlerBean )
) {
// ColdBox tries to detect invalid event handler loops by keeping
// track of the last invalid event to fire. If that invalid event
Expand All @@ -260,7 +262,7 @@ component accessors="true" extends="coldbox.system.Interceptor" {
request._lastInvalidEvent = variables.invalidEventHandler;
return;
}

if ( handlerBean.getHandler() == "" ) {
return;
}
Expand Down Expand Up @@ -555,13 +557,9 @@ component accessors="true" extends="coldbox.system.Interceptor" {
* @return { allow:boolean, type:string(authentication|authorization)}
*/
private struct function verifySecuredAnnotation( required securedValue, required event ){
// If no value, then default it to true
if ( !len( arguments.securedValue ) ) {
arguments.securedValue = true;
}

// Are we securing?
if ( isBoolean( arguments.securedValue ) && !arguments.securedValue ) {
if ( len( arguments.securedValue ) && isBoolean( arguments.securedValue ) && !arguments.securedValue ) {
return {
"allow" : true,
"type" : "authentication"
Expand Down Expand Up @@ -741,7 +739,7 @@ component accessors="true" extends="coldbox.system.Interceptor" {

return len( CGI.REMOTE_ADDR ) ? CGI.REMOTE_ADDR : "127.0.0.1";
}

/**
* Returns true of the passed handlerBean matches Coldbox's configured invalid event handler.
*
Expand Down
4 changes: 2 additions & 2 deletions interfaces/IAuthUser.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ interface{
function getId();

/**
* Verify if the user has one or more of the passed in permissions
* Verify if the user has the permission passed in
*
* @permission One or a list of permissions to check for access
* @permission A single permission to check for access
*
*/
boolean function hasPermission( required permission );
Expand Down
6 changes: 4 additions & 2 deletions interfaces/ISecurityValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ interface{
* This function is called once an incoming event matches a security rule.
* You will receive the security rule that matched and an instance of the ColdBox controller.
*
* You must return a struct with two keys:
* You must return a struct with three keys:
* - allow:boolean True, user can continue access, false, invalid access actions will ensue
* - type:string(authentication|authorization) The type of block that ocurred. Either an authentication or an authorization issue.
* - messages:string Info/debug messages
*
* @return { allow:boolean, type:string(authentication|authorization), messages:string }
*/
Expand All @@ -22,9 +23,10 @@ interface{
* This function is called once access to a handler/action is detected.
* You will receive the secured annotation value and an instance of the ColdBox Controller
*
* You must return a struct with two keys:
* You must return a struct with three keys:
* - allow:boolean True, user can continue access, false, invalid access actions will ensue
* - type:string(authentication|authorization) The type of block that ocurred. Either an authentication or an authorization issue.
* - messages:string Info/debug messages
*
* @return { allow:boolean, type:string(authentication|authorization), messages:string }
*/
Expand Down
2 changes: 1 addition & 1 deletion models/CBSecurity.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ component singleton accessors="true" {
* @items One, a list or an array
*/
private function arrayWrap( required items ){
return isArray( arguments.items ) ? items : items.listToArray();
return isArray( arguments.items ) ? items : listToArray( items );
}

}
5 changes: 1 addition & 4 deletions models/jwt/JwtService.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -759,10 +759,7 @@ component accessors="true" singleton {
results.allow = (
tokenHasScopes( arguments.permissions, payload.scope )
||
variables.cbSecurity
.getAuthService()
.getUser()
.hasPermission( arguments.permissions )
variables.cbSecurity.has( arguments.permissions )
);
results.type = "authorization";
} else {
Expand Down
16 changes: 8 additions & 8 deletions models/validators/CBAuthValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
* Copyright since 2016 by Ortus Solutions, Corp
* www.ortussolutions.com
* ---
* This is the core validator which leverages CF Security via cflogin and cfloginuser
* This is the core validator which leverages CBAuth
* https://helpx.adobe.com/coldfusion/developing-applications/developing-cfml-applications/securing-applications/using-coldfusion-security-tags-and-functions.html
*/
component singleton {

// Injection
property name="cbauth" inject="authenticationService@cbauth";
property name="cbSecurity" inject="CBSecurity@cbSecurity";

/**
* This function is called once an incoming event matches a security rule.
* You will receive the security rule that matched and an instance of the
* ColdBox controller.
*
* You must return a struct with two keys:
* You must return a struct with three keys:
* - allow:boolean True, user can continue access, false, invalid access actions will ensue
* - type:string(authentication|authorization) The type of block that ocurred. Either an authentication or an authorization issue.
* - messages:string Info/debug messages
*
* @return { allow:boolean, type:authentication|authorization, messages:string }
* @return { allow:boolean, type:string(authentication|authorization), messages:string }
*/
struct function ruleValidator( required rule, required controller ){
return validateSecurity( arguments.rule.permissions );
Expand All @@ -30,12 +30,12 @@ component singleton {
* This function is called once access to a handler/action is detected.
* You will receive the secured annotation value and an instance of the ColdBox Controller
*
* You must return a struct with two keys:
* You must return a struct with three keys:
* - allow:boolean True, user can continue access, false, invalid access actions will ensue
* - type:string(authentication|authorization) The type of block that ocurred. Either an authentication or an authorization issue.
* - messages:string Info/debug messages
*
* @return { allow:boolean, type:authentication|authorization, messages:string }
* @return { allow:boolean, type:string(authentication|authorization), messages:string }
*/
struct function annotationValidator( required securedValue, required controller ){
return validateSecurity( arguments.securedValue );
Expand All @@ -54,10 +54,10 @@ component singleton {
};

// Are we logged in?
if ( variables.cbauth.isLoggedIn() ) {
if ( variables.cbSecurity.getAuthService().isLoggedIn() ) {
// Do we have any permissions?
if ( listLen( arguments.permissions ) ) {
results.allow = variables.cbauth.getUser().hasPermission( arguments.permissions );
results.allow = variables.cbSecurity.has( arguments.permissions );
results.type = "authorization";
} else {
// We are satisfied!
Expand Down
8 changes: 4 additions & 4 deletions models/validators/CFValidator.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ component singleton {
* You will receive the security rule that matched and an instance of the
* ColdBox controller.
*
* You must return a struct with two keys:
* You must return a struct with three keys:
* - allow:boolean True, user can continue access, false, invalid access actions will ensue
* - type:string(authentication|authorization) The type of block that ocurred. Either an authentication or an authorization issue.
* - messages:string Info/debug messages
*
* @return { allow:boolean, type:authentication|authorization, messages:string }
* @return { allow:boolean, type:string(authentication|authorization), messages:string }
*/
struct function ruleValidator( required rule, required controller ){
return validateSecurity( arguments.rule.roles );
Expand All @@ -27,12 +27,12 @@ component singleton {
* This function is called once access to a handler/action is detected.
* You will receive the secured annotation value and an instance of the ColdBox Controller
*
* You must return a struct with two keys:
* You must return a struct with three keys:
* - allow:boolean True, user can continue access, false, invalid access actions will ensue
* - type:string(authentication|authorization) The type of block that ocurred. Either an authentication or an authorization issue.
* - messages:string Info/debug messages
*
* @return { allow:boolean, type:authentication|authorization, messages:string }
* @return { allow:boolean, type:string(authentication|authorization), messages:string }
*/
struct function annotationValidator( required securedValue, required controller ){
return validateSecurity( arguments.securedValue );
Expand Down
13 changes: 10 additions & 3 deletions test-harness/tests/specs/unit/SecurityTest.cfc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,13 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="cbse
.$( "getAppRootPath", expandPath( "/root" ) )
.$( "getColdboxSettings", {
"version": "6.0.0"
}, false );
}, false );

mockController
.$( "getSetting" )
.$args( "modules" )
.$results( [] );

security = interceptor;
security.setInvalidEventHandler( '' );
settings = {
Expand Down Expand Up @@ -114,7 +120,8 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="cbse
.$args( settings.validator )
.$results( wirebox.getInstance( settings.validator ) );

security.configure();
security.afterAspectsLoad();

expect(
security.getValidator(
createMock( "coldbox.system.web.context.RequestContext" ).$( "getCurrentModule", "" )
Expand All @@ -135,7 +142,7 @@ component extends="coldbox.system.testing.BaseInterceptorTest" interceptor="cbse
.$results( createStub() );

expect( function(){
security.configure();
security.afterAspectsLoad();
} ).toThrow( "Security.ValidatorMethodException" );
} );

Expand Down
16 changes: 10 additions & 6 deletions views/home/settings.cfm
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<cfscript>
globalSettings = prc.properties.filter( function( key ){
return !listFindNoCase( "rules,jwt", key );
} );
jwtSettings = prc.properties.jwt.filter( function( key ){
return !listFindNoCase( "secretKey", key );
} );
</cfscript>
<cfoutput>
<div class="mt-2">

<p>Here is a listing of the settings for the global interceptor <code>cbsecurity@global</code>:</p>

<cfdump var="#prc.properties.filter( function( key ){
return !listFindNoCase( "rules,jwt", key );
} )#">
<cfdump var="#globalSettings#">

<h2>JWT Settings</h2>
<p>Here are your settings for your Json Web Tokens Security. Please note your <code>secretKey</code> is not shown.</p>
<cfdump var="#prc.properties.jwt.filter( function( key ){
return !listFindNoCase( "secretKey", key );
} )#">
<cfdump var="#jwtSettings#">

</div>
</cfoutput>

0 comments on commit bd4e5e9

Please sign in to comment.