From 44da6ce0e1437381212705d307ab563cd541908b Mon Sep 17 00:00:00 2001 From: kdcllc Date: Tue, 7 Jul 2020 19:25:30 -0400 Subject: [PATCH] resolves issue #125 --- Bet.AspNetCore.sln | 9 - README.md | 2 +- .../AppAuthentication.csproj | 35 --- .../AzureCli/AzureCliAccessTokenProvider.cs | 135 ----------- src/AppAuthentication/Constants.cs | 28 --- src/AppAuthentication/Dockerfile | 24 -- src/AppAuthentication/Dockerfile.original | 37 --- .../EnvironmentHostedService.cs | 78 ------- .../Helpers/ConsoleHandler.cs | 84 ------- .../Helpers/EnvironmentHelper.cs | 35 --- src/AppAuthentication/Helpers/JsonHelper.cs | 23 -- src/AppAuthentication/Helpers/UriHelper.cs | 62 ----- .../Helpers/ValidationHelper.cs | 25 --- src/AppAuthentication/IAccessTokenProvider.cs | 11 - src/AppAuthentication/IConsoleExtensions.cs | 29 --- src/AppAuthentication/IProcessManager.cs | 13 -- src/AppAuthentication/Models/AccessToken.cs | 122 ---------- .../Models/AppAuthenticationResult.cs | 116 ---------- .../Models/AuthenticationToken.cs | 37 --- .../Models/HttpBearerChallenge.cs | 132 ----------- src/AppAuthentication/Models/TokenResponse.cs | 75 ------- ...nteractiveAzureServiceTokenProviderBase.cs | 13 -- src/AppAuthentication/ProcessManager.cs | 107 --------- src/AppAuthentication/Program.cs | 62 ----- .../Properties/launchSettings.json | 11 - src/AppAuthentication/README.md | 115 ---------- src/AppAuthentication/RunCommand.cs | 212 ------------------ .../VisualStudioAccessTokenProvider.cs | 191 ---------------- .../VisualStudio/VisualStudioTokenProvider.cs | 24 -- .../VisualStudioTokenProviderFile.cs | 40 ---- .../WebHostBuilderExtensions.cs | 84 ------- .../WebHostBuilderOptions.cs | 57 ----- 32 files changed, 1 insertion(+), 2027 deletions(-) delete mode 100644 src/AppAuthentication/AppAuthentication.csproj delete mode 100644 src/AppAuthentication/AzureCli/AzureCliAccessTokenProvider.cs delete mode 100644 src/AppAuthentication/Constants.cs delete mode 100644 src/AppAuthentication/Dockerfile delete mode 100644 src/AppAuthentication/Dockerfile.original delete mode 100644 src/AppAuthentication/EnvironmentHostedService.cs delete mode 100644 src/AppAuthentication/Helpers/ConsoleHandler.cs delete mode 100644 src/AppAuthentication/Helpers/EnvironmentHelper.cs delete mode 100644 src/AppAuthentication/Helpers/JsonHelper.cs delete mode 100644 src/AppAuthentication/Helpers/UriHelper.cs delete mode 100644 src/AppAuthentication/Helpers/ValidationHelper.cs delete mode 100644 src/AppAuthentication/IAccessTokenProvider.cs delete mode 100644 src/AppAuthentication/IConsoleExtensions.cs delete mode 100644 src/AppAuthentication/IProcessManager.cs delete mode 100644 src/AppAuthentication/Models/AccessToken.cs delete mode 100644 src/AppAuthentication/Models/AppAuthenticationResult.cs delete mode 100644 src/AppAuthentication/Models/AuthenticationToken.cs delete mode 100644 src/AppAuthentication/Models/HttpBearerChallenge.cs delete mode 100644 src/AppAuthentication/Models/TokenResponse.cs delete mode 100644 src/AppAuthentication/NonInteractiveAzureServiceTokenProviderBase.cs delete mode 100644 src/AppAuthentication/ProcessManager.cs delete mode 100644 src/AppAuthentication/Program.cs delete mode 100644 src/AppAuthentication/Properties/launchSettings.json delete mode 100644 src/AppAuthentication/README.md delete mode 100644 src/AppAuthentication/RunCommand.cs delete mode 100644 src/AppAuthentication/VisualStudio/VisualStudioAccessTokenProvider.cs delete mode 100644 src/AppAuthentication/VisualStudio/VisualStudioTokenProvider.cs delete mode 100644 src/AppAuthentication/VisualStudio/VisualStudioTokenProviderFile.cs delete mode 100644 src/AppAuthentication/WebHostBuilderExtensions.cs delete mode 100644 src/AppAuthentication/WebHostBuilderOptions.cs diff --git a/Bet.AspNetCore.sln b/Bet.AspNetCore.sln index 06bd309..c60b40c 100644 --- a/Bet.AspNetCore.sln +++ b/Bet.AspNetCore.sln @@ -59,10 +59,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bet.Extensions.Hosting", "s EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{D08248C1-62F0-4011-9CB2-406FDE28EEA3}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "cli-tools", "cli-tools", "{D5655917-C1A5-44AA-85D2-BF9132205E4E}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppAuthentication", "src\AppAuthentication\AppAuthentication.csproj", "{47756F33-5FF7-4FDB-8E7D-F30CCFBE8F34}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bet.AspNetCore.ReCapture", "src\Bet.AspNetCore.ReCapture\Bet.AspNetCore.ReCapture.csproj", "{6472D7D3-D27B-4B57-ABE1-1708AB64E1D1}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bet.Extensions.ML", "src\Bet.Extensions.ML\Bet.Extensions.ML.csproj", "{5FD99A79-7BFB-4112-9B7F-6E308306FC46}" @@ -151,10 +147,6 @@ Global {AA34055E-D487-44B7-BD4C-FEEB29FFDA05}.Debug|Any CPU.Build.0 = Debug|Any CPU {AA34055E-D487-44B7-BD4C-FEEB29FFDA05}.Release|Any CPU.ActiveCfg = Release|Any CPU {AA34055E-D487-44B7-BD4C-FEEB29FFDA05}.Release|Any CPU.Build.0 = Release|Any CPU - {47756F33-5FF7-4FDB-8E7D-F30CCFBE8F34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {47756F33-5FF7-4FDB-8E7D-F30CCFBE8F34}.Debug|Any CPU.Build.0 = Debug|Any CPU - {47756F33-5FF7-4FDB-8E7D-F30CCFBE8F34}.Release|Any CPU.ActiveCfg = Release|Any CPU - {47756F33-5FF7-4FDB-8E7D-F30CCFBE8F34}.Release|Any CPU.Build.0 = Release|Any CPU {6472D7D3-D27B-4B57-ABE1-1708AB64E1D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6472D7D3-D27B-4B57-ABE1-1708AB64E1D1}.Debug|Any CPU.Build.0 = Debug|Any CPU {6472D7D3-D27B-4B57-ABE1-1708AB64E1D1}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -246,7 +238,6 @@ Global {2B077466-D1D8-4D93-8324-90898D286719} = {C4F77FEB-4C40-4285-AE27-D9B361A3A46F} {50B38E2B-E33D-4BAF-B6D0-7BBA49D8824A} = {C4F77FEB-4C40-4285-AE27-D9B361A3A46F} {AA34055E-D487-44B7-BD4C-FEEB29FFDA05} = {C4F77FEB-4C40-4285-AE27-D9B361A3A46F} - {47756F33-5FF7-4FDB-8E7D-F30CCFBE8F34} = {D5655917-C1A5-44AA-85D2-BF9132205E4E} {6472D7D3-D27B-4B57-ABE1-1708AB64E1D1} = {8DBACFCC-6031-44F4-AF8C-556A3946AB0A} {5FD99A79-7BFB-4112-9B7F-6E308306FC46} = {C4F77FEB-4C40-4285-AE27-D9B361A3A46F} {028AAF57-302B-422E-AF8B-A7CC18F69C5E} = {D08248C1-62F0-4011-9CB2-406FDE28EEA3} diff --git a/README.md b/README.md index 55a41e4..1e42d56 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ This goal of this repo is to provide with a reusable functionality for developin ## `DotNetCore` CLI global tools -1. [AppAuthentication](./src/AppAuthentication/) - enables `Azure Key Vault` or `Azure Blob Storage` access from Docker Container in Local development based on token authentication. +1. [AppAuthentication](https://github.com/kdcllc/AppAuthentication) - enables Microsoft Managed Identity (MSI) testing `Azure Key Vault` or `Azure Blob Storage` access from Docker Container in Local development based on token authentication. ## Generic functionally that extends `Microsoft.Extensions` namespace diff --git a/src/AppAuthentication/AppAuthentication.csproj b/src/AppAuthentication/AppAuthentication.csproj deleted file mode 100644 index b0939d5..0000000 --- a/src/AppAuthentication/AppAuthentication.csproj +++ /dev/null @@ -1,35 +0,0 @@ - - - - Exe - netcoreapp3.1 - appauthentication - appauthentication - - A command-line tool to enable authentication of Azure Vault when developing in local environment. - For example when VSCode Remote Containers are used this utility can be run to enable the authentication. - This tool is only functional for Docker Containers or Kubernetes cluster running locally. - - True - Azure, Authentication, AppAuthentication, Azure Key Vault, Docker, Kubernetes, VSCode Remote - 1 - $(NoWarn);SA1203;SA1201;CA1802;SA1401;SA1214;SA1204 - Linux - ..\.. - - - - - - - - - - - - - - - - - diff --git a/src/AppAuthentication/AzureCli/AzureCliAccessTokenProvider.cs b/src/AppAuthentication/AzureCli/AzureCliAccessTokenProvider.cs deleted file mode 100644 index f5eace3..0000000 --- a/src/AppAuthentication/AzureCli/AzureCliAccessTokenProvider.cs +++ /dev/null @@ -1,135 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; -using System.Threading.Tasks; - -using AppAuthentication.Helpers; -using AppAuthentication.Models; - -using Microsoft.Azure.Services.AppAuthentication; - -namespace AppAuthentication.AzureCli -{ - /// - /// Gets a token using Azure CLI 2.0 for local development scenarios. - /// az account get-access-token --resource. - /// - internal class AzureCliAccessTokenProvider : NonInteractiveAzureServiceTokenProviderBase, IAccessTokenProvider - { - // Allows for unit testing, by mocking IProcessManager - private readonly IProcessManager _processManager; - - // Constants related to command to execute to get token using Azure CLI - private const string Cmd = "cmd.exe"; - private const string Bash = "/bin/bash"; - private const string GetTokenCommand = "az account get-access-token -o json"; - private const string ResourceArgumentName = "--resource"; - - // This is the path that a develop can set to tell this class what the install path for Azure CLI is. - private const string AzureCliPath = "AzureCLIPath"; - - // The default install paths are used to find Azure CLI. This is for security, so that any path in the calling program's Path environment is not used to execute Azure CLI. - private readonly string _azureCliDefaultPathWindows = - $"{Environment.GetEnvironmentVariable("ProgramFiles(x86)")}\\Microsoft SDKs\\Azure\\CLI2\\wbin; {Environment.GetEnvironmentVariable("ProgramFiles")}\\Microsoft SDKs\\Azure\\CLI2\\wbin" - ; - - // Default path for non-Windows. - private const string AzureCliDefaultPath = "/usr/bin:/usr/local/bin"; - - internal AzureCliAccessTokenProvider(IProcessManager processManager) - { - _processManager = processManager; - PrincipalUsed = new Principal { Type = "User" }; - } - - public async Task GetAuthResultAsync(string resource, string authority) - { - try - { - // Validate resource, since it gets sent as a command line argument to Azure CLI - ValidationHelper.ValidateResource(resource); - - // Execute Azure CLI to get token - var response = await _processManager.ExecuteAsync(new Process { StartInfo = GetProcessStartInfo(resource) }).ConfigureAwait(false); - - // Parse the response - var tokenResponse = TokenResponse.Parse(response); - - var accessToken = tokenResponse.AccessToken2; - - var token = AccessToken.Parse(accessToken); - - PrincipalUsed.IsAuthenticated = true; - - if (token != null) - { - // Set principal used based on the claims in the access token. - PrincipalUsed.UserPrincipalName = !string.IsNullOrEmpty(token.Upn) ? token.Upn : token.Email; - PrincipalUsed.TenantId = token.TenantId; - } - - var authResult = Models.AppAuthenticationResult.Create(tokenResponse, TokenResponse.DateFormat.DateTimeString); - - var authenticationToken = new AuthenticationToken - { - AccessToken = authResult.AccessToken, - TokenType = authResult.TokenType, - Resource = authResult.Resource, - ExpiresOn = authResult.ExpiresOn.ToString(), - ExpiresIn = token.ExpiryTime.ToString(), - ExtExpiresIn = token.ExpiryTime.ToString(), - RefreshToken = tokenResponse.AccessToken2 - }; - - return authenticationToken; - } - catch (Exception exp) - { - throw new Exception( - $"{nameof(AzureCliAccessTokenProvider)} not able to obtain the token for {ConnectionString} , {resource} , {authority}, {exp.Message}"); - } - } - - private ProcessStartInfo GetProcessStartInfo(string resource) - { - ProcessStartInfo startInfo; - -#if FullNetFx - startInfo = new ProcessStartInfo - { - FileName = Path.Combine(Environment.SystemDirectory, Cmd), - Arguments = $"/c {GetTokenCommand} {ResourceArgumentName} {resource}" - }; - - // Default install location for Az CLI is included. If developer has installed to non-default location, the path can be specified using AzureCliPath variable. - startInfo.EnvironmentVariables["PATH"] = $"{Environment.GetEnvironmentVariable(AzureCliPath)};{_azureCliDefaultPathWindows}"; -#else - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - startInfo = new ProcessStartInfo - { - FileName = Path.Combine(EnvironmentHelper.SystemDirectory, Cmd), - Arguments = $"/c {GetTokenCommand} {ResourceArgumentName} {resource}" - }; - - startInfo.Environment["PATH"] = $"{Environment.GetEnvironmentVariable(AzureCliPath)};{_azureCliDefaultPathWindows}"; - } - else - { - startInfo = new ProcessStartInfo - { - FileName = Bash, - Arguments = $"{GetTokenCommand} {ResourceArgumentName} {resource}" - }; - - startInfo.Environment["PATH"] = $"{Environment.GetEnvironmentVariable(AzureCliPath)}:{AzureCliDefaultPath}"; - } -#endif - return startInfo; - } - } -} diff --git a/src/AppAuthentication/Constants.cs b/src/AppAuthentication/Constants.cs deleted file mode 100644 index 7371676..0000000 --- a/src/AppAuthentication/Constants.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace AppAuthentication -{ - internal static class Constants - { - public const string CLIToolName = "appauthentication"; - - // MSI related constants - public static readonly string MsiAppServiceEndpointEnv = "MSI_ENDPOINT"; - - public static readonly string MsiAppServiceSecretEnv = "MSI_SECRET"; - - public static readonly string MsiContainerUrl = "host.docker.internal"; - - public static readonly string MsiLocalhostUrl = "localhost"; - - public static readonly string HostUrl = "http://{0}:{1}/"; - - public static readonly string MsiEndpoint = "oauth2/token"; - - public static readonly string AzureAuthConnectionStringEnv = "AzureServicesAuthConnectionString"; - - public static readonly string MsiRunAsApp = "RunAs=App;"; - - // https://docs.microsoft.com/en-us/azure/key-vault/service-to-service-authentication#connection-string-support - // RunAs=Developer; DeveloperTool=AzureCli - // RunAs=Developer; DeveloperTool=VisualStudio - } -} diff --git a/src/AppAuthentication/Dockerfile b/src/AppAuthentication/Dockerfile deleted file mode 100644 index 74b01fd..0000000 --- a/src/AppAuthentication/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -FROM mcr.microsoft.com/dotnet/core/runtime:3.1 AS base -WORKDIR /app - -FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build -WORKDIR /src -COPY ["src/AppAuthentication/AppAuthentication.csproj", "src/AppAuthentication/"] -COPY ["src/Bet.Extensions.Logging/Bet.Extensions.Logging.csproj", "src/Bet.Extensions.Logging/"] -COPY ["src/Bet.Extensions/Bet.Extensions.csproj", "src/Bet.Extensions/"] -COPY ["src/Bet.AspNetCore/Bet.AspNetCore.csproj", "src/Bet.AspNetCore/"] -COPY ["src/Bet.Extensions.Options/Bet.Extensions.Options.csproj", "src/Bet.Extensions.Options/"] -RUN dotnet restore "src/AppAuthentication/AppAuthentication.csproj" -COPY . . -WORKDIR "/src/src/AppAuthentication" -RUN dotnet build "AppAuthentication.csproj" -c Release -f -o /app/build - -FROM build AS publish -RUN dotnet publish "AppAuthentication.csproj" -c Release -f -o /app/publish - -FROM base AS final -WORKDIR /app -COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "AppAuthentication.dll"] -CMD ["run", "--verbose:debug"] - diff --git a/src/AppAuthentication/Dockerfile.original b/src/AppAuthentication/Dockerfile.original deleted file mode 100644 index 652c399..0000000 --- a/src/AppAuthentication/Dockerfile.original +++ /dev/null @@ -1,37 +0,0 @@ - -# BUILD: docker build --rm -f "src\AppAuthentication\Dockerfile" -t appauthentication:latest . - -FROM mcr.microsoft.com/dotnet/core/sdk:3.0 as build -WORKDIR /app - -# copy csproj and restore as distinct layers -COPY ./build ./build -COPY ./Directory.Build.props ./Directory.Build.props -COPY ./Directory.Build.targets ./Directory.Build.targets - -COPY ./src/AppAuthentication/AppAuthentication.csproj ./AppAuthentication/AppAuthentication.csproj -COPY ./src/Bet.Extensions/Bet.Extensions.csproj ./Bet.Extensions/Bet.Extensions.csproj -COPY ./src/Bet.AspNetCore/Bet.AspNetCore.csproj ./Bet.AspNetCore/Bet.AspNetCore.csproj -COPY ./src/Bet.Extensions.Logging/Bet.Extensions.Logging.csproj ./Bet.Extensions.Logging/Bet.Extensions.Logging.csproj -COPY ./src/Bet.Extensions.Options/Bet.Extensions.Options.csproj ./Bet.Extensions.Options/Bet.Extensions.Options.csproj - -WORKDIR /app/AppAuthentication - -RUN dotnet restore AppAuthentication.csproj - -# copy everything else and build app -COPY ./src/AppAuthentication/ ./AppAuthentication/ -COPY ./src/Bet.Extensions/ ./Bet.Extensions/ -COPY ./src/Bet.AspNetCore/ ./Bet.AspNetCore/ -COPY ./src/Bet.Extensions.Logging/ ./Bet.Extensions.Logging/ -COPY ./src/Bet.Extensions.Options/ ./Bet.Extensions.Options/ -COPY .git ./.git - -RUN dotnet build AppAuthentication.csproj -c Release -f netcoreapp2.2 \ - && /p:Version=1.0.0 -o out - -FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 AS runtime -WORKDIR /app -COPY --from=build /app/AppAuthentication/out ./ -ENTRYPOINT ["dotnet", "AppAuthentication.dll", "--verbose:debug"] - diff --git a/src/AppAuthentication/EnvironmentHostedService.cs b/src/AppAuthentication/EnvironmentHostedService.cs deleted file mode 100644 index 8a1c120..0000000 --- a/src/AppAuthentication/EnvironmentHostedService.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; - -namespace AppAuthentication -{ - internal class EnvironmentHostedService : IHostedService - { - private readonly WebHostBuilderOptions _options; - private readonly ILogger _logger; - - public EnvironmentHostedService( - WebHostBuilderOptions options, - ILogger logger) - { - _options = options; - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - - if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, EnvironmentVariableTarget.User)) && - !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, EnvironmentVariableTarget.User))) - { - _logger.LogTrace("{serviceName} resetting User Environment variables.", nameof(EnvironmentHostedService)); - ResetVariables(); - } - } - - public Task StartAsync(CancellationToken cancellationToken) - { - var domain = _options.IsLocal ? Constants.MsiLocalhostUrl : Constants.MsiContainerUrl; - - var envMsiUrl = $"{string.Format(Constants.HostUrl, domain, _options.Port)}{Constants.MsiEndpoint}"; - - if (_options.IsLocal) - { - Environment.SetEnvironmentVariable( - Constants.AzureAuthConnectionStringEnv, - Constants.MsiRunAsApp, - EnvironmentVariableTarget.User); - } - - Environment.SetEnvironmentVariable( - Constants.MsiAppServiceEndpointEnv, - envMsiUrl, - EnvironmentVariableTarget.User); - - Environment.SetEnvironmentVariable( - Constants.MsiAppServiceSecretEnv, - _options.SecretId, - EnvironmentVariableTarget.User); - - _logger.LogTrace( - "{serviceName} ended setting up User Environment variables {url}-{secret}", - nameof(EnvironmentHostedService), - envMsiUrl, - _options.SecretId); - - return Task.CompletedTask; - } - - public Task StopAsync(CancellationToken cancellationToken) - { - // Delete the environment variables - ResetVariables(); - - _logger.LogTrace("{serviceName} cleared up User Environment variables", nameof(EnvironmentHostedService)); - return Task.CompletedTask; - } - - internal static void ResetVariables() - { - Environment.SetEnvironmentVariable(Constants.MsiAppServiceEndpointEnv, null, EnvironmentVariableTarget.User); - Environment.SetEnvironmentVariable(Constants.MsiAppServiceSecretEnv, null, EnvironmentVariableTarget.User); - Environment.SetEnvironmentVariable(Constants.AzureAuthConnectionStringEnv, null, EnvironmentVariableTarget.User); - } - } -} diff --git a/src/AppAuthentication/Helpers/ConsoleHandler.cs b/src/AppAuthentication/Helpers/ConsoleHandler.cs deleted file mode 100644 index a69c04e..0000000 --- a/src/AppAuthentication/Helpers/ConsoleHandler.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Runtime.InteropServices; -using System.Xml.Linq; - -namespace AppAuthentication.Helpers -{ - internal static class ConsoleHandler - { - internal static Process OpenBrowser(string url) - { - try - { - return Process.Start(url); - } - catch - { - // hack because of this: https://github.com/dotnet/corefx/issues/10361 - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - url = url.Replace("&", "^&"); - return Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true }); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) - { - return Process.Start("xdg-open", url); - } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - { - return Process.Start("open", url); - } - else - { - throw; - } - } - } - - internal static string GetUserSecretsId() - { - var files = Directory.GetFiles("./", "*.csproj"); - if (files.Length == 0) - { - throw new Exception("This command must be run in a project directory"); - } - - var file = XElement.Load(files[0]); - var groups = file.Elements(XName.Get("PropertyGroup")); - foreach (var group in groups) - { - var secret = group.Element("UserSecretsId"); - if (secret != null) - { - return secret.Value; - } - } - - throw new Exception("The UserSecretsId element was not found in your csproj. Please ensure it has been configured."); - } - - internal static int GetRandomUnusedPort() - { - TcpListener listener = null; - - try - { - listener = new TcpListener(IPAddress.Loopback, 5050); - listener.Start(); - } - catch (Exception) - { - listener = new TcpListener(IPAddress.Loopback, 0); - listener.Start(); - } - - var port = ((IPEndPoint)listener.LocalEndpoint).Port; - listener.Stop(); - return port; - } - } -} diff --git a/src/AppAuthentication/Helpers/EnvironmentHelper.cs b/src/AppAuthentication/Helpers/EnvironmentHelper.cs deleted file mode 100644 index 52963c4..0000000 --- a/src/AppAuthentication/Helpers/EnvironmentHelper.cs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Runtime.InteropServices; -using System.Text; - -namespace AppAuthentication.Helpers -{ - /// - /// Method to get system directory. This method has been added to .NET Standard 2.0, but since we target 1.4, need to write it. - /// Gets the system directory to get the install path for Azure CLI. - /// - internal sealed class EnvironmentHelper - { - [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = false)] - private static extern int GetSystemDirectoryW([Out] StringBuilder lpBuffer, int jSize); - - private const int MaxShortPath = 260; - - public static string SystemDirectory - { - get - { - var sb = new StringBuilder(); - if (GetSystemDirectoryW(sb, MaxShortPath) == 0) - { - throw new Exception("Unable to get system directory"); - } - - return sb.ToString(); - } - } - } -} diff --git a/src/AppAuthentication/Helpers/JsonHelper.cs b/src/AppAuthentication/Helpers/JsonHelper.cs deleted file mode 100644 index 224fe37..0000000 --- a/src/AppAuthentication/Helpers/JsonHelper.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System.IO; -using System.Runtime.Serialization.Json; - -namespace AppAuthentication.Helpers -{ - /// - /// To deserialize JSON response from token providers. - /// - internal static class JsonHelper - { - internal static T Deserialize(byte[] byteArray) - { - using (var memoryStream = new MemoryStream(byteArray)) - { - var ser = new DataContractJsonSerializer(typeof(T)); - return (T)ser.ReadObject(memoryStream); - } - } - } -} diff --git a/src/AppAuthentication/Helpers/UriHelper.cs b/src/AppAuthentication/Helpers/UriHelper.cs deleted file mode 100644 index 3c54a37..0000000 --- a/src/AppAuthentication/Helpers/UriHelper.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; - -namespace AppAuthentication.Helpers -{ -#pragma warning disable RCS1102 // Make class static. - internal class UriHelper -#pragma warning restore RCS1102 // Make class static. - { - /// - /// Given an Azure AD authority URL, returns the instance URL from it. - /// - /// Azure AD authority e.g. https://login.microsoftonline.com/tenantID. - /// Instance URL if the authority is valid, else null. - internal static string GetAzureAdInstanceByAuthority(string authority) - { - if (!string.IsNullOrWhiteSpace(authority)) - { - if (Uri.TryCreate(authority, UriKind.Absolute, out var authorityUri)) - { - if (authorityUri.Scheme != "https") - { - return null; - } - - var path = authorityUri.AbsolutePath.Substring(1); - if (string.IsNullOrWhiteSpace(path)) - { - return null; - } - - return $"https://{authorityUri.Host}/"; - } - } - - return null; - } - - /// - /// Given an Azure AD authority URL, returns the tenant from it. - /// - /// Azure AD authority e.g. https://login.microsoftonline.com/tenantID. - /// Tenant if the authority is valid and has tenant information, else null. - internal static string GetTenantByAuthority(string authority) - { - if (!string.IsNullOrWhiteSpace(authority)) - { - if (Uri.TryCreate(authority, UriKind.Absolute, out var authorityUri)) - { - if (authorityUri?.Segments.Length >= 2) - { - return authorityUri.Segments[1].TrimEnd('/'); - } - } - } - - return null; - } - } -} diff --git a/src/AppAuthentication/Helpers/ValidationHelper.cs b/src/AppAuthentication/Helpers/ValidationHelper.cs deleted file mode 100644 index 5ced1d6..0000000 --- a/src/AppAuthentication/Helpers/ValidationHelper.cs +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Text.RegularExpressions; - -namespace AppAuthentication.Helpers -{ -#pragma warning disable RCS1102 // Make class static. - internal class ValidationHelper -#pragma warning restore RCS1102 // Make class static. - { - /// - /// Validates a resource identifier. - /// - /// The resource to validate. - public static void ValidateResource(string resource) - { - if (!Regex.IsMatch(resource, @"^[0-9a-zA-Z-.:/]+$")) - { - throw new ArgumentException($"Resource {resource} is not in expected format. Only alphanumeric characters, [dot], [colon], [hyphen], and [forward slash] are allowed."); - } - } - } -} diff --git a/src/AppAuthentication/IAccessTokenProvider.cs b/src/AppAuthentication/IAccessTokenProvider.cs deleted file mode 100644 index 2385d42..0000000 --- a/src/AppAuthentication/IAccessTokenProvider.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System.Threading.Tasks; - -using AppAuthentication.Models; - -namespace AppAuthentication -{ - internal interface IAccessTokenProvider - { - Task GetAuthResultAsync(string resource, string authority); - } -} diff --git a/src/AppAuthentication/IConsoleExtensions.cs b/src/AppAuthentication/IConsoleExtensions.cs deleted file mode 100644 index 577d170..0000000 --- a/src/AppAuthentication/IConsoleExtensions.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using McMaster.Extensions.CommandLineUtils; - -namespace AppAuthentication -{ - public static class IConsoleExtensions - { - public static void WriteLine(this IConsole console, ConsoleColor color, string format, params object[] arg) - { - var originalColor = console.ForegroundColor; - console.ForegroundColor = color; - console.WriteLine(format, arg); - console.ForegroundColor = originalColor; - } - - public static void WriteLine(this IConsole console, ConsoleColor color, string format) - { - var originalColor = console.ForegroundColor; - console.ForegroundColor = color; - console.WriteLine(format); - console.ForegroundColor = originalColor; - } - } -} diff --git a/src/AppAuthentication/IProcessManager.cs b/src/AppAuthentication/IProcessManager.cs deleted file mode 100644 index 247d125..0000000 --- a/src/AppAuthentication/IProcessManager.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Diagnostics; -using System.Threading.Tasks; - -namespace AppAuthentication -{ - /// - /// Interface that helps mock invoking a process and getting the result from standard output and error streams. - /// - internal interface IProcessManager - { - Task ExecuteAsync(Process process); - } -} diff --git a/src/AppAuthentication/Models/AccessToken.cs b/src/AppAuthentication/Models/AccessToken.cs deleted file mode 100644 index 54a8560..0000000 --- a/src/AppAuthentication/Models/AccessToken.cs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Globalization; -using System.Runtime.Serialization; - -using AppAuthentication.Helpers; - -namespace AppAuthentication.Models -{ - /// - /// Used to hold the deserialized access token. - /// - [DataContract] - internal class AccessToken - { - private const char Base64PadCharacter = '='; - private const char Base64Character62 = '+'; - private const char Base64Character63 = '/'; - private const char Base64UrlCharacter62 = '-'; - private const char Base64UrlCharacter63 = '_'; - private static readonly string DoubleBase64PadCharacter = string.Format(CultureInfo.InvariantCulture, "{0}{0}", Base64PadCharacter); - - private string _accessToken; - - private const string TokenFormatExceptionMessage = "Access token is not in the expected format."; - - // These fields are assigned to by JSON deserialization - [DataMember(Name = "upn", IsRequired = false)] - public string Upn { get; private set; } - - [DataMember(Name = "tid", IsRequired = false)] - public string TenantId { get; private set; } - - [DataMember(Name = "email", IsRequired = false)] - public string Email { get; private set; } - - [DataMember(Name = "appid", IsRequired = false)] - public string AppId { get; private set; } - - [DataMember(Name = "exp", IsRequired = true)] - public long ExpiryTime { get; private set; } - - public static AccessToken Parse(string accessToken) - { - if (string.IsNullOrEmpty(accessToken)) - { - throw new ArgumentNullException(nameof(accessToken)); - } - - try - { - // Access token as 3 parts. We are interested in the second part, which has claims. - var splitStrings = accessToken.Split('.'); - - var token = JsonHelper.Deserialize(DecodeBytes(splitStrings[1])); - - token._accessToken = accessToken; - - return token; - } - catch (Exception exp) - { - throw new FormatException($"{TokenFormatExceptionMessage} Exception: {exp.Message}"); - } - } - - /// - /// Return the access token as-is. - /// - /// - public override string ToString() - { - return _accessToken; - } - - /// - /// Check if the token is about to expire. - /// - /// - public bool IsAboutToExpire() - { - // Current time represented in seconds since 1/1/1970 - var currentTime = (DateTime.UtcNow - UnixTimeEpoch).TotalSeconds; - - // If the expiration time is greater than current time by more than 5 minutes, it is not about to expire - if (ExpiryTime > currentTime + (5 * 60)) - { - return false; - } - - return true; - } - - internal static DateTimeOffset UnixTimeEpoch => new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - private static byte[] DecodeBytes(string arg) - { - var s = arg; - s = s.Replace(Base64UrlCharacter62, Base64Character62); - s = s.Replace(Base64UrlCharacter63, Base64Character63); - - switch (s.Length % 4) - { - // Pad - case 0: - break; // No pad chars in this case - case 2: - s += DoubleBase64PadCharacter; - break; // Two pad chars - case 3: - s += Base64PadCharacter; - break; // One pad char - default: - throw new ArgumentException("Illegal base64url string!", nameof(arg)); - } - - return Convert.FromBase64String(s); - } - } -} diff --git a/src/AppAuthentication/Models/AppAuthenticationResult.cs b/src/AppAuthentication/Models/AppAuthenticationResult.cs deleted file mode 100644 index ac24233..0000000 --- a/src/AppAuthentication/Models/AppAuthenticationResult.cs +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Runtime.Serialization; -using Microsoft.IdentityModel.Clients.ActiveDirectory; - -namespace AppAuthentication.Models -{ - /// - /// Contains access token and other results from a token request call. - /// - internal class AppAuthenticationResult - { - /// - /// The access token returned from the token request. - /// - [DataMember] - public string AccessToken { get; private set; } - - /// - /// The time when the access token expires. - /// - [DataMember] - public DateTimeOffset ExpiresOn { get; private set; } - - /// - /// The Resource URI of the receiving web service. - /// - [DataMember] - public string Resource { get; private set; } - - /// - /// Indicates the token type value. - /// - [DataMember] - public string TokenType { get; private set; } - - /// - /// Return true when access token is near expiration. - /// - /// - internal bool IsNearExpiry() - { - // If the expiration time is within the next 5 minutes, the token is about to expire - return ExpiresOn < DateTimeOffset.UtcNow.AddMinutes(5); - } - - internal static AppAuthenticationResult Create(TokenResponse response, TokenResponse.DateFormat dateFormat) - { - if (response == null) - { - throw new ArgumentNullException(nameof(response)); - } - - var expiresOnString = response.ExpiresOn ?? response.ExpiresOn2; - var expiresOn = DateTimeOffset.MinValue; - - switch (dateFormat) - { - case TokenResponse.DateFormat.DateTimeString: - expiresOn = DateTimeOffset.Parse(expiresOnString); - break; - case TokenResponse.DateFormat.Unix: - var seconds = double.Parse(expiresOnString); - expiresOn = Models.AccessToken.UnixTimeEpoch.AddSeconds(seconds); - break; - } - - var result = new AppAuthenticationResult() - { - AccessToken = response.AccessToken ?? response.AccessToken2, - ExpiresOn = expiresOn, - Resource = response.Resource, - TokenType = response.TokenType ?? response.TokenType2 - }; - - return result; - } - - internal static AppAuthenticationResult Create(AuthenticationResult authResult) - { - if (authResult == null) - { - throw new ArgumentNullException(nameof(authResult)); - } - - var result = new AppAuthenticationResult() - { - AccessToken = authResult.AccessToken, - ExpiresOn = authResult.ExpiresOn - }; - - return result; - } - - // For unit testing - internal static AppAuthenticationResult Create(string accessToken) - { - if (string.IsNullOrEmpty(accessToken)) - { - throw new ArgumentNullException(nameof(accessToken)); - } - - var tokenObj = Models.AccessToken.Parse(accessToken); - - var result = new AppAuthenticationResult - { - AccessToken = accessToken, - ExpiresOn = Models.AccessToken.UnixTimeEpoch.AddSeconds(tokenObj.ExpiryTime) - }; - - return result; - } - } -} diff --git a/src/AppAuthentication/Models/AuthenticationToken.cs b/src/AppAuthentication/Models/AuthenticationToken.cs deleted file mode 100644 index 3eeac18..0000000 --- a/src/AppAuthentication/Models/AuthenticationToken.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Newtonsoft.Json; - -namespace AppAuthentication.Models -{ - internal class AuthenticationToken - { - [JsonProperty("token_type")] - public string TokenType { get; set; } - - [JsonProperty("scope")] - public string Scope { get; set; } - - [JsonProperty("expires_in")] - public string ExpiresIn { get; set; } - - [JsonProperty("ext_expires_in")] - public string ExtExpiresIn { get; set; } - - [JsonProperty("expires_on")] - public string ExpiresOn { get; set; } - - [JsonProperty("not_before")] - public string NotBefore { get; set; } - - [JsonProperty("resource")] - public string Resource { get; set; } - - [JsonProperty("access_token")] - public string AccessToken { get; set; } - - [JsonProperty("refresh_token")] - public string RefreshToken { get; set; } - - [JsonProperty("id_token")] - public string IdToken { get; set; } - } -} diff --git a/src/AppAuthentication/Models/HttpBearerChallenge.cs b/src/AppAuthentication/Models/HttpBearerChallenge.cs deleted file mode 100644 index 976b85c..0000000 --- a/src/AppAuthentication/Models/HttpBearerChallenge.cs +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; - -namespace AppAuthentication.Models -{ - /// - /// Helper class that handles HTTP Bearer challenges. - /// - internal class HttpBearerChallenge - { - private const string AuthorizationParameter = "authorization"; - private const string AuthorizationUriParameter = "authorization_uri"; - private const string ResourceParameter = "resource"; - private const string ScopeParameter = "scope"; - private const string Bearer = "Bearer"; - - public string AuthorizationServer { get; private set; } - - public string Resource { get; private set; } - - public string Scope { get; private set; } - - /// - /// Parses an HTTP Bearer challenge from Key Vault. - /// - /// The value of the WWW-Authenticate header to parse. - /// - internal static HttpBearerChallenge Parse(string challenge) - { - if (!ValidateChallenge(challenge)) - { - return null; - } - - var parameters = GetChallengeParameters(challenge); - - string authorization = null; - string resource = null; - string scope = null; - - if (parameters.ContainsKey(AuthorizationParameter)) - { - authorization = parameters[AuthorizationParameter]; - } - else if (parameters.ContainsKey(AuthorizationUriParameter)) - { - authorization = parameters[AuthorizationUriParameter]; - } - - if (parameters.ContainsKey(ResourceParameter)) - { - resource = parameters[ResourceParameter]; - } - - if (parameters.ContainsKey(ScopeParameter)) - { - scope = parameters[ScopeParameter]; - } - - // scope is not a required parameter - if (authorization == null || resource == null) - { - return null; - } - - return new HttpBearerChallenge(authorization, resource, scope); - } - - private static bool ValidateChallenge(string challenge) - { - if (string.IsNullOrEmpty(challenge)) - { - return false; - } - - if (!challenge.Trim().StartsWith(Bearer + " ")) - { - return false; - } - - return true; - } - - private static Dictionary GetChallengeParameters(string challenge) - { - // first, trim the challenge's Bearer prefix - challenge = challenge.Trim().Substring(Bearer.Length + 1); - - // then parse the key-value pairs into a dictionary - var parameters = new Dictionary(); - var keyValuePairs = challenge.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - if (keyValuePairs != null && keyValuePairs.Length > 0) - { - for (var i = 0; i < keyValuePairs.Length; i++) - { - var keyValuePair = keyValuePairs[i].Split('='); - - if (keyValuePair.Length == 2) - { - var key = keyValuePair[0].Trim().Trim('"'); - var value = keyValuePair[1].Trim().Trim('"'); - - if (!string.IsNullOrEmpty(key)) - { - parameters[key] = value; - } - } - } - } - - return parameters; - } - - /// - /// Initializes a new instance of the class. - /// Create instance of HTTP Bearer Challenge. - /// - /// - /// - /// - private HttpBearerChallenge(string authorization, string resource, string scope) - { - AuthorizationServer = authorization; - Resource = resource; - Scope = scope; - } - } -} diff --git a/src/AppAuthentication/Models/TokenResponse.cs b/src/AppAuthentication/Models/TokenResponse.cs deleted file mode 100644 index 553d042..0000000 --- a/src/AppAuthentication/Models/TokenResponse.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Runtime.Serialization; -using System.Text; - -using AppAuthentication.Helpers; - -namespace AppAuthentication.Models -{ - /// - /// Used to hold the deserialized token response. - /// - [DataContract] - internal class TokenResponse - { - private const string TokenResponseFormatExceptionMessage = "Token response is not in the expected format."; - - internal enum DateFormat - { - Unix, - DateTimeString - } - - // VS token service and MSI endpoint return access_token - [DataMember(Name = "access_token", IsRequired = false)] - public string AccessToken { get; private set; } - - // Azure CLI returns accessToken - [DataMember(Name = "accessToken", IsRequired = false)] - public string AccessToken2 { get; private set; } - - // VS token service and MSI endpoint return expires_on - [DataMember(Name = "expires_on", IsRequired = false)] - public string ExpiresOn { get; private set; } - - // Azure CLI returns expiresOn - [DataMember(Name = "expiresOn", IsRequired = false)] - public string ExpiresOn2 { get; private set; } - - [DataMember(Name = "error_description", IsRequired = false)] - public string ErrorDescription { get; private set; } - - // VS token service returns resource - [DataMember(Name = "resource", IsRequired = false)] - public string Resource { get; private set; } - - // VS token service and MSI endpoint return token_type - [DataMember(Name = "token_type", IsRequired = false)] - public string TokenType { get; private set; } - - // Azure CLI returns tokenType - [DataMember(Name = "tokenType", IsRequired = false)] - public string TokenType2 { get; private set; } - - /// - /// Parse token response returned from OAuth provider. - /// While more fields are returned, we only need the access token. - /// - /// This is the response received from OAuth endpoint that has the access token in it. - /// - public static TokenResponse Parse(string tokenResponse) - { - try - { - return JsonHelper.Deserialize(Encoding.UTF8.GetBytes(tokenResponse)); - } - catch (Exception exp) - { - throw new FormatException($"{TokenResponseFormatExceptionMessage} Exception:: {exp}"); - } - } - } -} diff --git a/src/AppAuthentication/NonInteractiveAzureServiceTokenProviderBase.cs b/src/AppAuthentication/NonInteractiveAzureServiceTokenProviderBase.cs deleted file mode 100644 index 40ee9ab..0000000 --- a/src/AppAuthentication/NonInteractiveAzureServiceTokenProviderBase.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Microsoft.Azure.Services.AppAuthentication; - -namespace AppAuthentication -{ - /// - /// Base class from which other token providers derive. - /// - internal abstract class NonInteractiveAzureServiceTokenProviderBase - { - public string ConnectionString; - public Principal PrincipalUsed; - } -} diff --git a/src/AppAuthentication/ProcessManager.cs b/src/AppAuthentication/ProcessManager.cs deleted file mode 100644 index 66644da..0000000 --- a/src/AppAuthentication/ProcessManager.cs +++ /dev/null @@ -1,107 +0,0 @@ -using System; -using System.Diagnostics; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using Microsoft.Extensions.Logging; - -namespace AppAuthentication -{ - /// - /// Invokes a process and returns the result from the standard output or error streams. - /// This is used to invoke az account get-access-token to get a token for local development. - /// - internal class ProcessManager : IProcessManager - { - public ProcessManager(ILogger logger) - { - _logger = logger; - } - - // Timeout used such that if process does not respond in this time, it is killed. - private readonly TimeSpan _timeOutDuration = TimeSpan.FromSeconds(20); - - // Error when process took too long. - private const string TimeOutError = "Process took too long to return the token."; - private readonly ILogger _logger; - - /// - /// Execute the given process and return the result. - /// - /// The process to execute. - /// Returns the process output from the standard output stream. - public Task ExecuteAsync(Process process) - { - var tcs = new TaskCompletionSource(); - var output = new StringBuilder(); - var error = new StringBuilder(); - - process.EnableRaisingEvents = true; - process.StartInfo.UseShellExecute = false; - process.StartInfo.RedirectStandardOutput = true; - process.StartInfo.RedirectStandardError = true; - process.StartInfo.CreateNoWindow = true; - - process.OutputDataReceived += (sender, e) => - { - if (!string.IsNullOrEmpty(e.Data)) - { - output.AppendLine(e.Data); - - _logger.LogDebug("Received data: {data}", e.Data); - } - }; - - process.ErrorDataReceived += (sender, e) => - { - if (!string.IsNullOrEmpty(e.Data)) - { - error.AppendLine(e.Data); - _logger.LogError("Received data: {data}", e.Data); - } - }; - - // If process exits, set the result - process.Exited += (sender, args) => - { - var success = process.ExitCode == 0; - - if (success) - { - tcs.TrySetResult(output.ToString()); - } - else - { - tcs.TrySetResult(error.ToString()); - _logger.LogError("{ex}", error); - } - }; - - // Used to kill the process if it doesn not respond for the given duration. - using (var cancellationTokenSource = new CancellationTokenSource(_timeOutDuration)) - { - var cancellationToken = cancellationTokenSource.Token; - cancellationToken.Register(() => - { - if (!tcs.Task.IsCompleted) - { - if (!process.HasExited) - { - process.Kill(); - } - - tcs.TrySetException(new TimeoutException(TimeOutError)); - } - }); - - process.Start(); - - process.BeginOutputReadLine(); - process.BeginErrorReadLine(); - - return tcs.Task; - } - } - } -} diff --git a/src/AppAuthentication/Program.cs b/src/AppAuthentication/Program.cs deleted file mode 100644 index c4d2aee..0000000 --- a/src/AppAuthentication/Program.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Diagnostics; -using System.Drawing; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; - -using McMaster.Extensions.CommandLineUtils; - -using Console = Colorful.Console; - -namespace AppAuthentication -{ - [Command( - Name = Constants.CLIToolName, - Description = "Cli tool to help with Docker/Kuberbetes Local Containers Development for Microsoft Azure MSI Identity authentication.", - UnrecognizedArgumentHandling = UnrecognizedArgumentHandling.Throw, - AllowArgumentSeparator = true)] - [Subcommand(typeof(RunCommand))] - [HelpOption("-?")] - [VersionOptionFromMember("--version", MemberName = nameof(GetVersion))] - public class Program - { - private static async Task Main(string[] args) - { - using (var mutex = new Mutex(true, Constants.CLIToolName, out var canCreateNew)) - { - if (canCreateNew) - { - return await CommandLineApplication.ExecuteAsync(args); - } - else - { - Console.WriteLine($"Only one instance of the {Constants.CLIToolName} tool can be run at the same time.", Color.Red); - return -1; - } - } - } - - private Task OnExecuteAsync(CommandLineApplication app, IConsole console) - { - Console.WriteAscii(Constants.CLIToolName, Colorful.FigletFont.Default); - - console.WriteLine(); - console.WriteLine(ConsoleColor.Green, "This tool requires to have Visual Studio.NET or Azure CLI Installed on Host Machine."); - - console.WriteLine(); - console.WriteLine(ConsoleColor.Red, "You must specify at a subcommand."); - - console.WriteLine(); - app.ShowHelp(); - - return Task.FromResult(1); - } - - private static string GetVersion() - { - return typeof(Program).Assembly.GetCustomAttribute().InformationalVersion; - } - } -} diff --git a/src/AppAuthentication/Properties/launchSettings.json b/src/AppAuthentication/Properties/launchSettings.json deleted file mode 100644 index 20b7158..0000000 --- a/src/AppAuthentication/Properties/launchSettings.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "profiles": { - "AppAuthentication": { - "commandName": "Project", - "commandLineArgs": "run --verbose:debug" - }, - "Docker": { - "commandName": "Docker" - } - } -} \ No newline at end of file diff --git a/src/AppAuthentication/README.md b/src/AppAuthentication/README.md deleted file mode 100644 index 288a655..0000000 --- a/src/AppAuthentication/README.md +++ /dev/null @@ -1,115 +0,0 @@ -# AppAuthentication Cli Tool - -[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](https://raw.githubusercontent.com/kdcllc/Bet.AspNetCore/master/LICENSE) -[![Build status](https://ci.appveyor.com/api/projects/status/fo9rakj7s7uhs3ij?svg=true)](https://ci.appveyor.com/project/kdcllc/bet-aspnetcore) -[![NuGet](https://img.shields.io/nuget/v/appauthentication.svg)](https://www.nuget.org/packages?q=appauthentication ) -![Nuget](https://img.shields.io/nuget/dt/appauthentication ) -[![feedz.io](https://img.shields.io/badge/endpoint.svg?url=https://f.feedz.io/kdcllc/bet-aspnetcore/shield/AppAuthentication/latest)](https://f.feedz.io/kdcllc/bet-aspnetcore/packages/AppAuthentication/latest/download) - -*Note: Pre-release packages are distributed via [feedz.io](https://f.feedz.io/kdcllc/bet-aspnetcore/nuget/index.json).* - -This dotnet cli tool provides ability to accesses Azure Key Vault/ Azure Blob Storage in Docker Container when this container is ran on the local machine. -In addition if needed this cli tool can be enabled to retrieve tokens for local machine development. -It can be utilized in conjunction with VSCode Remote Extensions. - -The tool was tested on: - -- On Windows 10 Visual Studio.NET or AzureCli Providers. - -- On Linux with Azure Cli only. Install Azure Cli `curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash` - - -![appauthentication debug in docker](../../img/appauthentication-docker-debug.gif) - -## Install - -```bash - dotnet tool install --global appauthentication -``` - -## Usage with Local Docker development - -1. Update `Docker-Compose.yml` - -Before running this cli tool please make sure that the docker-compose file for the project has the environment variables - -```yml - MSI_ENDPOINT={MSI_ENDPOINT} - MSI_SECRET={MSI_SECRET} -``` - -This can be done via `docker-compose.override.yml` like so: - -```yml - - environment: - - MSI_ENDPOINT=${MSI_ENDPOINT} - - MSI_SECRET=${MSI_SECRET} -``` - -2. Install dotnet cli `appauthentication` tool - -```cmd - dotnet tool install --global appauthentication -``` - -Notes: - -- Make sure that all of the existing `Containers` and `Images` are removed from the system as well. - -- Go to Tools --> Options --> Azure Service Authentication --> Account Selection and Select the account that will be used for authenticating with your company's Azure Vault. - -- Retrieve Azure AD Directory Id by navigating to [Azure Portal](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Properties) - -- Run this CLI tool with the following sample command: - -`Default provider is AzureCli provider` - -```bash - appauthentication run -a https://login.microsoftonline.com/{companyDirectoryGuidId} -v - - #or - - appauthentication run -a {companyDirectoryGuidId} -v - - - #or azure cli - - appauthentication run -a {companyDirectoryGuidId} -v --token-provider VisualStudio - -``` - -If AzureCli provider is used please make sure you log into Azure with the following commands: - -```bash - az login - az account list - az account set –subscription “YourSubscriptionName” -``` - -- Now you are ready to run your docker container locally and use Azure Vault. - -## Tools possible switches - -- --authority:authid or -a:authid -- --verbose:debug -- --token-provider:AzureCli or -t:VisualStudio (default VisualStudio) -- --environment:Production or -e:Development -- --resource:test or -r:someresource -- --port:1010 or -p:2323 -- --config:file or -c:appsettings.config -- --fix or -f -- --local or -l (default Docker) - - -## Testing from CLI - -```bash - dotnet run run --- -verbose:debug -``` - -## Reference - -- Using without 2.2 `ENV DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX=2` - -- To learn how to use this tool in real life example refer to [K8.DotNetCore.Workshop](https://github.com/kdcllc/K8.DotNetCore.Workshop) \ No newline at end of file diff --git a/src/AppAuthentication/RunCommand.cs b/src/AppAuthentication/RunCommand.cs deleted file mode 100644 index 1a3aa5d..0000000 --- a/src/AppAuthentication/RunCommand.cs +++ /dev/null @@ -1,212 +0,0 @@ -using System; -using System.Drawing; -using System.Globalization; -using System.Threading.Tasks; - -using AppAuthentication.AzureCli; -using AppAuthentication.Helpers; -using AppAuthentication.Models; -using AppAuthentication.VisualStudio; - -using McMaster.Extensions.CommandLineUtils; - -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -using Newtonsoft.Json; - -using Console = Colorful.Console; - -namespace AppAuthentication -{ - [Command( - "run", - Description = "Runs instance of the local server that returns authentication tokens.", - UnrecognizedArgumentHandling = UnrecognizedArgumentHandling.Throw, - AllowArgumentSeparator = true)] - [HelpOption("--help")] - internal class RunCommand - { - [Option( - "-a|--authority", - Description = "Authority Azure TenantId or Azure Directory ID")] - public string Authority { get; private set; } - - [Option( - "-r|--resource", - Description = "Resource to authenticate against. Provided https://login.microsoftonline.com/{tenantId}. Default set to https://vault.azure.net/")] - public string Resource { get; private set; } - - /// - /// Property types of ValueTuple{bool,T} translate to CommandOptionType.SingleOrNoValue. - /// Input | Value - /// ------------------------|-------------------------------- - /// (none) | (false, default(LogLevel)) - /// --verbose | (true, LogLevel.Information) - /// --verbose:information | (true, LogLevel.Information) - /// --verbose:debug | (true, LogLevel.Debug) - /// --verbose:trace | (true, LogLevel.Trace). - /// - [Option(Description = "Allows Verbose logging for the tool. Enable this to get tracing information. Default is false.")] - public (bool hasValue, LogLevel level) Verbose { get; } = (false, LogLevel.Error); - - [Option( - "-e|--environment", - Description = "Specify Hosting Environment Name for the cli tool execution. The Default is Development")] - public string HostingEnvironment { get; private set; } - - [Option( - "-p|--port", - Description = "Specify Web Host port number otherwise it is automatically generated. The Default port if open is 5050.")] - public int? Port { get; private set; } - - [Option( - "-c|--config", - Description = "Allows to specify a configuration file besides appsettings.json to be specified. The Default appsetting.json located in the execution path.")] - public string ConfigFile { get; private set; } - - [Option( - "-t|--token-provider", - Description = "The Azure CLI Access Token Provider to retrieve the Authentication Token. The Default provider is AzureCli.")] - public TokenProvider TokenProvider { get; } = TokenProvider.AzureCli; - - [Option("-f|--fix", Description = "Fix command resets Environment Variables.")] - public bool Fix { get; private set; } - - [Option( - "-l|--local", - Description = "Setup MSI_ENDPOINT to be pointing to localhost. The Default is set to support Docker Containers only.")] - public bool Local { get; set; } - - public string[] RemainingArguments { get; } - - private async Task OnExecuteAsync(IConsole console) - { - if (Fix) - { - EnvironmentHostedService.ResetVariables(); - } - - var builderConfig = new WebHostBuilderOptions - { - Authority = Authority, - HostingEnvironment = !string.IsNullOrWhiteSpace(HostingEnvironment) ? HostingEnvironment : "Development", - Resource = !string.IsNullOrWhiteSpace(Resource) ? Resource : "https://vault.azure.net/", - Verbose = Verbose.hasValue, - Level = Verbose.level, - ConfigFile = ConfigFile, - SecretId = Guid.NewGuid().ToString(), - IsLocal = Local - }; - - try - { - builderConfig.Port = Port ?? ConsoleHandler.GetRandomUnusedPort(); - - console.WriteLine( - ConsoleColor.Blue, - "[{0}][Running on Port]:[{1}]", - nameof(AppAuthentication).ToUpperInvariant(), - builderConfig.Port); - - var webHost = WebHostBuilderExtensions.CreateDefaultBuilder(builderConfig) - - // header: Secret = MSI_SECRET - // ?resource=clientid=&api-version=2017-09-01 - .Configure(app => - { - app.MapWhen( - context => context.Request.Path.Value.Contains("/oauth2"), - (IApplicationBuilder pp) => - { - pp.Map("/oauth2/token", (IApplicationBuilder ppa) => - { - ppa.Run(async (context) => - { - var logger = app.ApplicationServices.GetRequiredService>(); - - try - { - var provider = app.ApplicationServices.GetRequiredService(); - - var requestResource = context.Request.Query["resource"].ToString(); - - logger.LogDebug("[Request][QueryString][resource]:['{query}']", requestResource); - - var resource = !string.IsNullOrWhiteSpace(requestResource) ? requestResource : builderConfig.Resource; - - var token = await provider.GetAuthResultAsync(resource, builderConfig.Authority); - - var jsonResponse = JsonConvert.SerializeObject(token); - - context.Response.Headers.Add("content-type", "application/json"); - - logger.LogDebug("Sending response"); - - await context.Response.WriteAsync(jsonResponse); - } - catch (Exception ex) - { - logger.LogError("Error occurred processing the request: {0}", ex); - - context.Response.StatusCode = StatusCodes.Status500InternalServerError; - - await context.Response.WriteAsync(ex.ToString()); - } - }); - }); - }); - - app.Run(context => - { - context.Response.Headers.Add("content-type", "text/html"); - return context.Response.WriteAsync(@"hello world"); - }); - }) - .ConfigureServices((hostingContext, services) => - { - services.AddSingleton(builderConfig); - services.AddHostedService(); - - switch (TokenProvider) - { - case TokenProvider.VisualStudio: - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); - return new VisualStudioAccessTokenProvider(new ProcessManager(logger)); - }); - - break; - case TokenProvider.AzureCli: - services.AddSingleton(sp => - { - var logger = sp.GetRequiredService>(); - return new AzureCliAccessTokenProvider(new ProcessManager(logger)); - }); - break; - } - }) - .Build(); - - await webHost.RunAsync(); - - return 0; - } - catch (Exception ex) - { - Console.WriteLine(ex.Message, Color.Red); - return -1; - } - } - } - - internal enum TokenProvider - { - VisualStudio, - AzureCli - } -} diff --git a/src/AppAuthentication/VisualStudio/VisualStudioAccessTokenProvider.cs b/src/AppAuthentication/VisualStudio/VisualStudioAccessTokenProvider.cs deleted file mode 100644 index 843290b..0000000 --- a/src/AppAuthentication/VisualStudio/VisualStudioAccessTokenProvider.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Threading.Tasks; - -using AppAuthentication.Helpers; -using AppAuthentication.Models; - -using Microsoft.Azure.Services.AppAuthentication; - -namespace AppAuthentication.VisualStudio -{ - internal class VisualStudioAccessTokenProvider : NonInteractiveAzureServiceTokenProviderBase, IAccessTokenProvider - { - private const string ResourceArgumentName = "--resource"; - private const string TenantArgumentName = "--tenant"; - - private const string LocalAppDataPathEnv = "LOCALAPPDATA"; // %USERPROFILE%\AppData\Local - private const string NoAppDataEnvironmentVariableError = "Environment variable LOCALAPPDATA not set."; - private const string TokenProviderFilePath = ".IdentityService\\AzureServiceAuth\\tokenprovider.json"; - private const string TokenProviderFileNotFound = "Visual Studio Token provider file not found at"; - - // Represents the token provider file, which has information about executable to call to get token. - private VisualStudioTokenProviderFile _visualStudioTokenProviderFile; - - // Allows for unit testing, by mocking IProcessManager - private readonly IProcessManager _processManager; - - internal VisualStudioAccessTokenProvider( - IProcessManager processManager, - VisualStudioTokenProviderFile visualStudioTokenProviderFile = null) - { - _visualStudioTokenProviderFile = visualStudioTokenProviderFile; - _processManager = processManager; - PrincipalUsed = new Principal { Type = "User" }; - } - - public async Task GetAuthResultAsync(string resource, string authority) - { - try - { - // Validate resource, since it gets sent as a command line argument to Visual Studio token provider. - ValidationHelper.ValidateResource(resource); - - _visualStudioTokenProviderFile = _visualStudioTokenProviderFile ?? GetTokenProviderFile(); - - // Get process start infos based on Visual Studio token providers - var processStartInfos = GetProcessStartInfos(_visualStudioTokenProviderFile, resource, UriHelper.GetTenantByAuthority(authority)); - - // To hold reason why token could not be acquired per token provider tried. - var exceptionDictionary = new Dictionary(); - - foreach (var startInfo in processStartInfos) - { - try - { - // For each of them, try to get token - var response = await _processManager - .ExecuteAsync(new Process { StartInfo = startInfo }) - .ConfigureAwait(false); - - var tokenResponse = TokenResponse.Parse(response); - - var accessToken = AccessToken.Parse(tokenResponse.AccessToken); - - PrincipalUsed.IsAuthenticated = true; - - if (accessToken != null) - { - // Set principal used based on the claims in the access token. - PrincipalUsed.UserPrincipalName = - !string.IsNullOrEmpty(accessToken.Upn) ? accessToken.Upn : accessToken.Email; - - PrincipalUsed.TenantId = accessToken.TenantId; - } - - var authResult = Models.AppAuthenticationResult.Create(tokenResponse, TokenResponse.DateFormat.DateTimeString); - - var authenticationToken = new AuthenticationToken - { - AccessToken = authResult.AccessToken, - TokenType = authResult.TokenType, - Resource = authResult.Resource, - ExpiresOn = authResult.ExpiresOn.ToString(), - ExpiresIn = accessToken.ExpiryTime.ToString(), - ExtExpiresIn = accessToken.ExpiryTime.ToString(), - RefreshToken = tokenResponse.AccessToken, - }; - - return authenticationToken; - } - catch (Exception exp) - { - // If token cannot be acquired using a token provider, try the next one - exceptionDictionary[Path.GetFileName(startInfo.FileName)] = exp.Message; - } - } - - // Could not acquire access token, throw exception - var message = string.Empty; - - // Include exception details for each token provider that was tried - foreach (var key in exceptionDictionary.Keys) - { - message += Environment.NewLine + - $"Exception for Visual Studio token provider {key} : {exceptionDictionary[key]} "; - } - - // Throw exception if none of the token providers worked - throw new Exception(message); - } - catch (Exception exp) - { - throw new Exception( - $"{nameof(VisualStudioAccessTokenProvider)} not able to obtain the token for {ConnectionString} , {resource} , {authority}, {exp.Message}"); - } - } - - /// - /// Gets the token provider file from user's local appdata folder. - /// - /// - private VisualStudioTokenProviderFile GetTokenProviderFile() - { - if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(LocalAppDataPathEnv))) - { - throw new Exception(NoAppDataEnvironmentVariableError); - } - - var tokenProviderPath = Path.Combine( - Environment.GetEnvironmentVariable(LocalAppDataPathEnv), - TokenProviderFilePath); - - if (!File.Exists(tokenProviderPath)) - { - throw new Exception($"{TokenProviderFileNotFound} \"{tokenProviderPath}\""); - } - - return VisualStudioTokenProviderFile.Parse(File.ReadAllText(tokenProviderPath)); - } - - /// - /// Gets a list of token provider executables to call to get token. - /// - /// Visual Studio Token provider file. - /// - /// - /// - private List GetProcessStartInfos( - VisualStudioTokenProviderFile visualStudioTokenProviderFile, - string resource, - string tenant = default) - { - var processStartInfos = new List(); - - foreach (var tokenProvider in visualStudioTokenProviderFile.TokenProviders) - { - // If file does not exist, the version of Visual Studio that set the token provider may be uninstalled. - if (File.Exists(tokenProvider.Path)) - { - var arguments = $"{ResourceArgumentName} {resource} "; - - if (tenant != default) - { - arguments += $"{TenantArgumentName} {tenant} "; - } - - // Add the arguments set in the token provider file. - if (tokenProvider.Arguments?.Count > 0) - { - arguments += string.Join(" ", tokenProvider.Arguments); - } - - var startInfo = new ProcessStartInfo - { - FileName = tokenProvider.Path, - Arguments = arguments - }; - - processStartInfos.Add(startInfo); - } - } - - return processStartInfos; - } - } -} diff --git a/src/AppAuthentication/VisualStudio/VisualStudioTokenProvider.cs b/src/AppAuthentication/VisualStudio/VisualStudioTokenProvider.cs deleted file mode 100644 index a3cf463..0000000 --- a/src/AppAuthentication/VisualStudio/VisualStudioTokenProvider.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System.Collections.Generic; -using System.Runtime.Serialization; - -namespace AppAuthentication.VisualStudio -{ - /// - /// Used to de-serialize the Visual Studio token provider file. - /// - [DataContract] - internal class VisualStudioTokenProvider - { - [DataMember(Name = "Path", IsRequired = true)] - public string Path; - - [DataMember(Name = "Arguments", IsRequired = false)] - public List Arguments; - - [DataMember(Name = "Preference", IsRequired = true)] - public int Preference; - } -} diff --git a/src/AppAuthentication/VisualStudio/VisualStudioTokenProviderFile.cs b/src/AppAuthentication/VisualStudio/VisualStudioTokenProviderFile.cs deleted file mode 100644 index 7c22bac..0000000 --- a/src/AppAuthentication/VisualStudio/VisualStudioTokenProviderFile.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.Serialization; -using System.Text; - -using AppAuthentication.Helpers; - -namespace AppAuthentication.VisualStudio -{ - [DataContract] - internal class VisualStudioTokenProviderFile - { - [DataMember(Name = "TokenProviders")] - public List TokenProviders; - - private const string FormatExceptionMessage = "VisualStudio Token Provider File is not in the expected format."; - - public static VisualStudioTokenProviderFile Parse(string fileContents) - { - try - { - var visualStudioTokenProviderFile = JsonHelper.Deserialize(Encoding.UTF8.GetBytes(fileContents)); - - // Order the providers, so that the latest one is tried first. - visualStudioTokenProviderFile.TokenProviders = - visualStudioTokenProviderFile.TokenProviders.OrderByDescending(p => p.Preference).ToList(); - - return visualStudioTokenProviderFile; - } - catch (Exception exp) - { - throw new FormatException($"{FormatExceptionMessage} Exception Message: {exp.Message}"); - } - } - } -} diff --git a/src/AppAuthentication/WebHostBuilderExtensions.cs b/src/AppAuthentication/WebHostBuilderExtensions.cs deleted file mode 100644 index 524360b..0000000 --- a/src/AppAuthentication/WebHostBuilderExtensions.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.Drawing; -using System.IO; - -using McMaster.Extensions.CommandLineUtils; - -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; - -using Console = Colorful.Console; - -namespace AppAuthentication -{ - internal static class WebHostBuilderExtensions - { - internal static WebHostBuilder CreateDefaultBuilder(WebHostBuilderOptions options) - { - var builder = new WebHostBuilder(); - - builder.UseEnvironment(options.HostingEnvironment); - var fullPath = Directory.GetCurrentDirectory(); - - if (!string.IsNullOrWhiteSpace(Path.GetDirectoryName(options.ConfigFile))) - { - fullPath = Path.GetDirectoryName(options.ConfigFile); - } - - builder.UseContentRoot(fullPath); - - var defaultConfigName = !string.IsNullOrWhiteSpace(options.ConfigFile) ? Path.GetFileName(options.ConfigFile) : "appsettings.json"; - - if (options.Verbose) - { - Console.WriteLine($"ContentRoot:{fullPath}", color: Color.Green); - } - - var config = new ConfigurationBuilder(); - - config.AddEnvironmentVariables(prefix: "ASPNETCORE_"); - - // appsettings file or others - config.AddJsonFile(Path.Combine(fullPath, $"{defaultConfigName.Split(".")[0]}.json"), optional: true) - .AddJsonFile(Path.Combine(fullPath, $"{defaultConfigName.Split(".")[0]}.{options.HostingEnvironment}.json"), optional: true); - - if (options.Arguments != null) - { - config.AddCommandLine(options.Arguments); - } - - if (options.Verbose - && options.Level == LogLevel.Debug) - { - config.Build().DebugConfigurations(); - } - - builder.UseConfiguration(config.Build()); - - builder - .UseKestrel() - .UseUrls(string.Format(Constants.HostUrl, Constants.MsiLocalhostUrl, options.Port)) - .ConfigureLogging(logger => - { - if (options.Verbose) - { - logger.AddConsole(); - logger.AddDebug(); - } - }); - - builder - .ConfigureServices(services => - { - services.AddSingleton(options); - if (options.Verbose) - { - services.AddLogging(x => x.AddFilter((loglevel) => loglevel == options.Level)); - } - }); - - return builder; - } - } -} diff --git a/src/AppAuthentication/WebHostBuilderOptions.cs b/src/AppAuthentication/WebHostBuilderOptions.cs deleted file mode 100644 index 1a2a7d4..0000000 --- a/src/AppAuthentication/WebHostBuilderOptions.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Microsoft.Extensions.Logging; - -namespace AppAuthentication -{ - internal class WebHostBuilderOptions - { - /// - /// Default set to https://vault.azure.net/. - /// - public string Resource { get; set; } - - /// - /// Azure AD directory or Tenant GUID. - /// - public string Authority { get; set; } - - /// - /// Specify Environment. - /// - public string HostingEnvironment { get; set; } - - /// - /// Enables custom . - /// - public bool Verbose { get; set; } - - /// - /// The for the . - /// - public LogLevel Level { get; set; } - - /// - /// Web Host Port number. - /// - public int Port { get; set; } - - /// - /// Configuration file with settings. - /// - public string ConfigFile { get; set; } - - /// - /// Console apps pass-thru arguments to the generic host. - /// - public string[] Arguments { get; set; } - - /// - /// Guid Generated Id for the secret. - /// - public string SecretId { get; set; } - - /// - /// The default MSI_ENPOINT environment variable supports Docker only callbacks. - /// - public bool IsLocal { get; set; } - } -}