Note: This article is a proof of concept only and caution should be taken when implementing the Cloud Application Administrator role in a production environment especially on an external Azure AD account. Unless Azure AD Premium is subscribed, in which the custom policies can be created, giving a user the Cloud Application Administrator will allow the user viewing access to the current AD account.
Recently, I was required to add an external Azure AD user to an exisiting Subscription, and allow the user to deploy an Azure Function App via the Serverless Framework
The user was initially given the “Owner” role to the Subscription
In addition he was also given “Owner” to the Resource Group under the Subscription he was working in.
When the user tried to deploy the function, this was the response returned
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
$ serverless deploy Serverless: Load command config Serverless: Load command config:credentials Serverless: Load command create Serverless: Load command install Serverless: Load command package Serverless: Load command deploy Serverless: Load command deploy:function Serverless: Load command deploy:list Serverless: Load command deploy:list:functions Serverless: Load command invoke Serverless: Load command invoke:local Serverless: Load command info Serverless: Load command logs Serverless: Load command login Serverless: Load command logout Serverless: Load command metrics Serverless: Load command print Serverless: Load command remove Serverless: Load command rollback Serverless: Load command rollback:function Serverless: Load command slstats Serverless: Load command plugin Serverless: Load command plugin Serverless: Load command plugin:install Serverless: Load command plugin Serverless: Load command plugin:uninstall Serverless: Load command plugin Serverless: Load command plugin:list Serverless: Load command plugin Serverless: Load command plugin:search Serverless: Load command config Serverless: Load command config:credentials Serverless: Invoke deploy Serverless: Invoke package Serverless: Building Azure Events Hooks Serverless: Parsing Azure Functions Bindings.json... Serverless: Building binding for function: app event: httpTrigger Serverless: Building binding for function: app event: http Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Logging in to Azure Serverless: Open a browser to https://aka.ms/devicelogin and provide the following code (which is copied to your clipboard!) to complete the login process: HEMDDPHQ8 Error -------------------------------------------------- Insufficient privileges to complete the operation. For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable. Stack Trace -------------------------------------------- Error: Insufficient privileges to complete the operation. at client.pipeline (/Users/gerald/git/function-app-test/node_modules/azure-graph/lib/operations/applications.js:147:19) at retryCallback (/Users/gerald/git/function-app-test/node_modules/ms-rest/lib/filters/systemErrorRetryPolicyFilter.js:89:9) at retryCallback (/Users/gerald/git/function-app-test/node_modules/ms-rest/lib/filters/exponentialRetryPolicyFilter.js:140:9) at /Users/gerald/git/function-app-test/node_modules/ms-rest/lib/filters/rpRegistrationFilter.js:59:14 at handleRedirect (/Users/gerald/git/function-app-test/node_modules/ms-rest/lib/filters/redirectFilter.js:39:9) at /Users/gerald/git/function-app-test/node_modules/ms-rest/lib/filters/formDataFilter.js:23:14 at Request.defaultRequest [as _callback] (/Users/gerald/git/function-app-test/node_modules/ms-rest/lib/requestPipeline.js:125:16) at Request.self.callback (/Users/gerald/git/function-app-test/node_modules/ms-rest/node_modules/request/request.js:185:22) at Request.emit (events.js:182:13) at Request.EventEmitter.emit (domain.js:441:20) at Request.<anonymous> (/Users/gerald/git/function-app-test/node_modules/ms-rest/node_modules/request/request.js:1161:10) at Request.emit (events.js:187:15) at Request.EventEmitter.emit (domain.js:441:20) at IncomingMessage.<anonymous> (/Users/gerald/git/function-app-test/node_modules/ms-rest/node_modules/request/request.js:1083:12) at Object.onceWrapper (events.js:273:13) at IncomingMessage.emit (events.js:187:15) at IncomingMessage.EventEmitter.emit (domain.js:441:20) at endReadableNT (_stream_readable.js:1098:12) at process.internalTickCallback (internal/process/next_tick.js:72:19) From previous event: at PluginManager.invoke (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:391:22) at PluginManager.run (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:422:17) at variables.populateService.then.then (/usr/local/lib/node_modules/serverless/lib/Serverless.js:157:33) at processImmediate (timers.js:632:19) at process.topLevelDomainCallback (domain.js:120:23) From previous event: at Serverless.run (/usr/local/lib/node_modules/serverless/lib/Serverless.js:144:8) at serverless.init.then (/usr/local/lib/node_modules/serverless/bin/serverless:44:28) Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Issues: forum.serverless.com Your Environment Information ----------------------------- OS: darwin Node Version: 11.3.0 Serverless Version: 1.34.1 |
I proceeded to add the “Contributor” role to the Subscription, and a different message appeared.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
$ serverless deploy Serverless: Load command config Serverless: Load command config:credentials Serverless: Load command create Serverless: Load command install Serverless: Load command package Serverless: Load command deploy Serverless: Load command deploy:function Serverless: Load command deploy:list Serverless: Load command deploy:list:functions Serverless: Load command invoke Serverless: Load command invoke:local Serverless: Load command info Serverless: Load command logs Serverless: Load command login Serverless: Load command logout Serverless: Load command metrics Serverless: Load command print Serverless: Load command remove Serverless: Load command rollback Serverless: Load command rollback:function Serverless: Load command slstats Serverless: Load command plugin Serverless: Load command plugin Serverless: Load command plugin:install Serverless: Load command plugin Serverless: Load command plugin:uninstall Serverless: Load command plugin Serverless: Load command plugin:list Serverless: Load command plugin Serverless: Load command plugin:search Serverless: Load command config Serverless: Load command config:credentials Serverless: Invoke deploy Serverless: Invoke package Serverless: Building Azure Events Hooks Serverless: Parsing Azure Functions Bindings.json... Serverless: Building binding for function: app event: httpTrigger Serverless: Building binding for function: app event: http Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Logging in to Azure Serverless: Looking for deployed functions that are not part of the current deployment... Serverless: Creating resource group: function-app-test-adaptor-rg Serverless: Creating function app: function-app-test-adaptor Serverless: Waiting for Kudu endpoint... Serverless: Uploading function: app Serverless: Running Kudu command mv app/app-function.json app/function.json... Error -------------------------------------------------- Error executing command, try again later. For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable. Stack Trace -------------------------------------------- Error: Error executing command, try again later. at module.exports.logError (/usr/local/lib/node_modules/serverless/lib/classes/Error.js:92:11) at initializeErrorReporter.then.catch.e (/usr/local/lib/node_modules/serverless/bin/serverless:65:3) at processImmediate (timers.js:632:19) at process.topLevelDomainCallback (domain.js:120:23) From previous event: at /usr/local/lib/node_modules/serverless/bin/serverless:63:9 at Object.<anonymous> (/usr/local/lib/node_modules/serverless/bin/serverless:66:4) at Module._compile (internal/modules/cjs/loader.js:722:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10) at Module.load (internal/modules/cjs/loader.js:620:32) at tryModuleLoad (internal/modules/cjs/loader.js:560:12) at Function.Module._load (internal/modules/cjs/loader.js:552:3) at Function.Module.runMain (internal/modules/cjs/loader.js:775:12) at startup (internal/bootstrap/node.js:300:19) at bootstrapNodeJSCore (internal/bootstrap/node.js:826:3) Get Support -------------------------------------------- Docs: docs.serverless.com Bugs: github.com/serverless/serverless/issues Issues: forum.serverless.com Your Environment Information ----------------------------- OS: darwin Node Version: 11.3.0 Serverless Version: 1.34.1 |
In Azure AD in the Azure portal, I then came across the following Directory Roles
- Application administrator
- Application developer
- Cloud application administrator
I proceeded to add the “Cloud application administrator” role in the Azure AD and the Function App deployed successfully
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
$ serverless deploy Serverless: Load command config Serverless: Load command config:credentials Serverless: Load command create Serverless: Load command install Serverless: Load command package Serverless: Load command deploy Serverless: Load command deploy:function Serverless: Load command deploy:list Serverless: Load command deploy:list:functions Serverless: Load command invoke Serverless: Load command invoke:local Serverless: Load command info Serverless: Load command logs Serverless: Load command login Serverless: Load command logout Serverless: Load command metrics Serverless: Load command print Serverless: Load command remove Serverless: Load command rollback Serverless: Load command rollback:function Serverless: Load command slstats Serverless: Load command plugin Serverless: Load command plugin Serverless: Load command plugin:install Serverless: Load command plugin Serverless: Load command plugin:uninstall Serverless: Load command plugin Serverless: Load command plugin:list Serverless: Load command plugin Serverless: Load command plugin:search Serverless: Load command config Serverless: Load command config:credentials Serverless: Invoke deploy Serverless: Invoke package Serverless: Building Azure Events Hooks Serverless: Parsing Azure Functions Bindings.json... Serverless: Building binding for function: app event: httpTrigger Serverless: Building binding for function: app event: http Serverless: Packaging service... Serverless: Excluding development dependencies... Serverless: Logging in to Azure Serverless: Open a browser to https://aka.ms/devicelogin and provide the following code (which is copied to your clipboard!) to complete the login process: XXXXXXXXX Serverless: Creating resource group: function-app-test-adaptor-rg Serverless: Creating function app: function-app-test-adaptor Serverless: Waiting for Kudu endpoint... Serverless: Uploading function: app Serverless: Running Kudu command mv app/app-function.json app/function.json... Serverless: Syncing Triggers....Response statuscode: 200 Serverless: Successfully created Function App |
Some links that helped me along the way
Laurent says
Thank you for your article. Very instructive !
I did have the same error “Error executing command, try again later.” but what is strange is that I had it as a “Contributor”.
I got another error “The client ‘[email protected]’ with object id ‘XXX’ does not have authorization to perform action ‘Microsoft.Authorization/roleAssignments/write’ over scope ‘/subscriptions/XXX. I had it as a “Contributor” and “Resource access”.
You mentioned that these 3 roles can succeed to deploy:
– Application administrator
– Application developer
– Cloud application administrator
Are they the only ones ?
Best regards,
L.
gerald says
Hi Laurent
Good question! In my proof of concept, the “Cloud application administrator” role was sufficient to deploy the app. I would suggest you try this role out exclusively first as a starting point. Let me know how this goes