Skip to content

Commit

Permalink
Feature/iai (#141)
Browse files Browse the repository at this point in the history
Added Microsoft.Azure.IIoT.Deployment.


Added deployment of client and service applications.
Added AKS cluster.
Added integration of network components with AKS.
Added logging using Serilog.
Added environment variables of .env file.
Added k8s deployment templates for micro-services.
Fixed key retrieval of CosmosDB account.
Moved configuration to one ConfigMap.
Added resource limits.
Added RedirectUrls for client application.
Separated deployments and services yaml files.
Added programmatic deployment of OMP services.
Minor changes to OMP env vars generation.
Added cert upload to AKS.
Added client classes for KeyVault operations.
Added IaiAksManagementClient and IaiEnvironment.
Added IaiNetworkManagementClient.
Renamed Omp* classes to Iai*.
Added IaiWebSiteManagementClient.
Added IaiApplicationInsightsManagementClient class.
Added IaiOperationalInsightsManagementClient class.
Added a few more Azure resource management classes.
Consolidated app registration in IaiGraphServiceClient class.
Added Azure client and configuration provider classes.
Added DelegatingTokenProvider for TokenCredentials.
Renamed project to Microsoft.Azure.IIoT.Deployment.
Added Copyright header.
Added DeploymentExecutor class.
Added exception handling to Main().
Added namespace separation.
Got rid of Iai* prefix in class names.
Removed mentions of omp from IIoTK8SClient.
Renamed omp in k8s resources to industrial-iot.
Enabled redirection of HTTP traffic to HTTPS for App Service.
Upgraded Azure and Serilog nuget packages.
Using portable BouncyCastle. Bumped version of Azure Authorization NuGet.
Moved Microsoft.Azure.IIoT.Deployment project to deploy/src folder.
Added resource cleanup flow on error.
Changed order of resource cleanup.
Added Build.props.
Bumped Kubernetes version to 1.13.11.
Migrated to .Net Core 3.0
Added device code flow authentication for Unix systems.
Reordered resource creation tasks to accelerate deployment.
Using .Net Core 3.0 in Azure DevOps Pipelines.
Improved comments and added new PasswordCredential creation flow.
Added comments about installation of .Net Core 3.0 in DevOps steps.
Signing IAI executable.
Changed K8S IIoT env file to be Secret instead of ConfigMap.
Added retry to RoleAssignment creation.
Fixing Publish step of iai_publish.yml: so that it does not attempt to publish all projects.
Added registration of resource providers.
Fixing match pattern to only sign published exes.
Commenting out everything.
Changing order of DevOps jobs to execute iai_publish first.
Forcing execution of iai_publish in .vsts-ci.yml
Added ouputDir to publish task.
Trying to set output directory via arguments.
Disabling publish trimmer.
Fixing executable signing and zip archive naming.
Fixing versioning in zip file name.
Building Microsoft.Azure.IIoT.Deployment on all platforms.
Building Microsoft.Azure.IIoT.Deployment on all platforms.
Running virus scan only on Windows.
Fixing pattern to match linux and macOs executables.
Only signing Windows executables.
Added .Net Core 3.0 installation to iiot_deploy.
Added md5 checksum generation on linux and macOS.
Using separate job template for windows.
Added linux and macOS executable publishing jobs.
Minor changes to job names.
Reverting back commented out jobs.
Added documentation of Microsoft.Azure.IIoT.Deployment.
Added sample helm install command for NGINX Ingress.
Added note about required change in ingress YAML.
Added note about restarting App Service.
Fixed service names in Ingress.
Removed specific hosts from tls spec of Ingress.
Removed note about modifications to Ingress.
Removed host URL part. That is no longer relevant since we set up the default SSL certificate for Ingress controller.
Upgraded System.Private.Uri NuGet to version 4.3.2
Fixing review comments regarding docs.
Removed IndiaCentral region from list of functional regions: App Service Plan scaling is not available in the region.
  • Loading branch information
karok2m authored and cristipogacean committed Dec 4, 2019
1 parent 8e9a897 commit 82b7d7c
Show file tree
Hide file tree
Showing 61 changed files with 8,423 additions and 40 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,6 @@
/**/packages/**
/**/appsettings.*.json
.env

*.crt
*.key

15 changes: 15 additions & 0 deletions Industrial-IoT.sln
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.IIoT.OpcUa.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.IIoT.Cdm", "common\src\Microsoft.Azure.IIoT.Cdm\src\Microsoft.Azure.IIoT.Cdm.csproj", "{1ABED1C3-C9B5-41F4-9F8B-DD66C7105299}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "deploy", "deploy", "{8D316DA2-FC23-4F5A-ABE0-725C6E9653EC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{24CC83C2-F144-4EB9-9C7E-48406B1E2932}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.IIoT.Deployment", "deploy\src\Microsoft.Azure.IIoT.Deployment\Microsoft.Azure.IIoT.Deployment.csproj", "{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -895,6 +901,12 @@ Global
{1ABED1C3-C9B5-41F4-9F8B-DD66C7105299}.Develop|Any CPU.Build.0 = Debug|Any CPU
{1ABED1C3-C9B5-41F4-9F8B-DD66C7105299}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1ABED1C3-C9B5-41F4-9F8B-DD66C7105299}.Release|Any CPU.Build.0 = Release|Any CPU
{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF}.Develop|Any CPU.ActiveCfg = Debug|Any CPU
{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF}.Develop|Any CPU.Build.0 = Debug|Any CPU
{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1023,6 +1035,9 @@ Global
{C5D00945-D24F-4421-80DD-FAC549E79B33} = {AFBD4A17-2EB1-421C-BB0C-407C875F3F50}
{CD2F90BC-0FA9-4737-9F15-47EF06489423} = {A6028EDB-3331-48D2-8C7D-8D681172A61A}
{1ABED1C3-C9B5-41F4-9F8B-DD66C7105299} = {FEE95825-2E34-45AF-BDED-52F9C7412BF5}
{4CF22591-6F77-486F-BBFE-6173536D0625} = {30938473-53C1-4981-BFAB-B6309147FF24}
{24CC83C2-F144-4EB9-9C7E-48406B1E2932} = {8D316DA2-FC23-4F5A-ABE0-725C6E9653EC}
{4676D2B5-492B-47FF-9AD8-CB546CA0CEEF} = {24CC83C2-F144-4EB9-9C7E-48406B1E2932}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F09EFCEA-59F6-4A16-9CB6-7E865A3F62D8}
Expand Down
17 changes: 15 additions & 2 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@ stages:
- template: tools/templates/sdl.yml
- stage: pack
displayName: 'Package and Sign Nuget'
dependsOn: build
dependsOn:
- build
jobs:
- template: tools/templates/nuget.yml
parameters:
sign: ${{ startsWith(variables['Build.SourceBranch'], 'refs/heads/') }}
- stage: iiot_deployment
displayName: 'Publish Microsoft.Azure.IIoT.Deployment'
dependsOn:
- build
jobs:
- template: tools/templates/iiot_deployment_win.yml
parameters:
sign: ${{ startsWith(variables['Build.SourceBranch'], 'refs/heads/') }}
- template: tools/templates/iiot_deployment_linux.yml
- template: tools/templates/iiot_deployment_mac.yml
- stage: images
displayName: 'Create and Push Images'
dependsOn: pack
dependsOn:
- pack
- iiot_deployment
jobs:
- template: tools/templates/acrbuild.yml
parameters:
Expand Down
3 changes: 3 additions & 0 deletions deploy/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Project>
<Import Project="$([MSBuild]::GetPathOfFileAbove(common.props))" Condition="'$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), common.props))' != ''" />
</Project>
285 changes: 285 additions & 0 deletions deploy/src/Microsoft.Azure.IIoT.Deployment/AuthenticationManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

namespace Microsoft.Azure.IIoT.Deployment {

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.ResourceManager.Fluent.Authentication;
using Microsoft.Identity.Client;
using Microsoft.Rest;

class AuthenticationManager {

// ClientId of AzureIndustrialIoTIAI Application
public const string AzureIndustrialIoTIAIClientID = "fb2ca262-60d8-4167-ac33-1998d6d5c50b";

public static readonly string[] MicrosoftGraphIAIScopes = new string[] {
"https://graph.microsoft.com/Directory.AccessAsUser.All"
};

public static readonly string[] AzureManagementIAIScopes = new string[] {
"https://management.azure.com/user_impersonation"
};

public static readonly string[] KeyVaultIAIScopes = new string[] {
"https://vault.azure.net/user_impersonation"
};



private readonly AzureEnvironment _azureEnvironment;
private readonly IPublicClientApplication _publicClientApplication;

private IAccount _account;
private Guid _tenantId;


public AuthenticationManager(
AzureEnvironment azureEnvironment,
string tenant
) {
_azureEnvironment = azureEnvironment;
var azureCloudInstance = ToAzureCloudInstance(azureEnvironment);

_publicClientApplication = PublicClientApplicationBuilder
.Create(AzureIndustrialIoTIAIClientID)
.WithAuthority(azureCloudInstance, tenant)
//.WithAuthority(azureCloudInstance, AadAuthorityAudience.AzureAdMultipleOrgs)
.WithDefaultRedirectUri()
.Build();
}

public async Task AuthenticateAsync(
CancellationToken cancellationToken = default
) {
AuthenticationResult microsoftGraphAuthenticatoinResult;

var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

if (isWindows) {
// We will use interactive authentication flow for Windows.
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Acquiring-tokens-interactively

// ToDo: Add timeout.
microsoftGraphAuthenticatoinResult = await _publicClientApplication
.AcquireTokenInteractive(MicrosoftGraphIAIScopes)
.WithExtraScopesToConsent(AzureManagementIAIScopes)
.WithExtraScopesToConsent(KeyVaultIAIScopes)
//.WithPrompt(Prompt.SelectAccount)
.ExecuteAsync(cancellationToken);
}
else {
// We will use device code flow authentication for Unix systems.
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/Device-Code-Flow

// ToDo: Add timeout.
microsoftGraphAuthenticatoinResult = await _publicClientApplication
.AcquireTokenWithDeviceCode(
MicrosoftGraphIAIScopes,
deviceCodeResult => {
// This will print the message on the console which tells the user where to go sign-in using
// a separate browser and the code to enter once they sign in.
// The AcquireTokenWithDeviceCode() method will poll the server after firing this
// device code callback to look for the successful login of the user via that browser.
// This background polling (whose interval and timeout data is also provided as fields in the
// deviceCodeCallback class) will occur until:
// * The user has successfully logged in via browser and entered the proper code
// * The timeout specified by the server for the lifetime of this code (typically ~15 minutes) has been reached
// * The developing application calls the Cancel() method on a CancellationToken sent into the method.
// If this occurs, an OperationCanceledException will be thrown (see catch below for more details).
Console.WriteLine(deviceCodeResult.Message);
return Task.FromResult(0);
})
.ExecuteAsync();
}

// Extract account and tenant ID from microsoftGraphAuthenticatoinResult
_account = microsoftGraphAuthenticatoinResult.Account;
_tenantId = new Guid(microsoftGraphAuthenticatoinResult.TenantId);

// Validate that we have received Tokens.
await AcquireMicrosoftGraphTokenAsync(cancellationToken);
await AcquireAzureManagementTokenAsync(cancellationToken);
await AcquireKeyVaultTokenAsync(cancellationToken);
}

public async Task<AuthenticationResult> AcquireMicrosoftGraphTokenAsync(
CancellationToken cancellationToken = default
) {
// Fetch AccessToken from cache
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/AcquireTokenSilentAsync-using-a-cached-token
var authenticationResult = await _publicClientApplication
.AcquireTokenSilent(MicrosoftGraphIAIScopes, _account)
.ExecuteAsync(cancellationToken);

return authenticationResult;
}

public async Task<AuthenticationResult> AcquireAzureManagementTokenAsync(
CancellationToken cancellationToken = default
) {
// Fetch AccessToken from cache
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/AcquireTokenSilentAsync-using-a-cached-token
var authenticationResult = await _publicClientApplication
.AcquireTokenSilent(AzureManagementIAIScopes, _account)
.ExecuteAsync(cancellationToken);

return authenticationResult;
}

public async Task<AuthenticationResult> AcquireKeyVaultTokenAsync(
CancellationToken cancellationToken = default
) {
// Fetch AccessToken from cache
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/AcquireTokenSilentAsync-using-a-cached-token
var authenticationResult = await _publicClientApplication
.AcquireTokenSilent(KeyVaultIAIScopes, _account)
.ExecuteAsync(cancellationToken);

return authenticationResult;
}

public async Task<TokenCredentials> GetMicrosoftGraphTokenCredentialsAsync(
CancellationToken cancellationToken = default
) {
var microsoftGraphAuthenticatoinResult = await AcquireMicrosoftGraphTokenAsync(cancellationToken);
var microsoftGraphTokenCredentials = GenerateTokenCredentials(microsoftGraphAuthenticatoinResult);
return microsoftGraphTokenCredentials;
}

public TokenCredentials GetMicrosoftGraphDelegatingTokenCredentials() {
var microsoftGraphTokenCredentials = GenerateDelegatingTokenCredentials(AcquireMicrosoftGraphTokenAsync);
return microsoftGraphTokenCredentials;
}

public async Task<TokenCredentials> GetAzureManagementTokenCredentialsAsync(
CancellationToken cancellationToken = default
) {
var azureManagementAuthenticatoinResult = await AcquireAzureManagementTokenAsync(cancellationToken);
var azureManagementTokenCredentials = GenerateTokenCredentials(azureManagementAuthenticatoinResult);
return azureManagementTokenCredentials;
}

public TokenCredentials GetAzureManagementDelegatingTokenCredentials() {
var azureManagementTokenCredentials = GenerateDelegatingTokenCredentials(AcquireAzureManagementTokenAsync);
return azureManagementTokenCredentials;
}

public async Task<TokenCredentials> GetKeyVaultTokenCredentialsAsync(
CancellationToken cancellationToken = default
) {
var keyVaultAuthenticatoinResult = await AcquireKeyVaultTokenAsync(cancellationToken);
var keyVaultTokenCredentials = GenerateTokenCredentials(keyVaultAuthenticatoinResult);
return keyVaultTokenCredentials;
}

public TokenCredentials GetKeyVaultDelegatingTokenCredentials() {
var keyVaultTokenCredentials = GenerateDelegatingTokenCredentials(AcquireKeyVaultTokenAsync);
return keyVaultTokenCredentials;
}

public IAccount GetAccount() {
return _account;
}

public Guid GetTenantId() {
return _tenantId;
}

public async Task<AzureCredentials> GetAzureCredentialsAsync(
CancellationToken cancellationToken = default
) {
var azureManagementTokenCredentials = await GetAzureManagementTokenCredentialsAsync(cancellationToken);
var microsoftGraphTokenCredentials = await GetMicrosoftGraphTokenCredentialsAsync(cancellationToken);

var azureCredentials = new AzureCredentials(
azureManagementTokenCredentials,
microsoftGraphTokenCredentials,
_tenantId.ToString(),
_azureEnvironment
);

return azureCredentials;
}

public AzureCredentials GetDelegatingAzureCredentials() {
var azureManagementTokenCredentials = GetAzureManagementDelegatingTokenCredentials();
var microsoftGraphTokenCredentials = GetMicrosoftGraphDelegatingTokenCredentials();

var azureCredentials = new AzureCredentials(
azureManagementTokenCredentials,
microsoftGraphTokenCredentials,
_tenantId.ToString(),
_azureEnvironment
);

return azureCredentials;
}

public static AzureCloudInstance ToAzureCloudInstance(AzureEnvironment azureEnvironment) {
if (azureEnvironment.Equals(AzureEnvironment.AzureGlobalCloud)) {
return AzureCloudInstance.AzurePublic;
}
else if (azureEnvironment.Equals(AzureEnvironment.AzureChinaCloud)) {
return AzureCloudInstance.AzureChina;
}
else if (azureEnvironment.Equals(AzureEnvironment.AzureGermanCloud)) {
return AzureCloudInstance.AzureGermany;
}
else if (azureEnvironment.Equals(AzureEnvironment.AzureUSGovernment)) {
return AzureCloudInstance.AzureUsGovernment;
}
else {
throw new SystemException("Unknown AzureEnvironment: " + azureEnvironment.Name);
}
}

public static TokenCredentials GenerateTokenCredentials(
AuthenticationResult authenticationResult
) {
ITokenProvider tokenProvider = new StringTokenProvider(authenticationResult.AccessToken, "Bearer");

var tokenCredentials = new TokenCredentials(
tokenProvider,
authenticationResult.TenantId,
authenticationResult.Account.Username
);

return tokenCredentials;
}

public ITokenProvider GenerateDelegatingTokenProvider(
Func<CancellationToken, Task<AuthenticationResult>> authenticationResultProvider
) {
async Task<string> accessTokenProvider(CancellationToken cancellationToken) {
var authenticationResult = await authenticationResultProvider(cancellationToken);
return authenticationResult.AccessToken;
};

ITokenProvider tokenProvider = new DelegatingTokenProvider(accessTokenProvider);

return tokenProvider;
}

public TokenCredentials GenerateDelegatingTokenCredentials(
Func<CancellationToken, Task<AuthenticationResult>> authenticationResultProvider
) {
var tokenProvider = GenerateDelegatingTokenProvider(authenticationResultProvider);

var tokenCredentials = new TokenCredentials(
tokenProvider,
_tenantId.ToString(),
_account.Username
);

return tokenCredentials;
}
}
}

0 comments on commit 82b7d7c

Please sign in to comment.