Verify if user has at least one of required roles to be able to update a record owned by a certain user
try
{
    PoolId = new Guid(GetAllNodes("ownerconfig")[0].Attributes["value"].InnerText);
    GetAllNodes("roles")[0].Attributes["value"].InnerText.Split(';').ToList().ForEach(x =&gt; allowedRoles.Add(new Guid(x)));
}
catch (Exception ex)
{
    throw new InvalidPluginExecutionException(string.Format("Error deserializing plugin step XML config: {0}", ex.Message));
}



This is really bad. You are hiding the original exception. If you don't want to pass it as an inner exception at least do ex.ToString() to be able to see the stack-trace later if necessary.

As a matter of fact this try/catch could be a separate method that gets the PoolId from the xml you could then just return the PoolId without the helper variable outside this try/catch block.




if (xrmObjects.PluginContext.MessageName.ToLower() == "update" &amp;&amp; xrmObjects.PluginContext.PreEntityImages.Contains("entity")) {



Make the method return if the condition is false to reduce nesting.




if (PoolId == Guid.Empty || allowedRoles.Count == 0)
   return;



and


if (!userRoles.Any(x =&gt; allowedRoles.Any(y =&gt; y == x.RoleId.Value)))
   throw new InvalidPluginExecutionException(...)



I suggest you always use curly braces {}. It can prevent a lot of errors.




if (((EntityReference)entity["ownerid"]).Id == PoolId)



Same here, return if false.




using (XrmServiceContext ctx = new XrmServiceContext(xrmObjects.Service))



and


var userRoles = 



Be consistant. Use either var or types everywhere.




var userRoles = ctx.SystemUserRolesSet.Where(x =&gt; x.SystemUserId == xrmObjects.PluginContext.InitiatingUserId).ToList();

//check if current user has one of required roles
if (!userRoles.Any(x =&gt; allowedRoles.Any(y =&gt; y == x.RoleId.Value)))



You can merge it into:

var userHasRequiredRole = 
    ctx.SystemUserRolesSet
    .Where(x =&gt; x.SystemUserId == xrmObjects.PluginContext.InitiatingUserId)
    .Any(x =&gt; allowedRoles.Any(y =&gt; y == x.RoleId.Value));


so you can remove the comment and simply write:

if (!userHasRequiredRole) { throw... }


or even shorter:

var userHasRequiredRole = 
    ctx.SystemUserRolesSet
    .Any(x =&gt; 
        x.SystemUserId == xrmObjects.PluginContext.InitiatingUserId &amp;&amp;
        allowedRoles.Any(y =&gt; y == x.RoleId.Value));


although personally I'd use the Where+Any, it looks cleaner