Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Grant-Archibald-MS committed May 4, 2021
1 parent 3d0704e commit 73e3740
Show file tree
Hide file tree
Showing 10 changed files with 501 additions and 1 deletion.
38 changes: 38 additions & 0 deletions .github/workflow/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Game Release and Deploy Workflow

on:
push:
tags:
- '*'

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: |
cd scripts
zip -r ../apim-export-release.zip .
- name: Create tag
id: create_tag
shell: bash
run: |
tag=$(basename "${{ github.ref }}")
echo "::set-output name=tag::$tag"
- name: Create Release
id: create_release
uses: actions/create-release@v1
if: startsWith(github.ref, 'refs/tags/')
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.create_tag.outputs.tag }}
release_name: ${{ steps.create_tag.outputs.tag }}
draft: true
prerelease: false
- name: Release
uses: softprops/action-gh-release@v1
with:
files: apim-export-release.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"spellchecker.ignoreWordsList": [
"APIs",
"Dataverse",
"O365"
]
}
112 changes: 111 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,111 @@
# apim-powerplatform-export
# Overview

This repository expands on [Export APIs from Azure API Management to the Power Platform](https://docs.microsoft.com/en-us/azure/api-management/export-api-power-platform) article, discussing the following use content:

1. [Why is this important](#why-is-this-important)

2. [Export of API between different Azure Active Directory Tenants](#export-api-between-different-azure-active-directory-tenants)

3. [Sample](#sample) Provides sample scripts that can automate the end to end process of automating the deployment of an API from Azure to the Power Platform.

- [Provisioning Azure Resources](#provisioning-azure-resources)
- [Configure Azure API](#configure-azure-api)
- [Deploy your API to power platform](#deploy-your-api-to-power-platform)

3. [ALM automation of export process](#alm-automation)
4. [Notes](#notes)
- [O365 User License Context](#o365-licence-context)
- [Fusion Development Teams](#fusion-development-teams)

## Why Is This Important

Azure API Management API Export feature makes it easy to take advantage of pro code APIs that you have written in Azure or want to create and expose them to citizen developers so they can leverage them inside their low code Power Platform solutions.

The published [docs API export document](https://docs.microsoft.com/en-us/azure/api-management/export-api-power-platform) works well when the user manually wants to export the the Azure API Management API to a power platform as a custom connector. This guide looks at automating this process and covering scenarios like when you need to publish to APIs between multiple Azure Active Directory tenants.

## Export API Between Different Azure Active Directory Tenants

The article assumes that the Azure subscription and the power platform environment are in the same Azure Active directory tenant. The are various cases where this may not be the case for example:
- You are using your MSDN benefits [https://my.visualstudio.com/benefits](https://my.visualstudio.com/benefits) to use your Azure and Microsoft 365
Developer subscription (E5) benefits
- You are using your Development or Test Azure subscriptions which are not part of your main organization tenant
- You are deploying to trial subscription https://docs.microsoft.com/en-us/partner-center/advisors-create-a-trial-invitation and a separate pay as you go Azure subscription.

If scenarios like this apply to you then when you look to publish your API to your Power Apps environment then you will receive an empty list. to work around this gap you can use the [Sample](#sample) section below

## Sample

To run this sample download the latest [release](https://github.com/Grant-Archibald-MS/apim-powerplatform-export/releases) from GitHub. Upload the apim-export-release.zip to [https://shell.azure.com](https://shell.azure.com) or Azure Cloud Shell in [https://portal.azure.com](https://portal.azure.com).

Once uploaded perform thew following steps

1. unzip the release.zip

```
unzip apim-export-release.zip
```

2. Change config.json to include your settings replacing TODO values with your settings

```
{
"APIMPublisherEmail": "TODO",
"APIMPublisherName": "TODO2",
"powerPlatformEnvironment": "https://TODO3.crm.dynamics.com",
"powerPlatformTenantId": "TODO4",
"powerPlatformClientId": "TODO5",
"powerPlatformClientSecret": "TODO6",
"tags": [
"\"Workload name\"=\"Development APIM\"",
"\"Data Classification\"=\"Non-business\"",
"\"Business criticality\"=\"Low\"",
"\"Business Unit\"=\"Unknown\"",
"\"Operations commitment\"=\"Baseline Only\"",
"\"Operations Team\"=\"None\"",
"\"Expected Usage\"=\"Unknown time\""
]
}
```

### Provisioning Azure Resources

In [https://shell.azure.com](https://shell.azure.com) or Azure Cloud Shell of [https://portal.azure.com](https://portal.azure.com) choosing powershell script environment

1. ./resources.ps1

### Configure Azure API

TODO: To be updated include Azure Function included

### Deploy your API to power platform

#### Azure AD Service Principal

Ensure that you have created an Azure Active directory with the following
1. API Permissions for Dynamics CRM.
2. Admin granted permissions for Dynamics CRM
3. A secret allocated to the application

Ensure to that application user has been granted rights (System Customizer) in the power platform environment

#### Create Connector

In [https://shell.azure.com](https://shell.azure.com) or Azure Cloud Shell of [https://portal.azure.com](https://portal.azure.com) choosing powershell script environment

1. ./export-apim.ps1

## ALM Automation

You can use the sample scripts above to include them in your build process

## Notes

### O356 License Context

As at April 2021 as covered in [Licensing overview for Microsoft Power Platform](https://docs.microsoft.com/en-us/power-platform/admin/pricing-billing-skus) Power Apps include limited use rights included with Office 365 licenses to Export Azure API Management APIs to the Power platform.

This feature enable Customers to publish their Azure backend service as APIs and export these APIs to the Power Platform as custom connectors via Azure API Management. Customers with eligible Office 365 licenses that include Dataverse for Teams can use these connectors for custom applications, flows, and chatbots running in Teams and to connect Azure backend services. [Source](https://download.microsoft.com/download/9/5/6/9568EFD0-403D-4AE4-95F0-7FACA2CCB2E4/Power%20Apps,%20Power%20Automate%20and%20Power%20Virtual%20Agents%20Licensing%20Guide%20-%20Apr%202021.pdf). Appendix B in this guide includes specific O365 licenses that are eligible for this for this feature.

### Fusion Development Teams

You can use this feature as a first step to help integrate the concept of building fusion development teams including business, development and IT teams to build a solution. Using this base you can then expand into other premium connectors to accelerate and nurture fusion team development to build and deliver solutions in our organization.
17 changes: 17 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"APIMPublisherEmail": "[email protected]",
"APIMPublisherName": "Grant Archibald",
"powerPlatformEnvironment": "https://orgd1648131.crm.dynamics.com",
"powerPlatformTenantId": "8a235459-3d2c-415d-8c1e-e2fe133509ad",
"powerPlatformClientId": "6bca951c-ffc7-4345-b438-daa6a0326c18",
"powerPlatformClientSecret": "xKRexG5_d4Kj_ReD5WcN85dtj~3amU4~1A",
"tags": [
"\"Workload name\"=\"Development APIM\"",
"\"Data Classification\"=\"Non-business\"",
"\"Business criticality\"=\"Low\"",
"\"Business Unit\"=\"Unknown\"",
"\"Operations commitment\"=\"Baseline Only\"",
"\"Operations Team\"=\"None\"",
"\"Expected Usage\"=\"Unknown time\""
]
}
80 changes: 80 additions & 0 deletions scripts/components/apim.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<#
.NOTES
==============================================================================================
Copyright(c) Microsoft Corporation. All rights reserved.
File: apim.ps1
Purpose: Configure and deploy azure APIM Management
Version: 0.1.0
==============================================================================================
.SYNOPSIS
Define and provision APIM Management
.DESCRIPTION
Sample script to provision Azure Azure API Management
#>

class APIM {
[string] Create($resources, $config) {
$apimMatch = $resources.Where({ $_.type -eq "Microsoft.ApiManagement/service"})

$apiName = ""
Switch ($apimMatch.Count) {
0 {
$name = (New-Guid).Guid.Replace("-", "").Substring(0, 23)
$apiName = "A${name}"
Write-Host "Creating API Management"
az apim create --name $apiName --publisher-email $config.APIMPublisherEmail --publisher-name $config.APIMPublisherName --sku-name $config.apiSku --resource-group $config.resourceGroup
}
1 {
$apiName = $apimMatch[0].name
}
}

return $apiName
}

[string] ExportSwagger($config) {
Write-Host "Searching for APIM"

$apim = (az apim list -g $config.resourceGroup | ConvertFrom-Json)

if ( $apim.count -eq 1 ) {
Write-Host "Found APIM"
$serviceName = $apim[0].name

Write-Host "Searching for API"
$apis = (az apim api list --resource-group Azure-APIM-Management-Test --service-name $serviceName | ConvertFrom-Json)

$match = $apis | Where-Object { $_.name -eq $config.apiToExport }

if ($match.length -eq 1) {
Write-Host "Found api"

$token = (az account get-access-token --resource="https://management.azure.com" --query accessToken --output tsv)
$headers = @{
"Authorization" = "Bearer $token"
"Content-Type" = "application/json"
}

$apiId = $match[0].id
$url = [Uri]"https://management.azure.com${apiId}?format=swagger-link&export=true&api-version=2021-01-01-preview"

$apiDefinition = (Invoke-RestMethod -Method GET -Uri $url -Header $headers)
$downloadUrl = [Uri]$apiDefinition.value.link

$swagger = (Invoke-WebRequest -Uri $downloadUrl -Method GET)

return $swagger

}
} else {
$apiCount = $apim.count
Write-Host "Found $apiCount APIM instances, searhing for single"
}
return ""
}
}
76 changes: 76 additions & 0 deletions scripts/components/powerplatform.psm1
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<#
.NOTES
==============================================================================================
Copyright(c) Microsoft Corporation. All rights reserved.
File: powerplaform.ps1
Purpose: Configure and deploy Power Platform resources
Version: 0.1.0
==============================================================================================
.SYNOPSIS
Configure and deploy Power Platform resources
.DESCRIPTION
Sample script to provision Power Platform connectors
#>

class PowerPlatform {
[string] Login($config) {
$resourceName = $config.powerPlatformEnvironment
$tenantId = $config.powerPlatformTenantId
$clientId = $config.powerPlatformClientId
$clientSecret = $config.powerPlatformClientSecret

$body = @{grant_type="client_credentials";resource=$resourceName;client_id=$ClientID;client_secret=$clientSecret}

$loginURL = 'https://login.windows.net'

$url = [Uri]"$loginURL/$tenantId/oauth2/token?api-version=1.0"

return (Invoke-RestMethod -Method Post -Uri $url -Body $body).access_token
}

ImportConnector($config, [string] $accessToken, [string]$swagger) {
$headers = @{
"Authorization" = "Bearer $accessToken"
"OData-Version" = "4.0"
"Content-Type" = "application/json"
}

# https://docs.microsoft.com/en-us/dynamics365/customer-engagement/web-api/connector?view=dynamics-ce-odata-9

$swaggerData = ($swagger | ConvertFrom-Json)

$displayName = $swaggerData.info.title -replace " ", ""

#TODO - Add to a solution
$name = "new_5F" + $displayName.ToLower()

$body = @{
"name" = $name
"displayname" = $displayName
"connectortype" = 1
"openapidefinition" = $swagger
}

$json = ($body | ConvertTo-Json)

$Failure = $NULL

$url = $config.powerPlatformEnvironment
if ( !$url.endsWith("/") ) {
$url += "/"
}
$url += "api/data/v9.0/connectors"

$url = [Uri]$url

$resp = try { Invoke-WebRequest -Method POST -Uri $url -Headers $headers -Body $json } catch { $Failure = $_.Exception.Response }

Write-Host $resp
Write-Host $Failure
}
}
17 changes: 17 additions & 0 deletions scripts/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"APIMPublisherEmail": "TODO",
"APIMPublisherName": "TODO2",
"powerPlatformEnvironment": "https://TODO3.crm.dynamics.com",
"powerPlatformTenantId": "TODO4",
"powerPlatformClientId": "TODO5",
"powerPlatformClientSecret": "TODO6",
"tags": [
"\"Workload name\"=\"Development APIM\"",
"\"Data Classification\"=\"Non-business\"",
"\"Business criticality\"=\"Low\"",
"\"Business Unit\"=\"Unknown\"",
"\"Operations commitment\"=\"Baseline Only\"",
"\"Operations Team\"=\"None\"",
"\"Expected Usage\"=\"Unknown time\""
]
}
Loading

0 comments on commit 73e3740

Please sign in to comment.