Sunday, 24 May 2020

PowerApps Portals - Automate Portal Configuration Backup using Azure DevOps





















Welcome everyone to the Power Guide Mentorship Program.

Today I am going to share #PowerGuideTip12, in which I'll share a Tip to Automate the PowerApps Portals or Dynamics CRM Portals Backup using Azure DevOps.

Introduction

As you already know, Power Apps makers can now create a powerful new type of experience: external-facing websites (PowerApps Portals), that empower anyone either inside or outside your organization to interact with Common Data Service data either anonymously or through commercial authentication providers like LinkedIn, Microsoft, Facebook, and Google, or enterprise providers such as Azure AD B2C, Azure AD, and Okta.

Developer Needs

Portal development involves several configurations and customizations to achieve the desired experience for portal end-users. However, one of the most common mistakes that every developer often does is - Forget to take Backup of his/her daily work.

After you have completed the development or configuration of your portal instance, you might want to take backup to save your daily work. Sometimes taking manual Backup of your Portal Configuration is a very time-consuming process.

Today, In this article, I am going to share an automated solution in order to Automate your PowerApps Portal Backup, which will reduce the headache and load of every developer to take the Portal Backup every day manually.

Let's get started...

Approach 1 - Portal Configuration Backup using Azure DevOps

Azure DevOps is a Software as a service (SaaS) platform from Microsoft that provides end-to-end components, processes, and various tools for developing and deploying the software.  It also integrates with most leading tools on the market which allows you to automate your deployments.

Azure DevOps provides five Azure Services or Components:

Azure Boards: agile planning, work item tracking, visualization, and reporting tool.
Azure Pipelines: a language, platform, and cloud-agnostic CI/CD platform with support for containers or Kubernetes.
Azure Repos: provides cloud-hosted private git repos.
Azure Artifacts: provides integrated package management with support for Maven, npm, Python, and NuGet package feeds from public or private sources.
Azure Test Plans: provides an integrated planned and exploratory testing solution.

Today, I'll not deep-dive in explaining Azure DevOps. I'll explain this in my further article.

In this article, I'll show, how can I automate the Portal Backup using the Azure DevOps services.

Pre-Requisites:

  • Azure DevOps Subscription. If not, you can create a trial with no expiration validity. Can check here.
  • Power DevOps Tools. Can get it from here.
  • Configuration Migration Tool. Can download the latest tool from here.


Implementation:

Step 1 - Create Schema File to Export Portal Configuration

You can get the Portal Schema File from here. If it doesn't work due to any reason, you can create your own schema file as well for the selected Portal Entities.

Refer- https://docs.microsoft.com/en-us/power-platform/admin/create-schema-export-configuration-data


Step 2 - Set Up Azure DevOps Configurations

(a) Create a new Project in Azure DevOps (Ignore this step, if you already have an existing project)


 (b) Create a new Repository



(c) Create a new Folder inside the Repository (named: Portal Configuration)




(d) Upload Portal Scheme File inside Portal Configuration Folder (Generated from Step 1)




(e) Create a new Pipeline






(f) Install Power DevOps Tools. In my instance, It's already installed, hence it's showing 'Installed' not 'Get It Free'.



(g) Add the following Tasks in below-mentioned order




  • Task 1 - Power DevOps Tool Installer


  • Task 2 - Ping Environment
Connection String Format:  

AuthType=Office365; Url=https://powerguide.crm11.dynamics.com; UserName=arpit@powerguide.onmicrosoft.com;Password=Pass@word1

Note: Replace the red part with your CRM Instance details.


\
  • Task 3 - Export Configuration Migration Data
Connection String Format:  

AuthType=Office365; Url=https://powerguide.crm11.dynamics.com; UserName=arpit@powerguide.onmicrosoft.com;Password=Pass@word1
Note: Replace the red part with your CRM Instance details.

Schema File:  Portal Configuration/PortalSchemaFile.xml

Browse the Schema File from the Repository (Uploaded in Step (d)).

Data File: $(Build.ArtifactStagingDirectory)/data.zip

Path, where you want to keep your Exported Portal Configuration. 
$(Build.ArtifactStagingDirectory) means we are uploading the exported data file in Build Artifacts


  • Task 4 - Publish Build Artifacts
Path to Publish :  $(Build.ArtifactStagingDirectory)

Artifact Name: ConfigurationData_$(Build.BuildNumber)

$(Build.BuildNumber) means append the build number (that is today's date - see step (h)) while creating a new artifact.


  • Task 5 - Extract Configuration Migration Data

  • Task 6 - Publish Build Artifacts

(h) Change the default Build Number Format to Today's Date.

By default, Build Number shows a unique integer number for each running job like - #55, #56, #57, and so on. However, for readability purposes and find the Portal backup of a specific date, I have used the Build Job date as the Build number.



(i) Schedule the Pipeline (Job).

I have scheduled the Job to run at 10:00 PM Monday to Friday. We can configure it as per our need.



Step 3 - Run and Test






Email Confirmation on Portal Backup Job Completion

Important Points


  • In this demonstration, I have used only Build Pipeline (CI) in Azure DevOps in order to take the Portal Backup and storing it in Build Artifacts. If you want to deploy/migrate/import this data to Target CRM instance, you can create a Release Pipeline (CD), which will pick the package from the Build Artifacts and Import it in Target Instance.
  • Keep the Portal Backup CI Pipeline separate from your actual Build CI pipeline.
  • If your organization is not allowed to use Power DevOps Tools, You can write your own PowerShell Scripts to perform all the above-mentioned tasks.
  • Microsoft is also adding new Tasks in Power Build Tools. Hence in the future, you can also use, Microsoft's Power Build Tools to perform the same tasks that we have done using Power DevOps Tools.
  • This process takes the export of Complete Portal Configuration like changes made in the webpage, entity list, entity form, web template, etc, however, if you want to take the backup of CRM Customization as well, then you can add other tasks like Export Solution, Extract Solution using the same tool.
  • If you do not want to take the backup of whole portal configurations (all entities), you can create/modify the schema file and can only include most used portal entities like Web Pages, Web Templates, Entity Forms, etc
  • To view the backup of your Portal Configuration, you need to open the Pipeline Job (Open the Build Pipeline > Go to Job Run > Click to Open the Job > Click on Artifacts) of a specific date or you can check it on your email. For Example: If I want to get the Backup of Portal Configuration taken on 24/05/2020, I need to open the Portal Backup Pipeline Job of 24_05_2020. That's why I have modified the Build Number format to Date Format so that developer can easily find/search the backup by backup date.




Sometimes along with taking the whole portal configuration backup, we developer wants to take the backup of our Custom Code as well. Like HTML, CSS, JQuery, JavaScript, and Liquid Template.

Because Configuration Migration Tool gives the XML File (data.zip) of the Portal Configuration, and it's very hard to get/read the HTML/jquery/liquid template code from that file.

Approach 2 - Portal Custom Code Backup using Power Automate

In my next article, I'll share the #PowerGuideTip13 - To Automate the Portal Code backup using Power Automate. 

Stay Tuned.

Friday, 15 May 2020

Add Guest Users in Azure Active Directory using Power Automate and C# Code






















Welcome everyone to the Power Guide Mentorship Program.

Today I am going to share a #PowerGuideTip11- which will help you to automate the User creation in Azure Active Directory. There are various business requirements we may come across where we need to automate the user creation in Azure AD. Few very common business requirements are:

  • Add Owner in Microsoft Teams - Need to add the user in Azure AD
  • Add Members in Microsoft Teams. - User must be Guest User in Azure AD
  • Migrate Users from one CRM instance to another instance
  • Move users from one security group to another
  • Power Automate UI Approvals - In order to allow External Users to approve the request they must be in Azure AD as a guest user
  • Send Portal Invitation to Azure AD B2C Users.
  • Allow Portal access to invited users only -  Remove Sign Up option from Azure AD B2C Login Page and allow portal access to invited users only by creating them from CRM internally.
  • ....and many more

Today, I will share two-approaches through which you can easily automate your user creation in Azure AD: However, before discussing that, I would like to give a short explanation about Microsoft Graph API. Though I have already been covered this topic in my previous article.

If you want to know the Basics of Microsoft Graph API, You can go through my this article.

In brief, If we have to perform any operation in Dynamics 365 either from within the Dynamics CRM Application like forms and views, through JavaScript, Plugin, Workflow, C# code, or through any language, Microsoft has given one Rest API called - Dynamics 365 WEB API (Enhanced version of Organisation Service or OData). And that API is only restricted to perform operations in Dynamics 365 only.

However, you already know that Microsoft Dynamics 365 is tightly coupled with numerous other Microsoft products and services like Microsoft Azure, Microsoft Teams, Office 365. Outlook, OneDrive, OneNote, Microsoft Excel, and many more. And we often need to interact with these products and services to fulfill various business needs.

Hence, in order to interact with all these products and services, Microsoft introduced a new Rest API called Microsoft Graph API, which enables you to access various Microsoft Cloud service resources.

Since we have to create the users in Azure AD, Hence we'll have to interact with Graph API.



Let's get started...

Azure AD Configuration:

1.  Navigate to the Azure Portal.

2.  Search for App Registrations. Click App Registrations as shown below.



3.  Click on New Registration.



4.  Enter the Name and click Register.




5.  In the left panel, click Overview. Copy the Application (client) ID and Directory (tenant) ID values. These values will be used in Flow for authentication.




6.  In the left navigation, click Certificates & secrets. Click New client secret.





7.  Enter the description and set its Expiry to Never and click Add.




8.  Copy the secret value which will be used in flow for authentication.




9.  In the left navigation, click API Permissions.





10.  Click Add permission. Select Microsoft Graph API as shown below.




11.  Click Application Permission and Add the following Permissions (Add permission based on your need). 


I have added the following Application and Delegate Permission based on my Requirements and the operations I need to perform using Microsoft Graph API.



12.  Click Grant admin consent.





Once you are done with the Azure AD Configuration, you have two approaches/solutions to create users in Azure AD. What approach you go with it totally depends on your project need, product license, and organization need.

Approach 1 - Low Code - No Code

Using Power Automate:

Important Note: Make sure you have following privileges in Azure AD, otherwise you may end up facing permission related issues (for Azure AD user creation focus on highlighted one)



Step 1 - Go to https://make.powerapps.com/ and click on Flows

Step 2:  Click on + New and Choose + Instant from Blank




Step 3:  Provide Flow Name and Add Http Request Step




Step 4 - Configure the Flow as following.

Provide the Client ID, Client Secret Key, and Azure AD Tenant ID





Step 4 - As a best practice, Instead of hard-coding the Azure AD configuration, you can initialize all in the variables and pass the variable as shown below.





Step 5 - You can now Run and Test the Flow



Approach 2 - Custom Code


Using C# Code:

Important Note: Make sure the User (that you are using to connect yourAD in your code and getting token of it) must have following privileges in Azure AD, otherwise you may end up facing permission related issues (for Azure AD user creation focus on highlighted one)


Check these article as well for permissions - https://stackoverflow.com/questions/46429059/ms-graph-guid-for-permission-user-invite-all

https://stackoverflow.com/questions/48095484/inviting-a-user-in-azure-ad-through-microsoft-graph-api-doesnt-work/48101151

Step 1 - Open Visual Studio and Create a Console Application (CallMicrosoftGraphAPU)

Step 2:  Add Application.Config file to keep all the Azure AD related configuration

Put the following content in App.config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
  <appSettings>
    <add key="clientId" value="<your azure app client id>"/>
    <add key="clientSecretKey" value="<your azure app client secret key>"/>
    <add key="tenantId" value="<your azure active directory id>"/>
    <add key="audienceURL" value="https://graph.microsoft.com/.default"/>
    <add key="userName" value="<Azure AD admin username>"/>
    <add key="Password" value="<Azure AD admin password>"/>
  </appSettings>

</configuration>






Step 3:  Add the JSON file to keep HTTP Request JSON

Put the following content in JSON file

{
  "invitedUserEmailAddress": "<email id of guest user that you want to add in Azure AD>",
  "inviteRedirectUrl": "https://myapp.com",
  "sendInvitationMessage": "true" 

}




Step 4 - Download the C# Code from My GIT HUB Repository and paste it inside Program,cs


Step 5 - Add all necessary DLLs and References from Nuget Packagers. I have added the following references. You may need to add other references as well based on your Visual Studio version and framework





Step 6 - After pasting the code. The code will look like this:







using Newtonsoft.Json;
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;

namespace CallMicrosoftGraphAPI
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Generating Token");

            CreateGuestUser();

        }

        public static string GenerateToken()
        {
            String clientID = ConfigurationManager.AppSettings["clientId"];

            String clientSecretKey = ConfigurationManager.AppSettings["clientSecretKey"];

            string tenantId = ConfigurationManager.AppSettings["tenantId"];

            string audienceURL = ConfigurationManager.AppSettings["audienceURL"];

            string TokenUrl = "https://login.microsoftonline.com/"+ tenantId + "/oauth2/v2.0/token";

            string userName = ConfigurationManager.AppSettings["userName"];

            string Password = ConfigurationManager.AppSettings["Password"];

            var webClient = new WebClient();
            webClient.Headers[HttpRequestHeader.CacheControl] = "no-cache";
            webClient.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";

            string para = "grant_type=password&scope=" + audienceURL + "&client_id=" + clientID + "&client_secret=" + clientSecretKey + "&userName=" + userName + "&password=" + Password + "";

            string response = webClient.UploadString(TokenUrl, "POST", para);
            dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(response);
            string token = jsonObj.access_token;

            Console.WriteLine("Token Generated Succesfully...");

            return token;
        }

        public static void CreateGuestUser()
        {
// Reading the JSON value,
// You can directly paste your JSON as well. Check this article to get the syntax - https://stackoverflow.com/questions/22998177/store-hardcoded-json-string-to-variable

            string json = File.ReadAllText(@"C:\Users\Arpit\Documents\Code\CallMicrosoftGraphAPI\CallMicrosoftGraphAPI\request.json");

// Get the user token
            string token = GenerateToken();
           
            HttpResponseMessage servicerequest = null;

            using (HttpClient httpClient = new HttpClient())
            {
                httpClient.BaseAddress = new Uri("https://graph.microsoft.com/v1.0/invitations");
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                httpClient.DefaultRequestHeaders.Add("authorization", "Bearer " + token + "");

                var content = new StringContent(json.ToString(), System.Text.Encoding.UTF8, "application/json");

                servicerequest = httpClient.PostAsync("https://graph.microsoft.com/v1.0/invitations", content).Result;

                string response = servicerequest.Content.ReadAsStringAsync().Result;

                Console.WriteLine("User has been added as Guest User in Azure AD");

                Console.ReadKey();
               
            }
        }
    }

}

Code Explanation


  •  Read all Azure AD configurations from App.config
  •  Request for Access Token
  •  Got the Access Token
  •  Use the Token to call Microsoft Graph API in order to add a guest user in Azure AD
  • User added successfully

Step 6 - Run and Test the code




Download the Complete Code:

https://github.com/arpitdynamics/Dynamics365Code/blob/master/AddGuestUserInAzureAD.zip


That's all for today.

Stay Tuned for more such interesting stuff.

Cheers 👍
Blogger Widgets