Whitelisting instead of blacklisting with SecurityComponent::requireSecure() - cakephp

I'd like to use CakePHP's SecurityComponent to enforce app requests to be made over SSL using requireSecure().
My issue is that by default this is a blacklist methodology - allow insecure access by default, unless explicitly prohibited in that Controller. I'd like to switch to a whitelist methodology - deny insecure access by default, unless I explicitly allow it in that Controller.
Is this functionality built into the SecurityComponent? If not, how can I set this up manually?

It doesn't appear that this is built in by default. You could simulate this by creating a $requireSecure property of your Controllers, and then conditionally calling requireSecure() in AppController::beforeFilter(). Here's how you would implement it:
AppController.php:
public $requireSecure = true;
public function beforeFilter() {
if ($this->requireSecure) {
$blacklist = is_array($this->requireSecure) ? $this->requireSecure : array('*');
$this->Security->requireSecure($blacklist);
}
}
Whitelisted controller:
public $requireSecure = false;
Controller, varies by method (note that $requireSecure is a blacklist):
public $requireSecure = array('login');
This achieves the objective of requiring SSL by default, but being able to explicitly override this requirement in the Controller if desired.

Related

CakePHP Globally override class?

I reconfigured my cakeEmail class to log to a specific type by rewriting the send method. I would like to use this override globally. My current single file setup uses /Lib/CustomCakeEmail.php with
App:uses('CustomCakeEmail', 'Lib');
CakePhp: Cake Email AfterSend event suggests a method to globally override using AppController but I have been unable to even trigger the debugger in
App::uses('CustomCakeEmail', 'Lib');
class AppController extends Controller {
public function getEmailInstance($config = null) {
CakeLog::write('debug', 'appcontroller triggered');
return new CustomCakeEmail($config);
}
What is the correct way to implement this global override?
CakePHP Version 2.8.4

Turn off Hystrix functionality

I am integrating Hystrix in an application. That application is already in production and we will be testing out hystrix integration work in sandbox before we will push it to production.
My question is that is there any way to turn on/off hystrix functionality using some configuration setting?
There is no single setting for this. You'll need to set multiple parameters to disable Hystrix.
See https://github.com/Netflix/Hystrix/wiki/Configuration for the configuration options:
hystrix.command.default.execution.isolation.strategy=SEMAPHORE
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests=100000 # basically 'unlimited'
hystrix.command.default.execution.timeout.enabled=false
hystrix.command.default.circuitBreaker.enabled=false
hystrix.command.default.fallback.enabled=false
Please double check your version of Hystrix for the available parameters.
This is all what you need:
# Disable Circuit Breaker (Hystrix)
spring:
cloud:
circuit:
breaker:
enabled: false
hystrix:
command:
default:
circuitBreaker:
enabled: false
As ahus1 said, there is no single way to disable Hystrix entirely. To disable it in our application, we decided it was cleanest and safest to put a HystrixCommand in a wrapper class, and that wrapper class only exposed the parts of the HystrixCommand that we used (in our case, the execute() method). When constructing the wrapper class, we pass it a Callable that contains the code we want executed, and if Hystrix is disabled (according to our own config value), we simply call that Callable without ever creating a HystrixCommand. This avoids executing any Hystrix code whatsoever and makes it easier to say that Hystrix isn't affecting our application at all when it's disabled.
There are a couple of ways to achieve this-
Doing this for your every group including default. Although this will not disable hystrix(it will only keep the circuit closed all the time) but you will achieve the same result-
hystrix.command.{group-key}.circuitBreaker.forceClosed=false
If you are using java, you can create an around advice over #HystrixCommand annotation and bypass hystrix execution based upon a flag.
Java Code for #2-
#Pointcut("#annotation(com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand)")
public void hystrixCommandAnnotationPointcut() {
}
#Around("hystrixCommandAnnotationPointcut()")
public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
Method method = AopUtils.getMethodFromTarget(joinPoint);
if ((System.getProperty(enable.hystrix).equals("true")) {
result = joinPoint.proceed();
} else {
result = method.invoke(joinPoint.getTarget(), joinPoint.getArgs());
}
return result;
}
If your Project is spring Managed you can comment the bean definition of hystrixAspect in applicationContext.xml
Comment the following line
bean id="hystrixAspect"class="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"/>
This will remove Hystrix from your project.
I ran into this situation where I wanted to completely turnoff Hystrix using a single property (We use IBM uDeploy to manage dynamic properties). We are using javanica library built on top of Hystrix
Create a Configuration class which creates the HystrixCommandAspect
#Configuration
public class HystrixConfiguration{
#Bean(name = "hystrixCommandAspect")
#Conditional(HystrixEnableCondition.class)
public HystrixCommandAspect hystrixCommandAspect(){
return new HystrixCommandAspect()}
}
2. And the conditional class would be enabled based on a system property.
public class HystrixEnableCondition implements Condition{
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata){
return
"YES".equalsIgnoreCase(
context.getEnvironment().getProperty("circuitBreaker.enabled")) ||
"YES".equalsIgnoreCase(
System.getProperty("circuitBreaker.enabled"));
}
}
setting
hystrix.command.default.execution.isolation.strategy=SEMAPHORE
is enough.
Additionally you may or should disable also the timeout threads
with hystrix.command.default.execution.timeout.enabled=false

How to enable Security(CSRF) alone in Cake 2.0

I am trying to enable CSRF security in Cakephp 2.0
I have included the Security component in my controller.
public $components = array( 'Security');
I want to enable this component for only one function, say function test.
Other functions must be free of Security
I have tried to do like
$this->Security->requireSecure('test');
I have provided it like this as i want to enable security in test function alone.
In cakephp3.0 I found a option for enabling CSRF alone. But i need the solution for cakephp 2.0
I don't need any other securities validatePost, requirePost, requireDelete etc..
Awaiting for the feedbacks. Thanks in advance.
CSRF should be enabled in every action/form by default, and disabled for any action you want, not the backwards.
public $components = array('Security');
private $disabledCSRFForActions = array("test");
public function beforeFilter() {
parent::beforeFilter();
if (isset($this->Security) && in_array($this->action, $disabledCSRFForActions) {
$this->Security->validatePost = false;
$this->Security->enabled = false;
$this->Security->csrfCheck = false;
}
}

CakePHP: Use AWS's DynamoDB Session Handler

I have a CakePHP application hosted on AWS Elastic Beanstalk. Because of the multiple EC2 instances I will use in the future I want to store my PHP sessions in a database. AWS provides a very nice library for storing PHP sessions in their DynamoDB database. See http://goo.gl/URoi3s
Now I putted the AWS SDK in my vendors folder and created an access wrapper for it (a plugin):
<?php
Configure::load('aws');
require_once VENDORS . 'autoload.php';
use Aws\Common\Aws;
class AwsComponent extends Component
{
private $_aws;
public function __construct()
{
$this->_aws = Aws::factory(array(
'key' => Configure::read('Aws.key'),
'secret' => Configure::read('Aws.secret'),
'region' => Configure::read('Aws.region')
));
}
public function getClient($service)
{
return $this->_aws->get($service);
}
}
The wrapper is working well, I already implemented some S3 stuff. Now for the session handler i added the following code to my AppController.php:
public $components = array('Aws.Aws');
public function beforeFilter()
{
$this->_setSessionStorage();
}
private function _setSessionStorage()
{
$client = $this->Aws->getClient('dynamodb');
$client->registerSessionHandler(array(
'table_name' => 'sessions'
));
}
The AWS's internal registerSessionHandler() is executed (tested it) but the session is not beeing stored into the DynamoDB table. Of course I created the table before and if I add the call to the AWS library directly to my webroot/index.php before dispatcher is loaded everything works fine.
I think the problem is that my code is executed after CakePHP calls session_start(). So what is the best way to implement that? http://goo.gl/kUFUIR doesn't help me, I don't want to rewrite the AWS library for beeing compatible with the CakePHP interface.
So what is the best way to implement that? http://goo.gl/kUFUIR
doesn't help me, I don't want to rewrite the AWS library for beeing
compatible with the CakePHP interface.
This is in fact the best way. And this does not mean to reinvent the wheel, abstraction in OOP means that you make things available in a generic interface that can be replaced with something else. You wrap a foreign API or code in an API compatible to your system, in this case a CakePHP application.
Wrap the vendor lib in a AwsSession adapter that implements the CakeSessionHandlerInterface. This way it's API compatible with other session adapters in the case you change it and it might be even solve your core problem, because CakeSession will take care of the initialization.
Your component is initialized after the session in CakePHP, when the controller is already instantiated and then is initializing all its components. So this happens at a pretty late time. Your alternative is to stop CakePHP from initializing the session, I never had a need to do so, so no idea without looking it up myself. Dig in CakeSession. Even if you manage to do so, other components like the default Auth adapter depends on being able to work with Sessions, so you have to take care of the issue that your component has to be loaded before Auth as well. Pretty fragile system with lots of possbile points of failure. Seriously, go for the Session adapter, guess its a lot less painful to get it working this way.
By a quick look at the DynamoDB Session documentation this seems to be pretty easy. Extend the regular session handler and overload only the init and garbage collection of it to add the Aws API calls there, no guarantee this is right but seems to be easy.
What I end up with in CakePHP 3.
src/Network/Session/DynamoDbSession.php
&lt?php
namespace App\Network\Session;
use Aws\DynamoDb\DynamoDbClient;
use Cake\Core\Configure;
class DynamoDbSession implements \SessionHandlerInterface
{
private $handler;
/**
* DynamoDbSession constructor.
*/
public function __construct()
{
$client = new DynamoDbClient(Configure::read('DynamoDbCredentials'));
$this->handler = $client->registerSessionHandler(array(
'table_name' => Configure::read('DynamoDbCredentials.session_table')
));
}
public function close()
{
return $this->handler->close();
}
public function destroy($session_id)
{
return $this->handler->destroy($session_id);
}
public function gc($maxlifetime)
{
return $this->handler->gc($maxlifetime);
}
public function open($save_path, $session_id)
{
return $this->handler->open($save_path, $session_id);
}
public function read($session_id)
{
return $this->handler->read($session_id);
}
public function write($session_id, $session_data)
{
return $this->handler->write($session_id, $session_data);
}
}
Activate it in config/app.php file:
'Session' => [
'defaults' => 'php',
'handler' => [
'engine' => 'DynamoDbSession'
],
'timeout' => (30 * 24 * 60)
]

Html5 pushstate Urls on ServiceStack

At the moment we're using a default.cshtml view in the root of ServiceStack to serve our AngularJS single-page app.
What I'd like to do is enable support for html5 pushstate (so no hash in the URL), but the only examples I've found so far involve a dependency on MVC with a wildcard route, and pushing the ServiceStack infrastructure to a /api subroute.
We can't take the MVC dependency, so I think we need for accept:text/html requests we need to accept any url and serve up our root application. I'd be happy to remove the default HtmlFormat extension or override it (we could still use it's JsonReport content type it we needed to).
How can I best approach this?
The Order of Operations wiki page shows the number of different hooks you can tap into to inject your own customized behavior as well as the order which they are run.
Hi-jacking requests with RawHttpHandlers
You can by-pass ServiceStack completely by adding a Config.RawHttpHandlers to return a IHttpHandler on requests you want to hi-jack, e.g this is how the built-in mini profiler hi-jacks all requests for files that start with ssr- and returns the physical file:
config.RawHttpHandlers.Add((IHttpRequest request) => {
var file = GetFileNameWithoutExtension(request.PathInfo);
return file != null && file.StartsWith("ssr-")
? new MiniProfilerHandler()
: null;
}
Providing a fallback handler for non-matching routes
If you want to provide a default handler for non-matching route you can register a CatchAllHandlers in AppHost.Configure() or in a plugin with:
appHost.CatchAllHandlers.Add((string method, string pathInfo, string filepath) =>
{
return ShouldProvideDefaultPage(pathInfo)
? new RazorHandler("/defaultpage.cshtml")
: null;
});
Using a wildcard to accept any url in a service
You could create a dummy service and simply return the same single view, e.g:
[Route("/app/{PathInfo*}")]
public class App {
public string PathInfo { get; set; }
}
public class MyService : Service
{
public object Any(App request)
{
return request;
}
}
With the wild card this service will return the view e.g. /View/App.cshtml on any route starting with /app, e.g:
/app
/app/hello
/app/hello/my/name/is?foo=bar
Partial page support
Since partial reloads is related to pushstate I'll also mention the built-in support ServiceStack has for partial reloads.
ServiceStack Docs is an example demo that uses pushstate on browsers that support it, otherwise it falls back to use full-page reloads with browsers that don't.
You can ask for a partial page with ?format=text.bare param, e.g.
Full page: http://www.servicestack.net/docs/markdown/about
Partial page: http://www.servicestack.net/docs/markdown/about?format=html.bare
Partial page markdown: http://www.servicestack.net/docs/markdown/about?format=text.bare
Although this uses Markdown Razor. In the latest ServiceStack.Razor support you can access a partial page with just: ?format=bare
Expanding on my comment. This is what I ended up with trying to host an application in /app while also supporting the virtual file system.
host.CatchAllHandlers.Add((string method, string pathInfo, string filepath) =>
{
if (!Regex.IsMatch(pathInfo, "^/app([/?]|$)"))
return null;
// Serve valid requests as is
var vFile = HostContext.ResolveVirtualFile(pathInfo, null);
if (vFile != null)
return null;
var vDir = HostContext.ResolveVirtualDirectory(pathInfo, null);
if (vDir != null && vDir.GetDefaultDocument() != null)
return null;
// Fallback to default document
var vDef = HostContext.ResolveVirtualDirectory("/app/", null).GetDefaultDocument();
return new CustomResponseHandler((req, res) =>
new HttpResult(vDef.OpenRead(), MimeTypes.GetMimeType(vDef.Name)));
});

Resources