best practices


Background Primer:

Logging. As developers we all need to do this, especially for deployments where it’s entirely unreasonable to ask our end clients to use / maintain / notify us of crash events, and even if they did it gives us a needle’s-eye view of the problem. So while interim development usually starts off with good ole trace it’s potential for releasing sensitive data into the stream is greatly amplified by either the type of application you are writing and it’s complexity. Just having a debugger running, we’ve all seen every one else’s trace statements.

Security:

So AIR helps take the LogLogger from the SDK and gives us the potential to write log files, typically in the application storage area. While this can and does help the alpha and beta stages of release to end-clients it significantly increases their exposure of sensitive data because now you are writing it in area where only the user needs privilege – not admin.

The Better Approach:

Because we want to use the ILogger interface along with standard LogEvents (because Targets use these), the LogLogger is easy enough to re-write. With each message being ultimately broadcast in the event – this is the most appropriate domain to intercept, scramble, and resend. I started with each defined interface method and before each dispatch, a new method is used to build/construct the message. With the help of an implementation of a secure logger (composition goes a long way to help swap parts out instead of inheritance), this class is tasked with doing the actual work of rewriting or removing selected properties from objects we need to keep secure.

The Implementation:

The key with the build method is not only to introspect top level objects as part the …rest parameters, but also to see if anything is an array and to iterate that list to make sure the class type is or isn’t the type that needs to be secured. Any object which needs to be secured is then sent through the secure logger, otherwise a straight obj.toString() is used.

 

LogLogger

public class LogLogger extends EventDispatcher implements ILogger
{

private var _secureLogger:SecureLogger;
private var _category:String;
private var resourceManager:IResourceManager = ResourceManager.getInstance();

public function LogLogger(category:String)
{
super();
_category = category;
}

public function get category():String { return _category; }

public function log(level:int, msg:String, … rest):void
{
if (!hasEventListener(LogEvent.LOG)) return;
msg = build(msg, rest);
dispatchEvent(new LogEvent(msg, level));
}

public function debug(msg:String, … rest):void
{
if (!hasEventListener(LogEvent.LOG)) return;
msg = build(msg, rest);
dispatchEvent(new LogEvent(msg, LogEventLevel.DEBUG));
}

public function error(msg:String, … rest):void
{
if (!hasEventListener(LogEvent.LOG)) return;
msg = build(msg, rest);
dispatchEvent(new LogEvent(msg, LogEventLevel.ERROR));
}

public function fatal(msg:String, … rest):void
{
if (!hasEventListener(LogEvent.LOG)) return;
msg = build(msg, rest);
dispatchEvent(new LogEvent(msg, LogEventLevel.FATAL));
}

public function info(msg:String, … rest):void
{
if (!hasEventListener(LogEvent.LOG)) return;
msg = build(msg, rest);
dispatchEvent(new LogEvent(msg, LogEventLevel.INFO));
}

public function warn(msg:String, … rest):void
{
if (!hasEventListener(LogEvent.LOG)) return;
msg = build(msg, rest);
dispatchEvent(new LogEvent(msg, LogEventLevel.WARN));
}

private function get secureLogger():SecureLogger { return _secureLogger ||= new SecureLogger(); }

private function build(msg:String, params:Array):String
{
var repl:String =”;
for (var i:int = 0; i < params.length; i++)
{
var obj:Object = params[i];
if (!obj) repl = ‘null’;
else if (secureLogger.hasReplacementRule(obj))
{
if (obj is Array)
{
var n:int = (obj as Array).length;
for (var j:int = 0; j < n; j++)
{
var child:Object = obj[j];
repl += secureLogger.getReplacement(child);
}
}
else repl = secureLogger.getReplacement(obj);
}
else repl = obj.toString();

msg = msg.replace(new RegExp(“\\{“+i+”\\}”, “g”), repl);
}
return msg;
}
}

SecureLogger

public class SecureLogger
{
public function SecureLogger()  { super(); }

public function hasReplacementRule(obj:Object):Boolean
{
if (validateReplacementRule(obj)) return true;
if (obj is Array)
{
for each (var child:Object in obj)
{
if (validateReplacementRule(child)) return true;
}
}
return false;
}

private function validateReplacementRule(obj:Object):Boolean
{
if (obj is Account) return true;
if (obj is LoginCredentials) return true;
return false;
}

public function getReplacement(obj:Object):String
{
var str:String;
if (obj is Account) str = secureAccount(Account(obj));
else if (obj is LoginCredentials) str = ‘[LoginCredentials]‘;
else str = obj.toString(); return str;
}

//An example of using regex to re-write sensitive data
//Since it’s working with direct string manipulation, it must know about it’s format
private function secureAccount(obj:Account):String
{
var str:String = obj.toString();
str = str.replace(/number=\d+/, ‘number=’+ obj.id +’ ‘);
str = str.replace(/name=.*?(?=type)/, ‘name=Account ‘+ obj.id +’ ‘);
str = str.replace(/institutionName=.*?(?=institutionWebsite)/, ‘institutionName= Institution ‘+ obj.id +’ ‘);
str = str.replace(/institutionWebsite=.*?(?=status)/, ‘institutionWebsite= ‘); return str;
}

}

As Flex Architects / Team Leads can attest (at least those of us who do the proper preparation for a project), choosing an architecture to base your code upon isn’t an easy task since many good ones are out there, however each is like a relationship that leaves just a little off the table to be truly a desirable solution. However as with any framework worth it’s work, most of them are highly extensible without the need to modify the original to achieve the characteristics you need / want.

RobotLegs: Mediating sub-content to a Spark NavigatorContent pane.
Turns out there is a ‘bug’ and/or limitation when using the spark-based layout framework, and thankfully it’s a relatively easy one to over come. It has to do with the <s:NavigatorContent /> and how those children are built according to it’s creationPolicy as set by an appropriate container (TabNavigator, Accordion, and so on). Because the mediator is triggered on the FlexEvent.CREATION_COMPLETE event, it doesn’t take into consideration that while additional containers will be put on the stage, their containing children will not be instantiated since it’s part of the deferred process. This leaves the mediator in ‘limbo’ land since we obviously want to setup the user gestures for all the guts of the container (combos, buttons, data grids, etc). (more…)

There is probably only a handful of things that are probably less understood at the SDK level as to how just exactly the Drag-Drop event sequence is generated, captured, and handled. First off, the UIComponent is the one where events can be registered but does absolutely nothing about dispatching or even ‘psuedo-dispatching’ through an intermediary.

 

Not In Here:

Case is point – we all know about the DragManager, and how you have to enable certain targets to allow the capture sequence to generate events for the final drop event, however it’s really the SystemManager that handles a bunch of marshalling for you – since it sits at the near root level it knows about MouseEvents for just about every object.

It’s this ferrying back and forth between the InterManagerRequest.DRAG_MANAGER_REQUEST event between the DragManager and ultimately passed through the Implementor (ie DragManagerImpl), and the SystemManager, is what creates the DragEvent to eventually be fired via the DragProxy. This is why the documentation says it is important to trigger the allowDragDrop method from within the DragEvent.ENTER event – because the target is then assigned directly to the proxy instance.

(more…)

Highly flexible applications and highly secure applications are usually at the opposite ends of the spectrum and require some sort of constant balance. So how do you mitigate your security risks when you need to build an application that is dependent on running modules at runtime via some sort of configuration?

ApplicationDomain.currentDomain is the just about the worst thing you can do when trying to build a secure application.

The problem:
Your modules are loaded at runtime which need to interface internal code you’ve written in your main application. This means the ModuleLoader needs to then set the currentDomain to ApplicationDomain.currentDomain. However ideally the module loader needs to be able to distinguish levels of trust if it’s a module you (or trusted developer) have written, or a rogue module.

The ugly issue:
When using a blanket statement to allow all modules to load with the currentDomain, you are giving every loaded swf trusted access to your entire platform. Some cases, this isn’t a big deal. It becomes a nasty headache if you’re building an e-comm solution. It will allow man-in-the-middle attacks to allow someone to load their module, and using any number of methods for decompiling and introspection to figure out what class and methods are used to capture and/or listen to events for sensitive information like user info and payment tokens. Their swf only needs to add itself as an IEventDispatcher or through the document tree to add itself to the sensitive classes and wait for these methods to be triggered.

The solutions:
There are several different ways to help combat this problem, however some are better than others. Any solution pretty much involves using 2 ModuleLoader’s. One for secure / trusted, another for insecure untrusted. Always start the loading process from the insecure, then based on which method you choose -transfer the loaded swf to the untrusted ModuleLoader via addChild(), swapChild(), etc.

  1. Use a trusted Interface in your platform that is always loaded at the application layer. However this is the weakest of them all since this only provides a minimal level of security as it can still be broken. The most flexible Modules use -load-externs as a compiler command to allow most of the dependent classes to be front loaded to the application. This makes things a bit speedier especially when loading several modules that share an entire platform. By using an internal interface you can check at the ModuleLoader level if the loading module has sufficient trust to be given access. This works in theory since the Flash AVM will not replace a duplicate namespace collision, but can still be defeated since I can write a rogue module and duplicate the secure interface using the exact same package.
  2. Use server side methods to generate hash key’s in the configuration which matches the particular node of the module in question. NEVER use this method in conjunction with deciphering the hash key internally, it’s way too easy to figure out what’s going on in your code. Instead pass this hash key back to the server, ask it to validate it against the file name and it’s own interally identifiable metrics (eg file size, mod date, etc) to then pass back a Boolean pass/fail for trust. Based on this service, then assign which domain it can be loaded into.
  3. Use a domain trust method in a static and final class to determine if the source of the module’s URL is coming from a place that is trusted. This basically means using RegEx along with hardcoded strings to determine if the URL is from ‘mydomain.com’. While this can be a bit laborious since it might require constant care to edit the domains that are trusted, however this particular solution isn’t as easily defeated since the list of trusted domains are embedded in your application.

The problem domain: An issue exists where in a modular application you want to be able to share events from different modules without creating a dependency between the two. Deeply nested objects make this even more apparent when you realize you can’t use bubbling since they don’t reside within the same branch line down to the root trunk.

(more…)

http://help.adobe.com/en_US/AS3LCR/Flash_10.0/flash/sampler/package-detail.html

It’s interesting to see, not necessarily from a backward compatibility model, but interesting none the less for those of us who are leading enterprise applications which are still stuck at “lowest common denomenator” just due to their tremendous size and expected reach.

I can certainly see how many applications can expect to reach a better performance vs cost (engineering man hours, legacy patch costs, etc) ratio for their intensive parts which either have the best chance for memory or cpu utilization management. Lets face it, none of our applications can be so brazen to run on a Cray with unlimited resources (although it sure as hell would be a lot easier on reducing Engineering constraints or getting “Pixel Nazi’s” off our backs).

This one crept on me and while I thought I was on the right track it wasn’t until I came across a tech-note on Adobe’s site that finally led me down the right path which incidentally I only found by accident. The main issue was a SecurityViolation Error which is common place in dealing with accessing data in different domains. Usually we all know about this, and is fixed in implementing the correct subdomain accessor in the crossdomain.xml however even after it was deployed the app was still throwing this error, which made me now think the wildcard initiator doesn’t work as intended.

It turns out that not only does your crossdomain need to have the allow access from node, if the page and requested data use different protocols that a secure attribute must be added.

When your application is in HTTP and you want HTTPS data use:

allow-access-from domain=”*.mydomain.com” secure=”false”

WHen your application is in HTTPS and you want HTTP data use:

allow-access-from domain=”*.mydomain.com” secure=”true”

There are times when it becomes important that we step back from our work to really understand when / where / how patterns are applied. However, where I think many of us fall short, is more importantly is when NOT to.

Like any great pattern that is meant to simplify and organize, they can abused and overused. Remember, a pattern is really nothing more than a general solution to a particular problem set that has been previously solved. So for many cases, this is a godsend, because it means less time can be spent on the implementation and more time can be spent on the UI, aesthetics, and over all product improvements. (more…)

Depending on your specific responsibilities, in most cases, most of us programmers do not have to hash out the ideas of what becomes an effective design or work flow in the project or product of what we work on. Thankfully. However, if it is, then the following becomes a lot more common: where Engineering will say to Marketing, this idea just isn’t going to work and we’ll need another 2 weeks further from our already tight deadline. OK so I’m not dealing with any sort of hard deadline other than just wanting to have some sort of completion to the first stage, I did have to go back and come up with ‘a better way to use things.’ Notice I didn’t say ‘do things.’ (more…)

Flex 2 Development Guide (PDF): Styles : Pg 742

This one I know gets missed.A LOT. The key here is if you want set styles dynamically where it’s dependent upon conditions or states, the key is not to use the creationComplete event instead use preinitialize. This becomes even more true if the styles you set are on components that are either at or near the root level of the application tree.

Now for the majority of the application that only needs to be styled at startup, the best approach is similar to the way most Web Designers / Web Developers take the approach of style sheets: external or otherwise. Now if you use external css like I do, and your intent is to allow others either recompile your source (developers, enhancers) or dynamically pull from a well-known style sheet (application users), be nice and not only organize it but add comments as well where needed.

A common mistake that impacts performance is overusing or unnecessarily using the setStyle() method. In general, you only need the setStyle() method when you want to change styles on existing objects. Do not use it when setting up styles for an object for the first time. Instead, set styles in an

block, through an external CSS style sheet, or as global styles. It is important to initialize your objects with the correct style information, if you do not expect these styles to change while your program executes (whether it is your application, a new view in a navigator container, or a dynamically created component). Some applications must call the setStyle() method during the application or object instantiation. If this is the case, call the setStyle() method early in the instantiation phase. Early in the instantiation phase means setting styles from the component or application’s preinitialize event, instead of the creationComplete or other event. By setting the styles as early as possible during initialization, you avoid unnecessary style notification and lookup. For more information about the component startup life cycle, see Chapter 6, “Improving Startup Performance,” in Building and Deploying Flex 2 Applications.

Next Page »