Update Azure Credential - Manually Using Azure CLI


As ParkMyCloud and Microsoft Azure add new features, you may be occasionally required to update the permissions needed for ParkMyCloud to access your cloud resources.  This page tells you how to update the Azure permissions for an existing ParkMyCloud account.  For these instructions, we are assuming you have already completed the instructions for the original creation of your Azure Cloud Credential.  If not, please refer to the page: Create Azure Credential - Manually Using Azure CLI

1. Identify the Cloud Credential to be updated

Login to the ParkMyCloud Console and go to the Azure Credential that needs to be updated.  For example:

We will be using the Subscription ID and App ID from this page in a later step.

2. Install Azure CLI

If you do not already have the Azure CLI installed, please follow the instructions at https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest to install the Azure Command Line Interface (CLI) on the platform of your choice.

3. Login to Azure

Login to the Azure account associated with the Cloud Credential shown in Step 1.  The following example shows the Azure CLI commands on the Linux platform - other platforms will follow the same commands.

az login -u some_user@youraccount.com

This will request your password and then, once you are logged in, may show your subscription information.

4. Get the Service Principal Object ID

We now need to get the object ID for the service account.  There are two ways to do this - one with the Azure CLI, and the other is with the Azure Console.

4a. Getting the Service Principal Object ID with the Azure CLI

To do this, we will need the "App ID" from the ParkMyCloud Console, shown in the example above as 937062cd-e5e4-467f-a2ea-29895313047.  Paste this value into the az ad sp show command as shown here:

az ad sp show --id 937062cd-e5e4-467f-a2ea-29895313047

This will result in something like the following:

{
    "accountEnabled": "True",
    "addIns": [],
    "alternativeNames": [],
    "appDisplayName": "ParkMyCloudAzure-Production-2018-12-14",
    "appId": "937062cd-e5e4-467f-a2ea-29895313047",
    "appOwnerTenantId": "59888888-8888-8888-8888-88888888888",
    "appRoleAssignmentRequired": false,
    "appRoles": [],
    "applicationTemplateId": null,
    "deletionTimestamp": null,
    "displayName": "ParkMyCloudAzure-Production-2018-12-14",
    "errorUrl": null,
    "homepage": "https://console.parkmycloud.com",
    "informationalUrls": {
        "marketing": null,
        "privacy": null,
        "support": null,
        "termsOfService": null
    },
    "keyCredentials": [],
    "logoutUrl": null,
    "notificationEmailAddresses": [],
    "oauth2Permissions": [{
        "adminConsentDescription": "Allow the application to access ParkMyCloudAzure-Production-2018-12-14 on behalf of the signed-in user.",
        "adminConsentDisplayName": "Access ParkMyCloudAzure-Production-2018-12-14",
        "id": "fd3b9d0a-7c7c-4e8f-8153-dd81d5d825a9",
        "isEnabled": true,
        "type": "User",
        "userConsentDescription": "Allow the application to access ParkMyCloudAzure-Production-2018-12-14 on your behalf.",
        "userConsentDisplayName": "Access ParkMyCloudAzure-Production-2018-12-14",
        "value": "user_impersonation"
    }],
    "objectId": "2198fcea-df57-423e-9e06-5a499a9b31d3",
    "objectType": "ServicePrincipal",
    "odata.metadata": "https://graph.windows.net/3e20c9b8-1734-4141-95b4-efd9f4c247de/$metadata#directoryObjects/@Element",
    "odata.type": "Microsoft.DirectoryServices.ServicePrincipal",
    "passwordCredentials": [],
    "preferredSingleSignOnMode": null,
    "preferredTokenSigningKeyEndDateTime": null,
    "preferredTokenSigningKeyThumbprint": null,
    "publisherName": "ParkMyCloud, Inc.",
    "replyUrls": [],
    "samlMetadataUrl": null,
    "samlSingleSignOnSettings": null,
    "servicePrincipalNames": [
        "parkmycloud-20356-8333.parkmycloud.com",
        "937062cd-e5e4-467f-a2ea-29895313047"
    ],
    "servicePrincipalType": "Application",
    "signInAudience": "AzureADMyOrg",
    "tags": [],
    "tokenEncryptionKeyId": null
}

The key data here is the objectId shown on line 34 above as 2198fcea-df57-423e-9e06-5a499a9b31d3.  This is the Service Principal Object ID - copy it for use in step 6.

4b. Getting the Service Principal Object ID with the Azure Console

If you prefer to use the Azure Console:

  1. Log in to the Azure management console.
  2. Navigate to Azure Active Directory → Enterprise applications → All applications

  3. In the search box of the screen that appears on the right, enter the Application ID from Edit Credential screen from Step 1.  For example, in the example shown above, this was 937062cd-e5e4-467f-a2ea-29895313047
  4. Select the application that appears in the list.

  5. On the screen that comes up, select Properties
  6. On the right side of the screen, copy the text labeled Object ID.  This is the Service Principal Object ID - copy it for use in step 6.  We recommend you record this number in case you need to update the Azure Custom Role at a later time.

5. Create a Custom Role with Limited Permissions

Reference: https://docs.microsoft.com/en-us/azure/active-directory/role-based-access-control-custom-roles 

Get the latest Example Policy from the ParkMyCloud Console Edit Credential page or download it from https://s3.amazonaws.com/parkmycloud-public/PMCAzureRecommendedPolicy.json, and paste it into a new text file named something like PMCAzureRecommendedPolicy.json.

Important: Edit the file:

  • Since you already have an existing ParkMyCloud policy, you will need to rename this one.  Change the "Name" filed to include something unique, like the date.  Example: "ParkMyCloud Limited Access 2020-04-17"
  • Under the Assignable Scopes section, enter the Subscription ID from step 3.
{
    "Name": "ParkMyCloud Limited Access as of 2020-08-17",
    "Description": "ParkMyCloud limited access as of 2020-08-17",
    "IsCustom": "true",
    "Actions": [
        "Microsoft.Capacity/reservationOrders/*/read",
        "Microsoft.Commerce/*/read",
        "Microsoft.Compute/*/read",
        "Microsoft.Compute/virtualMachines/start/action",
        "Microsoft.Compute/virtualMachines/deallocate/action",
        "Microsoft.Compute/virtualMachines/write",
        "Microsoft.Compute/virtualMachineScaleSets/write",
        "Microsoft.Compute/virtualMachineScaleSets/start/action",
        "Microsoft.Compute/virtualMachineScaleSets/deallocate/action",
        "Microsoft.Consumption/*/read",
        "Microsoft.ContainerService/managedClusters/agentPools/read",
        "Microsoft.ContainerService/managedClusters/read",
        "Microsoft.Insights/*/read",
        "Microsoft.Insights/AutoscaleSettings/Write",
        "Microsoft.Network/networkInterfaces/read",
        "Microsoft.Network/publicIPAddresses/read",
        "Microsoft.Resources/subscriptions/*/read",
        "Microsoft.Sql/managedInstances/*/read",
        "Microsoft.Sql/managedInstances/write",
        "Microsoft.Sql/servers/databases/*/read",
        "Microsoft.Sql/servers/databases/pause/action",
        "Microsoft.Sql/servers/databases/resume/action",
        "Microsoft.Sql/servers/databases/write",
        "Microsoft.Sql/servers/read",
        "Microsoft.Sql/servers/elasticPools/*/read",
        "Microsoft.Sql/servers/elasticPools/write"  
    ],
    "NotActions": [],
    "AssignableScopes": [
        "/subscriptions/<Your_subscription_ID_here>"
    ]
}

Then execute the following command:

az role definition create --role-definition PMCAzureRecommendedPolicy.json

This will result in something like the following:

{
  "id": "/subscriptions/7eb65902-61fe-4b18-9641-0b7825f66aaa/providers/Microsoft.Authorization/roleDefinitions/6fda2b5e-088c-403e-8b2f-beec17ab9f94",
  "name": "6fda2b5e-088c-403e-8b2f-beec17ab9f94",
  "properties": {
    "additionalProperties": {
      "createdBy": "104a1c7c-0059-41fa-a6c5-6b19b8e95330",
      "createdOn": "2018-01-29T16:23:51.6582908Z",
      "updatedBy": "104a1c7c-0059-41fa-a6c5-6b19b8e95330",
      "updatedOn": "2018-01-29T16:23:51.6582908Z"
    },
    "assignableScopes": [
      "/subscriptions/7eb65902-61fe-4b18-9641-0b7825f66aaa"
    ],
    "description": "ParkMyCloud limited access as of 2020-08-17",
    "permissions": [
      {
        "actions": [
        	"Microsoft.Capacity/reservationOrders/*/read",
        	"Microsoft.Commerce/*/read",
        	"Microsoft.Compute/*/read",
        	"Microsoft.Compute/virtualMachines/start/action",
        	"Microsoft.Compute/virtualMachines/deallocate/action",
        	"Microsoft.Compute/virtualMachines/write",
        	"Microsoft.Compute/virtualMachineScaleSets/write",
        	"Microsoft.Compute/virtualMachineScaleSets/start/action",
        	"Microsoft.Compute/virtualMachineScaleSets/deallocate/action",
        	"Microsoft.Consumption/*/read",
        	"Microsoft.ContainerService/managedClusters/agentPools/read",
        	"Microsoft.ContainerService/managedClusters/read",
        	"Microsoft.Insights/*/read",
        	"Microsoft.Insights/AutoscaleSettings/Write",
        	"Microsoft.Network/networkInterfaces/read",
        	"Microsoft.Network/publicIPAddresses/read",
        	"Microsoft.Resources/subscriptions/*/read",
        	"Microsoft.Sql/managedInstances/*/read",
        	"Microsoft.Sql/managedInstances/write",
        	"Microsoft.Sql/servers/databases/*/read",
        	"Microsoft.Sql/servers/databases/pause/action",
        	"Microsoft.Sql/servers/databases/resume/action",
        	"Microsoft.Sql/servers/databases/write",
        	"Microsoft.Sql/servers/read",
        	"Microsoft.Sql/servers/elasticPools/*/read",
        	"Microsoft.Sql/servers/elasticPools/write"  
        ],
        "notActions": []
      }
    ],
    "roleName": "ParkMyCloud Limited Access as of 2020-08-17",
    "type": "CustomRole"
  },
  "type": "Microsoft.Authorization/roleDefinitions"
}

Make note of the name field near the top of the above, which is the Role Definition ID (in this case shown at line 3: 6fda2b5e-088c-403e-8b2f-beec17ab9f94).

6. Assign the Custom Role to Service Principal

The final step will be to map this custom role you have just created to the service principal:

az role assignment create --scope /subscriptions/<Subscription ID> --assignee-object-id <Service Principal Object Id> --role "<RoleId>" 

Where: 

  • Scope is Subscription ID from Step 1
  • Service Principal Object Id is from Step 4
  • Role Definition Id is from Step 5

This should result in output like the following:

Output
{
  "id": "/subscriptions/7eb65902-61fe-4b18-9641-0b7825f66aaa/providers/Microsoft.Authorization/roleAssignments/204c952f-368f-434f-baca-8726e1a60a9a",
  "name": "204c952f-368f-434f-baca-8726e1a60a9a",
  "properties": {
    "additionalProperties": {
      "createdBy": null,
      "createdOn": "2018-01-29T16:38:59.5499385Z",
      "updatedBy": "104a1c7c-0059-41fa-a6c5-6b19b8e95330",
      "updatedOn": "2018-01-29T16:38:59.5499385Z"
    },
    "principalId": "38cc91f5-84de-4031-895b-8e12f88a7e10",
    "roleDefinitionId": "/subscriptions/7eb65902-61fe-4b18-9641-0b7825f66aaa/providers/Microsoft.Authorization/roleDefinitions/1a0ae6e6-d03e-45ce-a321-37905147b925",
    "scope": "/subscriptions/11aaa902-82ca-4b18-9641-0b7825f7eb42a"
  },
  "type": "Microsoft.Authorization/roleAssignments"
}


Once these steps are complete, you may go back to this Credential in the ParkMyCloud Console and click the Test button.  Note that it can sometimes take up to 24 hours for the changes to be reflected throughout Azure, allowing for a fully successful test in the ParkMyCloud Console.