Thursday, March 15, 2012

Security For Developers - Part II - Code Access Security

 

As promised, this is the second portion on Security for Developers. If you missed the first part of this series, you can get it HERE.

Today we are going to learn about code access security in Microsoft Dynamics AX 2012. And to start I would like to talk about a little bit about code access security in C#.

In C# (.NET) as well as in AX 2012, we work with security demands. And what is a security demand?

We can probably figure that demands are used to ensure that every caller who calls your code (directly or indirectly) has been granted the demanded permission.

 In a regular environment this happens when demanded for permission; the runtime's security system walks the call stack, by comparing the granted permissions of each caller to the permission being demanded. At this point, like in any high security building in New York City, if any caller in the call stack is found without the demanded permission then a SecurityException is thrown.  In the case of a New York City building, you will be thrown out of the building. Simple ah?

 Well, the same type of process exists in AX 2012 as AX 2012 Code Access Security is used by developers to protect Secured APIs from being invoked by un-trusted code (code that does not originate from the AOT). Code access security does this by verifying the following:

  1. The code asserted the appropriate permission on the call stack to use the secured class.
  2. The assert (the request to use the secured class) is executed in trusted code and saved in the AOT.
  3. The assert is executed on the same tier as the secured class.
In addition, Code Access Security covers the use of secured classes on the server tier only and we don’t need to modify client callas of secured classes, which is cool and scalable.

So here is how this works:
  1. Code Access Security must be implemented by the secured class owner and all consumers of the secured class.
  2. The owner secures the secured class by implementing a specific type of permission class and calling the demand()  (remember the C# demands above?) method on that class.
  3. Each class consumer must explicitly request permission to invoke a secured class by calling the assert() method on the permission class.  (this is where the permissions are compared)
  4. Application code will break unless both of these steps are completed. (This is similar to the  SecurityException in .NET)

NOTE: Code Access Security does not guarantee the validity of any data or parameters passed to the secured class. Data validation is still the responsibility of the consumer. 

Now, in AX 2012, there are six groups of protected classes in AX 2012 Code Access Security:
  • Direct SQL
  • Run-time compilation and execution of X++
  • Data-controlled execution of X++
  • File handling
  • Win32 Interop
  • Windows API
The follow first code shows how to consume the TextBuffer class. So, we first need to create a new FileIOPermission object, then pass the file name as a parameter, and then we call the assert() method. The second example shows how to call a CAS-enabled API.

server void MyServerFunction()
{

  // Declare the code access security permission object.
  FileIOPermission fileIOPermission;
  TextBuffer txtb = new TextBuffer();
  Filename filename ="c:\\temp\\myfile.txt";

  // Assert that it is okay to read and write files
  fileIOPermission = new   FileIOPermission(filename, 'rw');
  fileIOPermission.assert();


  // From file will demand CAS permission (read)
  txtb.fromFile(filename); // Read text from file

  // To clipboard will demand CAS permission (write)
  txtb.toClipboard(); // Copy it to the clipboard

  // To file will demand CAS permission (write)
  txtb.toFile(filename); // Write text to file
}



server void callCASEnabledAPI()
{

    DictClass dictClass;
    anytype   retVal;
    str       resultOutput;

    // Variable for the permission class.
    ExecutePermission perm;
    ;


    perm = new ExecutePermission();

    // Grants permission to execute the DictClass.callObject method.
    // DictClass.callObject is protected by code access security.

    perm.assert();
    dictClass = new DictClass(classidget(infolog));

    if (dictClass != null)

    {
        retVal       = dictClass.callObject("toString", infolog);
        resultOutput = strfmt("Return value of is %1", retVal);
        print resultOutput;
        pause;
   }

                // Closes the code access permission scope.
                CodeAccessPermission::revertAssert();
}


In the above example, if permission to use the API is not asserted, the following error is generated:
Request for the permission of type '%1' failed.
 
The following, and sadly, the last example shows how to execute permissions to a direct SQL statement within X++.

static void getCustomersDirectSQL(Args _args)
{

  Connection   userConnection;
  Statement    stmt;
  str     sqlString;
  ;

  userConnection = new Connection();
  stmt = userConnection.createStatement();

  sqlString = 'select * from custTable';

  new SqlStatementExecutePermission(sqlString).assert();
  stmt.executeQuery(sqlString);
  CodeAccessPermission::revertAssert();

}


It is important to remember that these tools are critical when developing our modifications to the system (AX 2012). Now that AX 2012 X++ language is compiled in the IL, we need to take advantage of the .NET CLR code access security when integration internal/external applications with AX 2012.

I hope you enjoyed reading this post and stay tune for my last post of this series about display methods authorizations in AX 2012.

Have a great and safe weekend!


No comments:

Post a Comment

Thank you for your thoughts. Your comment will appear in my blog shortly after review.

Have a great day!