Skip navigation
All Places > Developer > Blog > 2015 > December
2015
Based on Sugar Developer community feedback, we have an additional update about the CreateActionsView changes in Sugar 7.7.

 

CreateActions migration script added to Sugar 7.7 Upgrader

 

During Sugar 7.7 upgrade, the upgrader will identify existing create-actions view/layout customizations and automatically migrate them to create view/layout.  This is a best effort migration that follows the two steps listed near bottom of this blog post.

 

If a custom create view/layout already exists, then create-actions changes will not be automatically migrated.

 

This will mitigate impact of this change for existing Sugar customers.

The Sugar application requires that a number of directories be writable in order to properly function.  The precise directories and minimum permissions needed are covered in the Sugar Install Guide.

 

A common practice for Sugar Developers to work around file permission issues is to make everything writable to the web user.  In practice, this does not cause any functional issues and is an easy way to avoid problems. But this is not desirable in production or sensitive environments from a security point of view because it violates the principle of least privilege. So Developers should really familiarize themselves with setting up secure file permissions for their web servers since this will be more in line with real production environments.

 

Here are some tips for working with extended file system permissions on your Sugar deployments from Jelle Vink our Security Architect.

 

Using extended File System ACLs

 

To have more granular control there is an option to use extended file system access controls.  Normally Linux file systems are mounted with extended attribute support by default. The common file systems all support this (ext2, ext3, ext4, reiserfs, btrfs, jfs, etc) so it is worth investigating this approach if your environment supports it.

 

You can use the setfacl, getfacl and getfattr commands for extended access control which means that you can actually assign more than one user and/or group to a file or directory and set specific access permissions for each one of them. More information about these extended attributes can be found on the web.

 

Configuring default Sugar file system permissions

 

Sugar does not always use same routines to create files and directories. Some use raw fopen to access the file system but most accesses go through sugar_file_utils functions. When the latter are used, the following settings apply for newly created directories and files.

 

These settings can be configured in config_override.php to allow control over how default file permissions are set:

$sugar_config['default_permissions']['user'] = 'user_goes_here'; //Empty by default

 

$sugar_config['default_permissions']['group'] = 'group_goes_here'; //Empty by default

 

$sugar_config['default_permissions']['dir_mode'] = 02770; //(*)

 

$sugar_config['default_permissions']['file_mode'] = 0660; //(*)

 

(*) use octal notation, so these integer values look like 1528 and 432 respectively.

 

You can see for directories that setgid is enabled then, by default, you will ensure new files created in that directory inherit the directory's group instead of the user's default group.

 

You can see that the default permissions are 0660 for files. This ensures that files are readable by the Apache (or web) group.

 

There is a catch for files created outside of sugar_file_* functions. Those will use the system umask which is often set to 0022. In this case, by changing the umask for web server user to 0002 will result in a file permission that matches the Sugar application default (0660).

 

Sugar Cron user

 

Another important check is to see whether the user which is used to run Sugar cron is properly set up. When running cron, there is always a chance that some changes are written to the file system.  For example, part of the cache may need to be rebuilt as part of a scheduled task. If you schedule to run cron.php as root user then any files created during that process will be owned by root instead of the web server user which can cause a lot of headaches when the web server tries to access these files.

 

In Summary

 

The proper setup of users and groups is an essential server administration skill. In combination with the possibility of having extended attributes, the permission configuration in $sugar_config, and ability to use setgid on directories you should be able to perform any complex setup to meet security requirements.

Sidecar and Backbone.js

 

The Sidecar user interface framework is built on a variety of browser side technologies.  Being proficient in these underlying technologies is important for any developer writing Sugar 7 user interface code.

 

They key JavaScript component that pulls Sidecar together is Backbone.js. Backbone provides the underlying structure to Sidecar as well as providing a rich set of base features and APIs that are heavily used throughout the Sugar 7 application.

Sugar 7.6.x uses Backbone 0.9.10.

 

If you've ever created a Sugar Dashlet or any other user interface component in Sugar 7 then you will familiar with Backbone concepts such as customizing a View or working with a Model. However, many loosely coupled customizations or integrations with Sugar 7 user interface are possible through the use of Backbone Events.

 

For server side code, recall that you can use Logic Hooks to trap a Module's save events instead of overriding a module's SugarBean.  The same pattern can be applied where instead of overriding a core file, you can listen to essential events and take action as they occur.

 

We will explore more below.  The code from this example is also available on Sugar Integration Building Blocks project in Github.

 

Backbone Events

 

The Backbone.Events module is a lightweight pub-sub pattern that gets mixed in to each Backbone class (Model, View, Collection, Router, etc). This means you can listen to or dispatch custom named events from any Backbone object.

 

Backbone Events should not be confused with jQuery Events which is an API for working with DOM events. Backbone supports an events hash on Views that can be used to attach event handlers to DOM using jQuery. These are not Backbone Events. This can be confusing since both interfaces include an on() function, allow you to attach an event handler, and other similarities.

The target for jQuery events are DOM elements.  The target for Backbone Events are Backbone objects.

 

Sidecar classes all extend these base Backbone classes.  So each Sidecar object (Layouts, Views, Fields, Beans, Contexts, etc.) supports Events.

 

Existing Backbone Event Catalog

 

All of the existing catalog of Backbone Events are supported and triggered by the Sugar application.

 

For example, we can listen to built-in Backbone Router events, such as the route event, that are triggered by Sidecar.  Try running the following JavaScript code within your browser's console.

SUGAR.App.router.on('route', function(){console.log(arguments);});

 

As you click through the Sugar application, each time the router is called you will see routing events appear in your browser console.

 



 

Example Sidecar Events

 

In addition to existing built-in Backbone Events, the Sidecar framework makes use of a variety of unique events.  We will show examples of some events that are particularly useful for customization purposes.

Not all Sidecar Events are documented below.  If you are interested, explore further by downloading the Sidecar Dev Tools and use the Application Stream to monitor many Sidecar Events as they are triggered.

 

Application (Global) Events

 

Application events are all triggered on app.events (SUGAR.App.events) object. For example, if you wanted to see all global application events printed in your browser console then you could use the following code.

SUGAR.App.events.on('all', function(){console.log(arguments)});

 

For example,app:sync:complete

 

This is a very useful application event to know about. This event is triggered after login and the series of initial synchronization operations is completed.

 

This is earliest point of the application lifecycle where all metadata, view definitions, Handlebars templates, etc, are available to JavaScript code. So this is a good jumping off point for custom code.

 

Bean Events

 

Some events are triggered only on Bean objects.

 

For example,validation:complete

 

Validation tasks are run against a Bean prior to saving a Bean object back to server.  If validation passed, then this event will pass TRUE to listeners. If validation failed, then this event will pass FALSE to listeners.

 

Context Events

 

The Context object is often used to facilitate communication between different Sidecar components on the page using Events.

 

For example,button:save_button:click

 

This event is triggered whenever a Save button is clicked.  The Record View uses this event to run save routines without being tightly coupled to a particular save button.

 

Adding a new Record View button

 

Here is a demonstration of how you can use Events as an alternative to overriding Sidecar controllers. This approach is more upgrade and customization friendly than overriding a core application file.

 

The following steps will create a new custom button on the Accounts module's Record View and wire it to a JavaScript callback function.

 



 

Step 1: Insert Button Metadata

 

We need to add Button metadata to the existing Accounts view using a Sidecar Extension.  This defines the Sidecar Event to be triggered as well as the target object for the event.custom/Extension/modules/Accounts/Ext/clients/base/views/record/custom_button.php

 

custom_button.php

<?php
/**
* Copyright 2015 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.
*/
//Insert our custom button definition into existing Buttons array before the sidebar toggle button
array_splice($viewdefs['Accounts']['base']['view']['record']['buttons'], -1, 0, array(
array(
'name' => 'custom_button',
'type' => 'button',
'label' => 'My Custom Button',
'css_class' => 'btn-link',
//Set target object for Sidecar Event. 
//By default, button events are triggered on current Context but can optionally set target to 'view' or 'layout'
//'target' => 'context'
'events' => array(
// custom Sidecar Event to trigger on click.  Event name can be anything you want.
'click' => 'button:custom_button:click',
        )
    ),
));


 

Step 2: Add Event handler JS using JSGroupings

 

We can add event handling JavaScript into page using a JSGroupings Extension. This is designed to attach a callback function to the appropriate Context object when the application is on the Account module's Record view.custom/Extension/application/Ext/JSGroupings/addCustomButtonJS.php

 

 

 

addCustomButtonJS.php

<?php
/**
* Copyright 2015 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.
*/
//Loop through the groupings to find grouping file you want to append to
foreach ($js_groupings as $key => $groupings)
{
foreach  ($groupings as $file => $target)
    {
//if the target grouping is found
if ($target == 'include/javascript/sugar_grp7.min.js')
        {
//append the custom JavaScript file to existing grouping
$js_groupings[$key]['custom/modules/Accounts/myCustomButton.js'] = 'include/javascript/sugar_grp7.min.js';
        }

break;
    }
}

myCustomButton.js
(function(app){
/**
* Copyright 2015 SugarCRM Inc.  Licensed by SugarCRM under the Apache 2.0 license.
*/
//Run callback when Sidecar metadata is fully initialized
app.events.on('app:sync:complete', function(){

//When a record layout is loaded...
app.router.on('route:record', function(module){
//AND the module is Accounts...
if(module === 'Accounts') {
//AND the 'button:custom_button:click' event occurs on the current Context
app.controller.context.on('button:custom_button:click', function(model){
console.log("Custom Button event triggered on: " + model.get("name"));
//Show an alert on screen
app.alert.show('custom-message-id', {
                        level: 'success',
                        messages: 'It worked!',
                        autoClose: true
                    });
                });
//No off() needed.  See note later in blog post.
            }
        });

    });
})(SUGAR.App);

 

 

 

Step 3: Quick Repair and Rebuild

 

You then need to run Quick Repair and Rebuild in order to build your new extensions.  You will also need to do a hard refresh of the browser page in order to load the updated JavaScript files.

 



 

 

 

Sidecar Event Management

 

As with any single page application, it is important to include memory management considerations when you are coding your solutions. Event handlers can be a common source of memory leaks in JavaScript applications since they can prevent the objects they are attached to from being garbage collected. You do not want to keep old Sidecar Views, Layouts, etc, in memory long after they should have been removed.

 

Here are a couple tips.For global objects, make sure your event listener is attached only once. Make sure you understand the lifecycle of the objects you are working with.  Do not guess.Events get detached from Sidecar created objects. The Context object and any Layouts, Views, Fields that are created by Sidecar are disposed of whenever a new layout is loaded via Sidecar's built-in controller.  This process detaches any listeners attached on these objects.  This is why it was not necessary for us to remove the Context listener in the example above.If you created it, then you need to clean it up.  If you have JavaScript code that calls app.view.create* then you are responsible for disposing of it properly.  Calling dispose() on your own components when you are finished with them will remove event listeners as well as detach it from the DOM, etc.  Otherwise the view, your event listeners, and anything else that is attached could stay in memory forever.Use Backbone's listenTo() and stopListening() functions where possible.  They are designed to make automatic management of Events easier.

Matt Marum

CSRF Tokens in Sugar 7.7

Posted by Matt Marum Employee Dec 1, 2015

What is a Cross Site Request Forgery (CSRF)?

 

A CSRF is a type of exploit that a malicious website or attacker could employ to have a user send unauthorized commands to a website or application.  It is a type of confused deputy attack against a user's web browser that tricks it to send malicious HTTP requests to a target website.

 

Some CSRF techniques are trivial to employ.  For example, it is possible to place an arbitrary URL within an HTML IMG tag which will convince your browser to run an HTTP GET against that URL.

 

Try out this example that uses RequestBin.  I added an image tag to a page in my local web setup.

<img src="http://requestb.in/vzwvagvz">

 

When I checked RequestBin then I could see what the request from my browser looked like to the external service.

 



 

A malicious HTTP GET can potentially expose sensitive information.  For HTTP GET requests, the state of the system rarely changes meaning that lasting damage can be limited.  What can be more troubling is when a browser is tricked into performing an HTTP POST using a maliciously designed HTML form.

 

CSRF Authenticator in Sugar 7.7

 

Here is some information from Jelle Vink (Security Architect) on the CSRF Authenticator added in Sugar 7.7.  It is used primarily with Sugar 6.x based user interfaces (BWC modules) that include regular web forms since these are potential CSRF attack vectors. As of this writing, the Sugar 7.7 release is in beta.

 

Note that this is an early implementation and subject to change in future releases and therefore it is currently opt-in only for Sugar 7.7.  But the CSRF Authenticator will be enabled by default in a later Sugar release.

CSRF Authenticator is not enabled by default in Sugar 7.7 but this will change in a later Sugar release!

 

This will affect the behavior of customizations made to BWC modules that generate HTML that includes web forms.  There are actions that need to be taken to have these custom forms support CSRF authentication.

 

Enabling the CSRF Authenticator

 

To opt-in and enable this feature then use this directive in config_override.php:

$sugar_config['csrf']['opt_in'] = true;

 

How it works

 

We have added CSRF tokens to each web form that the Sugar application generates.  If the correct token is not included during a form submit then the POST request will be rejected.

 

The Sugar 7.7 implementation ties the CSRF token used in BWC forms to the user's PHP session.

 

The SugarController class is used to determine if it is a modify action. When the SugarApplication class detects a modify action, the CSRF authentication logic in SugarController will be called for all POST requests.

 

For more details, see the SugarApplication and SugarController classes in the Sugar 7.7 codebase.

 

The following configuration parameters are available:

 

Soft Failure Mode

$sugar_config['csrf']['soft_fail_form'] = true/false

 

This config setting disables CSRF authentication and is only present to mitigate any upgrade issues where customizations are missing the necessary CSRF token inclusion.Using this settings is not recommended in a production environment! When soft failure is enabled then Sugar will merely log missing CSRF tokens or mismatches.

 

Token Size

$sugar_config['csrf']['token_size']

 

The size of the tokens (in characters) being generated.  This value defaults to 32 characters.

 

Form Token Field

$sugar_config['csrf']['form_token_field']

 

This is the form field used to transport the token value.  It defaults to 'csrf'.

 

Using the CSRF Authenticator

The CSRF Authenticator will be enabled by default in a future Sugar version. Developers should act now to make sure they are ready.

 

Sugar Developers can enable CSRF authentication in Sugar 7.7 instances in their local development environment.config_override.php

$sugar_config['csrf']['opt_in'] = true;

 

Then you will see FATAL errors in the Sugar log when users use forms that do not have CSRF tokens added to them properly.sugarcrm.log

Wed Jul  1 06:47:46 2015 [710][1][FATAL] CSRF: attack vector detected, invalid form token detected

 

Wed Jul  1 06:47:46 2015 [710][1][FATAL] CSRF: auth failure for Users -> Save

 

Sugar Developers should add the following Smarty tag to their custom forms used with BWC modules.

{sugar_csrf_form_token}

 

For example,customform.tpl

<form name='myCustomForm' action="index.php" method="POST">

 

  {sugar_csrf_form_token}

 

  <input type='hidden' name='id' value='{$id}'>

 

  <input type='hidden' name='module' value='{$module}'>

 

  ...

 

</form>