Based on the situation you describe, you seem to be yet another victim of the remote administration security block introduced by SP2010 and still active by default in the 2013 version.
Strictly speaking, the block was developed to force security when managing SPPersistedObject.
Taken from Ms knowledgbase: "This feature explicitly blocks any modifications to the objects inheriting from SPPersistedObject in the Microsoft.SharePoint.Administration namespace and does not allow the content web applications to update the configuration database"
This roughly translates to - if you try to make an update that touches an SPPersistedObject from a web-site collection scopes you will be blocked with a generic Access Denied error even if you should be able to perform the action because you are running under farm admin account.
To confirm this is actually your case, you can try to disable the
RemoteAdministratorAccessDenied property and see if this change enables your code to run.
[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint”) > $null
[System.Reflection.Assembly]::LoadWithPartialName(“Microsoft.SharePoint.Administration”) > $null
$contentService = [Microsoft.SharePoint.Administration.SPWebService]::ContentService
$contentService.RemoteAdministratorAccessDenied = $false
The above PowerShell script (taken from here for sake of simplicity) will turn of the aforementioned security setting and enable you to perform the test (remember to reset the property to the original value afterwards!).
There is a problem though: if you are indeed a victim of this security setting, then the only solution that comes to mind is disabling the security check altogether. As you may expect, this isn't exactly a desirable solution. For that reason, should the test I suggest above confirm that you are indeed seeing the result of what I describe, before considering disabling the setting I strongly suggest that you consider reworking your solution so that you won't need to perform the offending operation.