public static async void callAPIPage(string scope, string skipToken, string workspaceid, string workspacekey, string logName, ILogger log, string myJson) { var azureServiceTokenProvider = new AzureServiceTokenProvider(); string AuthToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/"); using (var client = new HttpClient()) { // Setting Authorization. client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken); // Setting Base address. client.BaseAddress = new Uri("https://management.azure.com"); // Setting content type. client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // Initialization. HttpResponseMessage response = new HttpResponseMessage(); AzureLogAnalytics logAnalytics = new AzureLogAnalytics( workspaceId: $"{workspaceid}", sharedKey: $"{workspacekey}", logType: $"{logName}"); string newURL = "/" + scope + "/providers/Microsoft.CostManagement/query?api-version=2019-11-01&" + skipToken; response = await client.PostAsync(newURL, new StringContent(myJson, Encoding.UTF8, "application/json")); QueryResults result = JsonConvert.DeserializeObject <QueryResults>(response.Content.ReadAsStringAsync().Result); jsonResult = "["; for (int i = 0; i < result.properties.rows.Length; i++) { object[] row = result.properties.rows[i]; double cost = Convert.ToDouble(row[0]); if (i == 0) { jsonResult += $"{{\"PreTaxCost\": {cost},\"Date\": \"{row[1]}\",\"ResourceId\": \"{row[2]}\",\"ResourceType\": \"{row[3]}\",\"SubscriptionName\": \"{row[4]}\",\"ResourceGroup\": \"{row[5]}\"}}"; } else { jsonResult += $",{{\"PreTaxCost\": {cost},\"Date\": \"{row[1]}\",\"ResourceId\": \"{row[2]}\",\"ResourceType\": \"{row[3]}\",\"SubscriptionName\": \"{row[4]}\",\"ResourceGroup\": \"{row[5]}\"}}"; } } jsonResult += "]"; //log.LogInformation($"Cost Data: {jsonResult}"); logAnalytics.Post(jsonResult); string nextLink = null; nextLink = result.properties.nextLink.ToString(); if (!string.IsNullOrEmpty(nextLink)) { skipToken = nextLink.Split('&')[1]; Console.WriteLine(skipToken); callAPIPage(scope, skipToken, workspaceid, workspacekey, logName, log, myJson); } } }
public Task <string> Generate() { var azureServiceTokenProvider = new AzureServiceTokenProvider(); return(azureServiceTokenProvider.GetAccessTokenAsync(_config.IdentifierUri)); }
/// <summary> /// Configure the configuration builder /// </summary> /// <param name="args">arguments for creating build configuration</param> /// <returns>The web host builder</returns> public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((hostingContext, config) => { config.AddJsonFile("altinn-appsettings/altinn-appsettings-secret.json", optional: true, reloadOnChange: true); IWebHostEnvironment hostingEnvironment = hostingContext.HostingEnvironment; string envName = hostingEnvironment.EnvironmentName; config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true); config.AddEnvironmentVariables(); config.AddCommandLine(args); IConfiguration stageOneConfig = config.Build(); string appId = stageOneConfig.GetValue <string>("KvSetting:ClientId"); string tenantId = stageOneConfig.GetValue <string>("KvSetting:TenantId"); string appKey = stageOneConfig.GetValue <string>("KvSetting:ClientSecret"); string keyVaultEndpoint = stageOneConfig.GetValue <string>("KvSetting:SecretUri"); if (!string.IsNullOrEmpty(appId) && !string.IsNullOrEmpty(tenantId) && !string.IsNullOrEmpty(appKey) && !string.IsNullOrEmpty(keyVaultEndpoint)) { AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider($"RunAs=App;AppId={appId};TenantId={tenantId};AppKey={appKey}"); KeyVaultClient keyVaultClient = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback( azureServiceTokenProvider.KeyVaultTokenCallback)); config.AddAzureKeyVault( keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager()); try { string secretId = hostingEnvironment.IsDevelopment() ? "ApplicationInsights--InstrumentationKey--Dev" : "ApplicationInsights--InstrumentationKey"; SecretBundle secretBundle = keyVaultClient.GetSecretAsync( keyVaultEndpoint, secretId).Result; Startup.ApplicationInsightsKey = secretBundle.Value; } catch (Exception vaultException) { _logger.LogError($"Could not find secretBundle for application insights {vaultException}"); } } if (hostingEnvironment.IsDevelopment() && !Directory.GetCurrentDirectory().Contains("app")) { config.AddJsonFile(Directory.GetCurrentDirectory() + $"/appsettings.{envName}.json", optional: true, reloadOnChange: true); Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName)); if (assembly != null) { config.AddUserSecrets(assembly, true); } } }) .ConfigureLogging(builder => { // The default ASP.NET Core project templates call CreateDefaultBuilder, which adds the following logging providers: // Console, Debug, EventSource // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1 // Clear log providers builder.ClearProviders(); // Setup up application insight if ApplicationInsightsKey is available if (!string.IsNullOrEmpty(Startup.ApplicationInsightsKey)) { // Add application insights https://docs.microsoft.com/en-us/azure/azure-monitor/app/ilogger // Providing an instrumentation key here is required if you're using // standalone package Microsoft.Extensions.Logging.ApplicationInsights // or if you want to capture logs from early in the application startup // pipeline from Startup.cs or Program.cs itself. builder.AddApplicationInsights(Startup.ApplicationInsightsKey); // Optional: Apply filters to control what logs are sent to Application Insights. // The following configures LogLevel Information or above to be sent to // Application Insights for all categories. builder.AddFilter <Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>(string.Empty, LogLevel.Warning); // Adding the filter below to ensure logs of all severity from Program.cs // is sent to ApplicationInsights. builder.AddFilter <Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>(typeof(Program).FullName, LogLevel.Trace); // Adding the filter below to ensure logs of all severity from Startup.cs // is sent to ApplicationInsights. builder.AddFilter <Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider>(typeof(Startup).FullName, LogLevel.Trace); } else { // If not application insight is available log to console builder.AddFilter("Microsoft", LogLevel.Warning); builder.AddFilter("System", LogLevel.Warning); builder.AddConsole(); } }).UseStartup <Startup>() .CaptureStartupErrors(true);
public static async Task obProxy(List <string> standardizedEvents, ILogger log) { string proxyAddress = Utils.getEnvironmentVariable("proxyAddress"); if (proxyAddress.Length == 0) { log.LogError("Address of proxy function is required."); throw new ArgumentException(); } string serviceResourceIDURI = Utils.getEnvironmentVariable("serviceResourceIDURI"); if (serviceResourceIDURI.Length == 0) { log.LogError("The AAD service resource ID URI (serviceResourceIDURI) of the proxy app is required."); throw new ArgumentException(); } string astpConnection = ""; bool devEnvironment = Utils.getEnvironmentVariable("FUNCTIONS_CORETOOLS_ENVIRONMENT").ToLower() == "true"; if (devEnvironment) { astpConnection = Utils.getEnvironmentVariable("astpConnectionString"); } // log.LogInformation($"devEnvironment: {devEnvironment}, astpConnection: {astpConnection}"); string accessToken = ""; try { var azureServiceTokenProvider = new AzureServiceTokenProvider( connectionString: astpConnection ); accessToken = await azureServiceTokenProvider.GetAccessTokenAsync(serviceResourceIDURI); } catch (Exception ex) { log.LogError($"Error acquiring token from AzureServiceTokenProvider: {ex.Message}"); throw; } //ServicePointManager.Expect100Continue = true; //ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; //ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateMyCert); var client = new SingleHttpClientInstance(); StringBuilder bulkTransmission = new StringBuilder(); foreach (string item in standardizedEvents) { bulkTransmission.Append(item); } try { var httpRequestMessage = new HttpRequestMessage { Method = HttpMethod.Post, RequestUri = new Uri(proxyAddress), Headers = { { HttpRequestHeader.Authorization.ToString(), "Bearer " + accessToken } }, Content = new StringContent(bulkTransmission.ToString(), Encoding.UTF8) }; HttpResponseMessage response = await SingleHttpClientInstance.SendToService(httpRequestMessage); if (response.StatusCode != HttpStatusCode.OK) { throw new System.Net.Http.HttpRequestException($"StatusCode from Proxy Function: {response.StatusCode}, and reason: {response.ReasonPhrase}"); } } catch (System.Net.Http.HttpRequestException e) { throw new System.Net.Http.HttpRequestException("Sending to Proxy Function. Is the service running?", e); } catch (Exception f) { throw new System.Exception("Sending to Proxy Function. Unplanned exception.", f); } }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { try { log.LogInformation("GetAzureStorageSASUploadToken begin request."); string cloudAccountName = null; string cloudKey = null; if (req.Host.ToString().ToLower().Contains("localhost")) { cloudAccountName = "devstoreaccount1"; cloudKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="; } else { // Uses MSI to get an Azure AD token: You can run locally if you have a domain joined computer and your domain is synced with Azure AD // The Function App must be in a Policy to to read secrets AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(); KeyVaultClient keyvaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); string keyVault = Environment.GetEnvironmentVariable("MY_KEY_VAULT"); var secretCloudAccountName = await keyvaultClient.GetSecretAsync($"https://{keyVault}.vault.azure.net/", "LandingZoneStorageAccountName"); var secretcloudKey = await keyvaultClient.GetSecretAsync($"https://{keyVault}.vault.azure.net/", "LandingZoneStorageAccountKey"); cloudAccountName = secretCloudAccountName.Value; cloudKey = secretcloudKey.Value; } string customerId = req.Query["customerId"]; string customerSecret = req.Query["customerSecret"]; string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody); customerId = customerId ?? data?.customerId; customerSecret = customerSecret ?? data?.customerSecret; customerId = customerId.ToLower(); DocumentDBRepository <CosmosIngestionData> documentDBRepository = new DocumentDBRepository <CosmosIngestionData>(log); var result = documentDBRepository.GetItems(o => o.CustomerId == customerId && o.PartitionId == customerId && o.CustomerSecret == customerSecret && o.isCustomerEnabled).FirstOrDefault(); // INSERT SEED DATA if (result == null && customerId == "acmeinc") { CosmosIngestionData acmeInc = new CosmosIngestionData(); acmeInc.CustomerId = "acmeinc"; acmeInc.PartitionId = "acmeinc"; acmeInc.ContainerName = "acmeinc"; acmeInc.CustomerSecret = "0DC8B9026ECD402C84C66AFB5B87E28C"; acmeInc.CustomerSASTokenExpireTimeInMinutes = 60; acmeInc.CustomerWhitelistIPAddress = null; acmeInc.isCustomerEnabled = true; acmeInc.ADFPipelineName = "CopyLandingDataToDataLake"; acmeInc.ADFResourceGroup = Environment.GetEnvironmentVariable("ResourceGroup"); acmeInc.ADFDataFactoryName = Environment.GetEnvironmentVariable("DataFactoryName"); acmeInc.ADFSubscriptionId = Environment.GetEnvironmentVariable("SubscriptionId"); acmeInc.isADFEnabled = true; // Insert the seed data documentDBRepository.Client.UpsertDocumentAsync(documentDBRepository.Collection.SelfLink, acmeInc).Wait(); result = acmeInc; } if (result != null) { // create a blob container // create a SAS token with list and write privilages (no read or delete) - they can upload, but never download to protect their data string sasToken = GetSASToken(result.ContainerName, result.CustomerWhitelistIPAddress, result.CustomerSASTokenExpireTimeInMinutes, cloudAccountName, cloudKey); ReturnData returnData = new ReturnData() { AccountName = cloudAccountName == "devstoreaccount1" ? "http://127.0.0.1:10000/devstoreaccount1" : cloudAccountName, ContainerName = result.ContainerName, SASToken = sasToken }; return((ActionResult) new OkObjectResult(returnData)); } else { return(new UnauthorizedResult()); } } catch (Exception ex) { log.LogError("GetAzureStorageSASUploadToken Exception: " + ex.ToString()); return(new BadRequestResult()); } } // Run
public static async Task <string> GetAccessTokenAsync() { var tokenProvider = new AzureServiceTokenProvider(); return(await tokenProvider.GetAccessTokenAsync("https://storage.azure.com/")); }
public async Task ConfigureAuth(IAppBuilder app) { var azureServiceTokenProvider1 = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider1.KeyVaultTokenCallback)); var azureServiceTokenProvider2 = new AzureServiceTokenProvider(); string accessToken = await azureServiceTokenProvider2.GetAccessTokenAsync("https://management.azure.com/") .ConfigureAwait(false); var demoSecret = ConfigurationManager.AppSettings["demoSecret"]; var googleClientId = await keyVaultClient.GetSecretAsync( "https://useraccountskeys.vault.azure.net/secrets/GoogleClientID/0987555de5794d6ab165db0d7cb0c601") .ConfigureAwait(false); var googleClientSecret = await keyVaultClient.GetSecretAsync( "https://useraccountskeys.vault.azure.net/secrets/GoogleClientSecret/f8234e18205043c2a1d8804f42fc34c6") .ConfigureAwait(false); var facebookAppId = await keyVaultClient.GetSecretAsync( "https://useraccountskeys.vault.azure.net/secrets/FacebookAppID/10d67e52aec04f8a90730e4b09187170") .ConfigureAwait(false); var facebookAppSecret = await keyVaultClient.GetSecretAsync( "https://useraccountskeys.vault.azure.net/secrets/FacebookAppSecret/386eade3a4ae444d8916baae7ffaec9f") .ConfigureAwait(false); app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext <ApplicationUserManager>(ApplicationUserManager.Create); app.CreatePerOwinContext <ApplicationSignInManager>(ApplicationSignInManager.Create); app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), Provider = new CookieAuthenticationProvider { OnValidateIdentity = SecurityStampValidator.OnValidateIdentity <ApplicationUserManager, ApplicationUser>( validateInterval: TimeSpan.FromMinutes(30), regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) } }); app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie); app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5)); app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie); app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions() { ClientId = googleClientId.Value, ClientSecret = googleClientSecret.Value }); app.UseFacebookAuthentication(new FacebookAuthenticationOptions() { AppId = facebookAppId.Value, AppSecret = facebookAppSecret.Value }); }
internal async Task <string> BuildSbConnectionString() { try { var instanceName = (_msiConfig != null) ? _msiConfig.InstanceName : _spConfig.InstanceName; // If we already have the connection string for this instance - don't go get it again. if (ConnectionStrings.TryGetValue(instanceName, out var connStr)) { return(connStr); } const string azureManagementAuthority = "https://management.azure.com/"; const string windowsLoginAuthority = "https://login.windows.net/"; string token, subscriptionId, sharedAccessPolicy; // Generate authentication token using Msi Config if it's been specified, otherwise, use Service principle. if (_msiConfig != null) { // Managed Service Identity (MSI) authentication. var provider = new AzureServiceTokenProvider(); token = provider.GetAccessTokenAsync(azureManagementAuthority, _msiConfig.TenantId).GetAwaiter().GetResult(); if (string.IsNullOrEmpty(token)) { throw new InvalidOperationException("Could not authenticate using Managed Service Identity, ensure the application is running in a secure context"); } subscriptionId = _msiConfig.SubscriptionId; instanceName = _msiConfig.InstanceName; sharedAccessPolicy = _msiConfig.SharedAccessPolicyName; } else { // Grab an authentication token from Azure. var context = new AuthenticationContext(windowsLoginAuthority + _spConfig.TenantId); var credential = new ClientCredential(_spConfig.AppId, _spConfig.AppSecret); var tokenResult = await context.AcquireTokenAsync(azureManagementAuthority, credential); if (tokenResult == null) { throw new InvalidOperationException($"Could not authenticate to {azureManagementAuthority} using supplied AppId: {_spConfig.AppId}"); } token = tokenResult.AccessToken; subscriptionId = _spConfig.SubscriptionId; instanceName = _spConfig.InstanceName; sharedAccessPolicy = _spConfig.SharedAccessPolicyName; } // Set credentials and grab the authenticated REST client. var tokenCredentials = new TokenCredentials(token); var client = RestClient.Configure() .WithEnvironment(AzureEnvironment.AzureGlobalCloud) .WithLogLevel(HttpLoggingDelegatingHandler.Level.None) .WithCredentials(new AzureCredentials(tokenCredentials, tokenCredentials, string.Empty, AzureEnvironment.AzureGlobalCloud)) .WithRetryPolicy(new RetryPolicy(new HttpStatusCodeErrorDetectionStrategy(), new FixedIntervalRetryStrategy(3, TimeSpan.FromMilliseconds(500)))) .Build(); // Authenticate against the management layer. var azureManagement = Azure.Authenticate(client, string.Empty).WithSubscription(subscriptionId); var sbNamespace = (await azureManagement.ServiceBusNamespaces.ListAsync()).FirstOrDefault(s => s.Name == instanceName); // If the namespace is not found, throw an exception. if (sbNamespace == null) { throw new InvalidOperationException($"Could not find the a service bus instance in the subscription with ID {subscriptionId}"); } // Get the built connection string. var name = await sbNamespace.AuthorizationRules.GetByNameAsync(sharedAccessPolicy); var keys = await name.GetKeysAsync(); var connectionString = keys.PrimaryConnectionString; // Cache the connection string off so we don't have to re-authenticate. if (!ConnectionStrings.ContainsKey(instanceName)) { ConnectionStrings.TryAdd(instanceName, connectionString); } // Return the connection string. return(connectionString); // NOTE: Re-implement the code in previous version of Master Branch when the intent is to use shared access policies that are topic or queue level. // When this happens, a connection string may need to be added to both the sender and receiver as a connection string generated using a lower level // access policy will mean it needs a connection per send/receive. This is why I have left this out for now (I can see from our solution we do not use // low level Shared Access Policies at the moment either. } catch (Exception e) { Logger?.LogError(e, "An exception occurred during service bus connection"); throw new ArgumentException("An exception occurred during service connection, see inner exception for more detail", e); } }
/// <summary> /// Initializes a new instance of the <see cref="AadTokenMsiBasedProvider"/> class. /// </summary> public AadTokenMsiBasedProvider() { this.azureServiceTokenProvider = new AzureServiceTokenProvider(); }
public static async Task <IActionResult> UpdateLastProcessedTimestampInTable(HttpRequest req, TraceWriter log) { if (TableConnectionString == null) { log.Info($"Fetching LastProcessedDateTime table Connection String for the first time from KeyVault..."); var azureServiceTokenProvider = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); var secretName = Environment.GetEnvironmentVariable("AzureTableStorageLastProcessedConnectionStringSecretName", EnvironmentVariableTarget.Process); var azureKeyVaultUrl = Environment.GetEnvironmentVariable("AzureKeyVaultUrl", EnvironmentVariableTarget.Process); var secret = await keyVaultClient.GetSecretAsync($"{azureKeyVaultUrl}secrets/{secretName}").ConfigureAwait(false); TableConnectionString = secret.Value; log.Info("[Setting]: Successfully fetched Table Connection String from KeyVault."); } string tableName = Environment.GetEnvironmentVariable("LastProcessedDateTimeTableName", EnvironmentVariableTarget.Process); string tablePropertyName = Environment.GetEnvironmentVariable("LastProcessedTablePropertyName", EnvironmentVariableTarget.Process); //log.Info($"[Setting]: Table Connection String: {TableConnectionString}"); log.Info($"[Setting]: Table Name: {tableName}"); log.Info($"[Setting]: Table Property Name: {tablePropertyName}"); string newLastProcessedDateTimeUtcAsString = req.Query["newLastProcessedDateTimeUtc"]; // GET string requestBody = new StreamReader(req.Body).ReadToEnd(); // POST dynamic data = JsonConvert.DeserializeObject(requestBody); newLastProcessedDateTimeUtcAsString = newLastProcessedDateTimeUtcAsString ?? data?.newLastProcessedDateTimeUtc; if (string.IsNullOrWhiteSpace(newLastProcessedDateTimeUtcAsString)) { string errorMessage = "A 'newLastProcessedDateTimeUtc' querystring parameter or a request body containing a JSON object with a 'newLastProcessedDateTimeUtc' property was expected but not found."; log.Info(errorMessage); return(new BadRequestObjectResult(errorMessage)); } var newLastProcessedDateTimeUtc = DateTime.Parse(newLastProcessedDateTimeUtcAsString); log.Info($"New Last Processed DateTimeUtc: {newLastProcessedDateTimeUtcAsString}."); try { CloudStorageAccount storageAccount = CloudStorageAccount.Parse(TableConnectionString); CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); CloudTable cloudTable = tableClient.GetTableReference(tableName); bool tableExists = await cloudTable.ExistsAsync(); if (!tableExists) { log.Info($"Table {tableName} was not found in storage account. Creating table..."); bool createdTableSuccessfully = await cloudTable.CreateIfNotExistsAsync(); if (!createdTableSuccessfully) { log.Info($"Failed to create table {tableName}. Create the table manually in storage account '{storageAccount.Credentials.AccountName}' with PartionKey/RowKey of 1/1 and a property '{tablePropertyName}' with an empty value."); return(new BadRequestObjectResult("Operation failed: Specified table not found. Check function's log for details.")); } // Add the first entity / default entity: log.Info($"Adding a default entity to newly created table '{tableName}'..."); DynamicTableEntity entity = new DynamicTableEntity("1", "1"); entity.Properties[tablePropertyName] = new EntityProperty(DefaultDateTimeValue); TableOperation insertOperation = TableOperation.Insert(entity); await cloudTable.ExecuteAsync(insertOperation); log.Info($"Added default entity to newly created table '{tableName}'."); } else { // Update the existing entity if this is not the default date/time value (used to initialize the ADFv2 pipeline): if (string.CompareOrdinal(DefaultDateTimeValue, newLastProcessedDateTimeUtcAsString) != 0) { TableQuery <DynamicTableEntity> query = new TableQuery <DynamicTableEntity>() .Take(1); // Get the first entity in the table. We don't care what the partition or row keys are. TableQuerySegment <DynamicTableEntity> resultSegment = await cloudTable.ExecuteQuerySegmentedAsync(query, null); DynamicTableEntity entity = resultSegment.Results[0]; log.Info($"PartitionKey/RowKey values of the first entity in table '{tableName}' are: {entity.PartitionKey}/{entity.RowKey}."); EntityProperty lastProcessedTableEntityProperty = entity.Properties[tablePropertyName]; log.Info($"Current value of '{tablePropertyName}' property in table '{tableName}' is: {lastProcessedTableEntityProperty.StringValue}."); // Set the property value to the new one: lastProcessedTableEntityProperty.StringValue = newLastProcessedDateTimeUtcAsString; entity.Properties[tablePropertyName] = lastProcessedTableEntityProperty; TableOperation updateOperation = TableOperation.Replace(entity); await cloudTable.ExecuteAsync(updateOperation); } } dynamic payload = new System.Dynamic.ExpandoObject(); payload.Result = "Operation succeeded."; return(new OkObjectResult(JsonConvert.SerializeObject(payload, Formatting.Indented))); } catch (Exception exception) { log.Info($"Exception [UpdateLastProcessedTimestampInTable]: {exception.ToString()}."); return(new BadRequestObjectResult("Operation failed. Check function's log for details.")); } }
public async Task GetAppAuthResultCacheTest() { // Create two instances of AzureServiceTokenProvider based on AzureCliAccessTokenProvider. MockProcessManager mockProcessManager = new MockProcessManager(MockProcessManager.MockProcessManagerRequestType.Success); AzureCliAccessTokenProvider azureCliAccessTokenProvider = new AzureCliAccessTokenProvider(mockProcessManager); AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(azureCliAccessTokenProvider); AzureServiceTokenProvider azureServiceTokenProvider1 = new AzureServiceTokenProvider(azureCliAccessTokenProvider); List <Task> tasks = new List <Task>(); // ManualResetEvent will enable testing of SemaphoreSlim used in AzureServiceTokenProvider. ManualResetEvent manualResetEvent = new ManualResetEvent(false); // Use AzureServiceTokenProviders to get tokens in parallel. for (int i = 0; i < 5; i++) { Task task = Task.Run(async delegate { // This will prevent the next line from running, until manualResetEvent.Set() is called. // This will ensure all GetAccessTokenAsync calls are made at once. manualResetEvent.WaitOne(); await azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId); }); tasks.Add(task); Task task1 = Task.Run(async delegate { manualResetEvent.WaitOne(); // This is using the other instance of AzureServiceTokenProvider. await azureServiceTokenProvider1.GetAccessTokenAsync(Constants.KeyVaultResourceId); }); tasks.Add(task1); } // This will cause GetAccessTokenAsync calls to be made concurrently. manualResetEvent.Set(); await Task.WhenAll(tasks); // Even though multiple calls are made to get token concurrently, using two different instances, the process manager should only be called once. // This test tells us that the cache is working as intended. Assert.Equal(1, mockProcessManager.HitCount); // Get the token again. This will test if the cache call before semaphore use is working as intended. for (int i = 0; i < 5; i++) { tasks.Add(azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId)); } await Task.WhenAll(tasks); // The hit count should still be 1, since the token should be fetched from cache. Assert.Equal(1, mockProcessManager.HitCount); // Update the cache entry, to simulate token expiration. This updated token will expire in just less than 5 minutes. // In a real scenario, the token will expire after some time. // AppAuthResultCache should not return this, since it is about to expire. var tokenResponse = TokenResponse.Parse(TokenHelper.GetUserTokenResponse(5 * 60 - 2)); var authResult = AppAuthenticationResult.Create(tokenResponse); AppAuthResultCache.AddOrUpdate("ConnectionString:;Authority:;Resource:https://vault.azure.net/", new Tuple <AppAuthenticationResult, Principal>(authResult, null)); // Get the token again. for (int i = 0; i < 5; i++) { tasks.Add(azureServiceTokenProvider.GetAccessTokenAsync(Constants.KeyVaultResourceId)); } await Task.WhenAll(tasks); // Hit count should be 2 now, since new token should have been aquired. Assert.Equal(2, mockProcessManager.HitCount); }
public static async Task <IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "put", Route = "books/{bookId}/pages/{pageId}/languages/{languageCode}/text")] HttpRequest req, string bookid, string pageid, string languagecode, ILogger log, ExecutionContext context) { var status = (StatusCodeResult) new StatusCodeResult(200); string method = req.Method; try { log.LogInformation("Http function to PUT texturl"); //get request body string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody); log.LogInformation($"data -> {data}"); //get environment variables var config = new ConfigurationBuilder() .SetBasePath(context.FunctionAppDirectory) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build(); //access azure keyvault var serviceTokenProvider = new AzureServiceTokenProvider(); log.LogInformation("serviceTokenProvider"); var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(serviceTokenProvider.KeyVaultTokenCallback)); log.LogInformation("keyVaultClient"); SecretBundle secrets; String uri = String.Empty; String key = String.Empty; String database = String.Empty; String collection = String.Empty; try { //storage account is the keyvault key secrets = await keyVaultClient.GetSecretAsync($"{config["KEY_VAULT_URI"]}secrets/{config["COSMOS_NAME"]}/"); //parse json stored in keyvalut JObject details = JObject.Parse(secrets.Value.ToString()); uri = (string)details["COSMOS_URI"]; key = (string)details["COSMOS_KEY"]; database = (string)details["COSMOS_DB"]; collection = (string)details["COSMOS_COLLECTION"]; log.LogInformation("Secret Values retrieved from KeyVault."); } catch (Exception kex) { status = (StatusCodeResult) new StatusCodeResult(500); //server error } if (200 == status.StatusCode) { //declare client DocumentClient dbClient = new DocumentClient(new Uri(uri), key); log.LogInformation("new DocumentClient"); try { var collectionUri = UriFactory.CreateDocumentCollectionUri(database, collection); var query = "SELECT * FROM Books b WHERE b.id=\"" + bookid + "\""; var crossPartition = new FeedOptions { EnableCrossPartitionQuery = true }; var documents = dbClient.CreateDocumentQuery(collectionUri, query, crossPartition).ToList(); log.LogInformation($"document retrieved -> {documents.Count().ToString()}"); //insert Book b = documents.ElementAt(0); Page p = b.Pages.ElementAt(int.Parse(pageid) - 1); for (int j = 0; j < p.Languages.Count(); j++) { if (p.Languages.ElementAt(j).language.Equals(languagecode)) { p.Languages.ElementAt(j).Text_Url = data.pages[int.Parse(pageid) - 1].languages[j].text_url.ToString(); } } var result = await dbClient.UpsertDocumentAsync(UriFactory.CreateDocumentCollectionUri(database, collection), b); log.LogInformation($"document updated -> {result}"); status = (StatusCodeResult) new StatusCodeResult(200); //db write successful } catch (Exception wrt) { status = (StatusCodeResult) new StatusCodeResult(404); //document not found } } else { status = (StatusCodeResult) new StatusCodeResult(400); } } catch (Exception e) { status = (StatusCodeResult) new StatusCodeResult(400); } return(status); }
private static KeyVaultClient CreateKeyVaultClient() { var tokenProvider = new AzureServiceTokenProvider(); return(new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback))); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log) { log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}"); var azureServiceTokenProvider = new AzureServiceTokenProvider(); string AuthToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://management.azure.com/"); Console.WriteLine(AuthToken); using (var client = new HttpClient()) { // Setting Authorization. client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken); // Setting Base address. client.BaseAddress = new Uri("https://management.azure.com"); // Setting content type. client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); // Initialization. HttpResponseMessage response = new HttpResponseMessage(); DateTime startTime = DateTime.Now.AddDays(-30); DateTime endTime = DateTime.Now; string start = startTime.ToString("MM/dd/yyyy"); string end = endTime.ToString("MM/dd/yyyy"); string myJson = @"{ 'dataset': { 'aggregation': { 'totalCost': { 'function': 'Sum', 'name': 'PreTaxCost' } }, 'granularity': 'Daily', 'grouping': [ { 'name': 'ResourceId', 'type': 'Dimension' }, { 'name': 'ResourceType', 'type': 'dimension' }, { 'name': 'SubscriptionName', 'type': 'dimension' }, { 'name': 'ResourceGroup', 'type': 'dimension' } ] }, 'timePeriod': { 'from': '" + start + @"', 'to': '" + end + @"' }, 'timeframe': 'Custom', 'type': 'Usage' }"; log.LogInformation($"Cost Query: {myJson}"); AzureLogAnalytics logAnalytics = new AzureLogAnalytics( workspaceId: $"{workspaceid}", sharedKey: $"{workspacekey}", logType: $"{logName}"); foreach (string scope in scopes) { log.LogInformation($"Scope: {scope}"); // HTTP Post response = await client.PostAsync("/" + scope + "/providers/Microsoft.CostManagement/query?api-version=2019-11-01", new StringContent(myJson, Encoding.UTF8, "application/json")); Console.WriteLine(client); QueryResults result = Newtonsoft.Json.JsonConvert.DeserializeObject <QueryResults>(response.Content.ReadAsStringAsync().Result); jsonResult = "["; for (int i = 0; i < result.properties.rows.Length; i++) { object[] row = result.properties.rows[i]; double cost = Convert.ToDouble(row[0]); if (i == 0) { jsonResult += $"{{\"PreTaxCost\": {cost},\"Date\": \"{row[1]}\",\"ResourceId\": \"{row[2]}\",\"ResourceType\": \"{row[3]}\",\"SubscriptionName\": \"{row[4]}\",\"ResourceGroup\": \"{row[5]}\"}}"; } else { jsonResult += $",{{\"PreTaxCost\": {cost},\"Date\": \"{row[1]}\",\"ResourceId\": \"{row[2]}\",\"ResourceType\": \"{row[3]}\",\"SubscriptionName\": \"{row[4]}\",\"ResourceGroup\": \"{row[5]}\"}}"; } } jsonResult += "]"; log.LogInformation($"Cost Data: {jsonResult}"); logAnalytics.Post(jsonResult); string nextLink = result.properties.nextLink.ToString(); if (!string.IsNullOrEmpty(nextLink)) { string skipToken = nextLink.Split('&')[1]; callAPIPage(scope, skipToken, workspaceid, workspacekey, logName, log, myJson); } //return new OkObjectResult(jsonResult); } } return(new OkObjectResult(jsonResult)); }
// This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName(); var migrationsAssemblyName = migrationsAssembly.Name; var useSqlServer = Convert.ToBoolean(Configuration["BlazorBoilerplate:UseSqlServer"] ?? "false"); var dbConnString = useSqlServer ? Configuration.GetConnectionString("DefaultConnection") : $"Filename={Configuration.GetConnectionString("SqlLiteConnectionFileName")}"; var authAuthority = Configuration["BlazorBoilerplate:IS4ApplicationUrl"].TrimEnd('/'); void DbContextOptionsBuilder(DbContextOptionsBuilder builder) { if (useSqlServer) { builder.UseSqlServer(dbConnString, sql => sql.MigrationsAssembly(migrationsAssemblyName)); } else if (Convert.ToBoolean(Configuration["BlazorBoilerplate:UsePostgresServer"] ?? "false")) { builder.UseNpgsql(Configuration.GetConnectionString("PostgresConnection"), sql => sql.MigrationsAssembly(migrationsAssemblyName)); } else { builder.UseSqlite(dbConnString, sql => sql.MigrationsAssembly(migrationsAssemblyName)); } } services.Configure <ApiBehaviorOptions>(options => { options.SuppressModelStateInvalidFilter = true; }); services.AddDbContext <ApplicationDbContext>(DbContextOptionsBuilder); services.AddIdentity <ApplicationUser, IdentityRole <Guid> >() .AddRoles <IdentityRole <Guid> >() .AddEntityFrameworkStores <ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddScoped <IUserClaimsPrincipalFactory <ApplicationUser>, AdditionalUserClaimsPrincipalFactory>(); // cookie policy to deal with temporary browser incompatibilities services.AddSameSiteCookiePolicy(); // Adds IdentityServer var identityServerBuilder = services.AddIdentityServer(options => { options.IssuerUri = authAuthority; options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; }) .AddConfigurationStore(options => { options.ConfigureDbContext = DbContextOptionsBuilder; }) .AddOperationalStore(options => { options.ConfigureDbContext = DbContextOptionsBuilder; // this enables automatic token cleanup. this is optional. options.EnableTokenCleanup = true; options.TokenCleanupInterval = 3600; //In Seconds 1 hour }) .AddAspNetIdentity <ApplicationUser>(); X509Certificate2 cert = null; if (_environment.IsDevelopment()) { // The AddDeveloperSigningCredential extension creates temporary key material for signing tokens. // This might be useful to get started, but needs to be replaced by some persistent key material for production scenarios. // See http://docs.identityserver.io/en/release/topics/crypto.html#refcrypto for more information. // https://stackoverflow.com/questions/42351274/identityserver4-hosting-in-iis //.AddDeveloperSigningCredential(true, @"C:\tempkey.rsa") identityServerBuilder.AddDeveloperSigningCredential(); } else { // running on azure // please make sure to replace your vault URI and your certificate name in appsettings.json! if (Convert.ToBoolean(Configuration["HostingOnAzure:RunsOnAzure"]) == true) { // if we use a key vault if (Convert.ToBoolean(Configuration["HostingOnAzure:AzurekeyVault:UsingKeyVault"]) == true) { // if managed app identity is used if (Convert.ToBoolean(Configuration["HostingOnAzure:AzurekeyVault:UseManagedAppIdentity"]) == true) { try { AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); var certificateBundle = keyVaultClient.GetSecretAsync(Configuration["HostingOnAzure:AzureKeyVault:VaultURI"], Configuration["HostingOnAzure:AzurekeyVault:CertificateName"]).GetAwaiter().GetResult(); var certificate = System.Convert.FromBase64String(certificateBundle.Value); cert = new X509Certificate2(certificate, (string)null, X509KeyStorageFlags.MachineKeySet); } catch (Exception ex) { throw (ex); } } // if app id and app secret are used if (Convert.ToBoolean(Configuration["HostingOnAzure:AzurekeyVault:UsingKeyVault"]) == false) { throw new NotImplementedException(); } } } // using local cert store if (Convert.ToBoolean(Configuration["BlazorBoilerplate:UseLocalCertStore"]) == true) { var certificateThumbprint = Configuration["BlazorBoilerplate:CertificateThumbprint"]; using (X509Store store = new X509Store("WebHosting", StoreLocation.LocalMachine)) { store.Open(OpenFlags.ReadOnly); var certs = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false); if (certs.Count > 0) { cert = certs[0]; } else { // import PFX cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "AuthSample.pfx"), "Admin123", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); // save certificate and private key X509Store storeMy = new X509Store(StoreName.CertificateAuthority, StoreLocation.LocalMachine); storeMy.Open(OpenFlags.ReadWrite); storeMy.Add(cert); } store.Close(); } } // pass the resulting certificate to Identity Server if (cert != null) { identityServerBuilder.AddSigningCredential(cert); } else { throw new FileNotFoundException("No certificate for Identity Server could be retrieved."); } } var authBuilder = services.AddAuthentication(options => { options.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme; }) .AddIdentityServerAuthentication(options => { options.Authority = authAuthority; options.SupportedTokens = SupportedTokens.Jwt; options.RequireHttpsMetadata = _environment.IsProduction() ? true : false; options.ApiName = IdentityServerConfig.ApiName; }); //https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?view=aspnetcore-3.1 if (Convert.ToBoolean(Configuration["ExternalAuthProviders:Google:Enabled"] ?? "false")) { authBuilder.AddGoogle(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.ClientId = Configuration["ExternalAuthProviders:Google:ClientId"]; options.ClientSecret = Configuration["ExternalAuthProviders:Google:ClientSecret"]; }); } //Add Policies / Claims / Authorization - https://stormpath.com/blog/tutorial-policy-based-authorization-asp-net-core services.AddAuthorization(options => { options.AddPolicy(Policies.IsAdmin, Policies.IsAdminPolicy()); options.AddPolicy(Policies.IsUser, Policies.IsUserPolicy()); options.AddPolicy(Policies.IsReadOnly, Policies.IsReadOnlyPolicy()); options.AddPolicy(Policies.IsMyDomain, Policies.IsMyDomainPolicy()); // valid only on serverside operations }); services.AddSingleton <IAuthorizationPolicyProvider, AuthorizationPolicyProvider>(); services.AddTransient <IAuthorizationHandler, DomainRequirementHandler>(); services.AddTransient <IAuthorizationHandler, PermissionRequirementHandler>(); services.Configure <IdentityOptions>(options => { // Password settings options.Password.RequireDigit = false; options.Password.RequiredLength = 6; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = false; options.Password.RequireLowercase = false; //options.Password.RequiredUniqueChars = 6; // Lockout settings options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); options.Lockout.MaxFailedAccessAttempts = 10; options.Lockout.AllowedForNewUsers = true; // Require Confirmed Email User settings if (Convert.ToBoolean(Configuration["BlazorBoilerplate:RequireConfirmedEmail"] ?? "false")) { options.User.RequireUniqueEmail = false; options.SignIn.RequireConfirmedEmail = true; } }); services.ConfigureApplicationCookie(options => { // Suppress redirect on API URLs in ASP.NET Core -> https://stackoverflow.com/a/56384729/54159 options.Events = new CookieAuthenticationEvents() { OnRedirectToAccessDenied = context => { if (context.Request.Path.StartsWithSegments("/api")) { context.Response.StatusCode = Status403Forbidden; } return(Task.CompletedTask); }, OnRedirectToLogin = context => { context.Response.StatusCode = Status401Unauthorized; return(Task.CompletedTask); } }; }); services.AddControllers().AddNewtonsoftJson(); services.AddSignalR(); services.AddSwaggerDocument(config => { config.PostProcess = document => { document.Info.Version = migrationsAssembly.Version.ToString(); document.Info.Title = "Blazor Boilerplate"; #if ServerSideBlazor document.Info.Description = "Blazor Boilerplate / Starter Template using the Server Side Version"; #endif #if ClientSideBlazor document.Info.Description = "Blazor Boilerplate / Starter Template using the Client Side / Webassembly Version."; #endif }; }); services.AddScoped <IUserSession, UserSession>(); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton <IEmailConfiguration>(Configuration.GetSection("EmailConfiguration").Get <EmailConfiguration>()); services.AddTransient <IAccountService, AccountService>(); services.AddTransient <IEmailService, EmailService>(); services.AddTransient <IUserProfileService, UserProfileService>(); services.AddTransient <IApiLogService, ApiLogService>(); services.AddTransient <ITodoService, ToDoService>(); services.AddTransient <IMessageService, MessageService>(); // DB Creation and Seeding services.AddTransient <IDatabaseInitializer, DatabaseInitializer>(); //Automapper to map DTO to Models https://www.c-sharpcorner.com/UploadFile/1492b1/crud-operations-using-automapper-in-mvc-application/ var automapperConfig = new MapperConfiguration(configuration => { configuration.AddProfile(new MappingProfile()); }); var autoMapper = automapperConfig.CreateMapper(); services.AddSingleton(autoMapper); #if ServerSideBlazor services.AddScoped <IAuthorizeApi, AuthorizeApi>(); services.AddScoped <IUserProfileApi, UserProfileApi>(); services.AddScoped <AppState>(); services.AddMatToaster(config => { config.Position = MatToastPosition.BottomRight; config.PreventDuplicates = true; config.NewestOnTop = true; config.ShowCloseButton = true; config.MaximumOpacity = 95; config.VisibleStateDuration = 3000; }); // Setup HttpClient for server side services.AddScoped <HttpClient>(); services.AddRazorPages(); services.AddServerSideBlazor(); // Authentication providers Log.Logger.Debug("Removing AuthenticationStateProvider..."); var serviceDescriptor = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(AuthenticationStateProvider)); if (serviceDescriptor != null) { services.Remove(serviceDescriptor); } Log.Logger.Debug("Adding AuthenticationStateProvider..."); services.AddScoped <AuthenticationStateProvider, IdentityAuthenticationStateProvider>(); #endif Log.Logger.Debug($"Total Services Registered: {services.Count}"); foreach (var service in services) { Log.Logger.Debug($"\n Service: {service.ServiceType.FullName}\n Lifetime: {service.Lifetime}\n Instance: {service.ImplementationType?.FullName}"); } }
private AzureServiceTokenProvider.TokenCallback GetKeyVaultCallback() { AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(); return(azureServiceTokenProvider.KeyVaultTokenCallback); }
async Task <ExpirationMetadata <string> > GetTokenViaCode(string authority, string resource) { using (var scope = serviceScopeFactory.CreateScope()) { var http = scope.ServiceProvider.GetRequiredService <System.Net.Http.IHttpClientFactory>().CreateClient(); var req = new HttpRequestMessage(HttpMethod.Get, $"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource={resource}"); req.Headers.TryAddWithoutValidation("Metadata", "true"); try { var tokenresponse = await http.SendAsync(req); tokenresponse.EnsureSuccessStatusCode(); var token = JToken.Parse(await tokenresponse.Content.ReadAsStringAsync()).SelectToken("$.access_token").ToString(); //TODO get proper validuntil return(new ExpirationMetadata <string> { Result = token, ValidUntil = DateTimeOffset.UtcNow.AddMinutes(2) }); } catch (HttpRequestException ex) { } var a = new AzureServiceTokenProvider(); var accessToken = await a.GetAccessTokenAsync(resource); if (accessToken != null) { return(new ExpirationMetadata <string> { Result = accessToken, ValidUntil = DateTimeOffset.UtcNow.AddMinutes(2) }); } IOptions <ManagedIdentityTokenProviderOptions> options = scope.ServiceProvider.GetRequiredService <IOptions <ManagedIdentityTokenProviderOptions> >(); var ctx = new AuthenticationContext(authority ?? $"https://login.microsoftonline.com/{options.Value.TenantId}", scope.ServiceProvider.GetRequiredService <TokenCache>()); AuthenticationResult result = null; try { result = await ctx.AcquireTokenSilentAsync(resource, options.Value.ApplicationId); } catch (AdalException adalException) { if (adalException.ErrorCode == AdalError.FailedToAcquireTokenSilently || adalException.ErrorCode == AdalError.UserInteractionRequired) { try { DeviceCodeResult codeResult = await ctx.AcquireDeviceCodeAsync(resource, options.Value.ApplicationId); logger.LogInformation(codeResult.Message); var url = codeResult.VerificationUrl + "#" + codeResult.UserCode; //Process.Start( codeResult.VerificationUrl+"#"+codeResult.UserCode); var startInfo = new ProcessStartInfo("explorer.exe", url); Process.Start(startInfo); result = await ctx.AcquireTokenByDeviceCodeAsync(codeResult); } catch (Exception exc) { logger.LogError(exc, "Failed to get token"); } } } return(new ExpirationMetadata <string> { Result = result?.AccessToken, ValidUntil = result?.ExpiresOn ?? DateTimeOffset.UtcNow.AddSeconds(10) }); } }
/// <summary> /// Processes the async to build the access the key vault and build the container. /// </summary> /// <returns>The async.</returns> /// <param name="containerName">Container name.</param> /// <param name="log">Log.</param> /// <param name="context">Context.</param> private static async Task ProcessAsync(string containerName, ILogger log, ExecutionContext context) { log.LogInformation("---- in ProcessAsync function"); CloudStorageAccount storageAccount = null; CloudBlobContainer cloudBlobContainer = null; //grab the environment variabled from the local.settings.json file string key_vault_uri = System.Environment.GetEnvironmentVariable("KEY_VAULT_URI"); string storage_name = System.Environment.GetEnvironmentVariable("STORAGE_NAME"); string storageConnectionString = System.Environment.GetEnvironmentVariable("CONNECTION_STRING"); log.LogInformation("---- setting my local variables for the key vault"); // Make a connection to key vault var azureServiceTokenProvider = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); log.LogInformation("---- create a Key Vault client"); // Build the URL for the key vault from the settings string keyVaultURI = key_vault_uri + "/secrets/" + storage_name; log.LogInformation("---- create the key vault URI"); try { var secret = await keyVaultClient.GetSecretAsync(keyVaultURI); var storagePrimaryAccessKey = secret.Value; storageConnectionString = storagePrimaryAccessKey; log.LogInformation("----- connection string was retrieved from the Key Vault"); } catch (Exception ex) { log.LogInformation("----- Cannot access the Key Vault."); } // Check whether the connection string can be parsed. if (CloudStorageAccount.TryParse(storageConnectionString, out storageAccount)) { try { log.LogInformation("Key Vault accessed."); // Create the CloudBlobClient that represents the Blob storage endpoint for the storage account. CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient(); // Fix the string to make it comply with the rules containerName = containerName.ToLower(); containerName = containerName.Replace(" ", "-"); cloudBlobContainer = cloudBlobClient.GetContainerReference(containerName); await cloudBlobContainer.CreateAsync(); //// Set the permissions so the blobs are public. If commented out, the default should make it only readable to the owner of the storage account. //BlobContainerPermissions permissions = new BlobContainerPermissions //{ // PrivateAccess = // PublicAccess = BlobContainerPublicAccessType.Blob //}; //await cloudBlobContainer.SetPermissionsAsync(permissions); } catch (StorageException ex) { log.LogInformation("Error returned from the service: {0}", ex.Message); } } else { log.LogInformation("Key Vault access failed. A connection string has not been " + "defined in the system environment variables."); } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { if (HostingEnvironment.IsDevelopment()) { services.AddDataProtection() .SetDefaultKeyLifetime(LoginCookieLifetime * 2); } else { IConfigurationSection dpConfig = Configuration.GetSection("DataProtection"); string vaultUri = Configuration["KeyVaultUri"]; string keyVaultKeyIdentifierName = dpConfig["KeyIdentifier"]; var provider = new AzureServiceTokenProvider(); var kvClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(provider.KeyVaultTokenCallback)); KeyBundle key = kvClient.GetKeyAsync(vaultUri, keyVaultKeyIdentifierName).GetAwaiter().GetResult(); services.AddDataProtection() .PersistKeysToAzureBlobStorage(new Uri(dpConfig["KeyFileUri"])) .ProtectKeysWithAzureKeyVault(kvClient, key.KeyIdentifier.ToString()) .SetDefaultKeyLifetime(LoginCookieLifetime * 2) .SetApplicationName(typeof(Startup).FullName); } ConfigureApiServices(services); services.Configure <CookiePolicyOptions>( options => { options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.Lax; options.HttpOnly = Microsoft.AspNetCore.CookiePolicy.HttpOnlyPolicy.Always; if (HostingEnvironment.IsDevelopment()) { options.Secure = CookieSecurePolicy.SameAsRequest; } else { options.Secure = CookieSecurePolicy.Always; } }); services.AddBuildAssetRegistry( options => { options.UseSqlServer(Configuration.GetSection("BuildAssetRegistry")["ConnectionString"]); }); services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_1) .AddFluentValidation(options => options.RegisterValidatorsFromAssemblyContaining <Startup>()) .AddRazorPagesOptions( options => { options.Conventions.AuthorizeFolder("/", MsftAuthorizationPolicyName); options.Conventions.AllowAnonymousToPage("/Index"); options.Conventions.AllowAnonymousToPage("/Error"); options.Conventions.AllowAnonymousToPage("/SwaggerUi"); }) .AddGitHubWebHooks() .AddApiPagination() .AddCookieTempDataProvider( options => { // Cookie Policy will not send this cookie unless we mark it as Essential // The application will not function without this cookie. options.Cookie.IsEssential = true; }); services.AddSingleton <IConfiguration>(Configuration); ConfigureAuthServices(services); services.AddSingleton <BackgroundQueue>(); services.AddSingleton <IHostedService>(provider => provider.GetRequiredService <BackgroundQueue>()); services.AddServiceFabricService <IDependencyUpdater>("fabric:/MaestroApplication/DependencyUpdater"); services.AddGitHubTokenProvider(); services.Configure <GitHubClientOptions>(o => { o.ProductHeader = new Octokit.ProductHeaderValue("Maestro", Assembly.GetEntryAssembly() .GetCustomAttribute <AssemblyInformationalVersionAttribute>() ?.InformationalVersion); }); services.Configure <GitHubTokenProviderOptions>( (options, provider) => { IConfigurationSection section = Configuration.GetSection("GitHub"); section.Bind(options); }); services.AddAzureDevOpsTokenProvider(); services.Configure <AzureDevOpsTokenProviderOptions>( (options, provider) => { var config = provider.GetRequiredService <IConfiguration>(); var tokenMap = config.GetSection("AzureDevOps:Tokens").GetChildren(); foreach (IConfigurationSection token in tokenMap) { options.Tokens.Add(token.GetValue <string>("Account"), token.GetValue <string>("Token")); } }); services.AddKustoClientProvider( options => { IConfigurationSection section = Configuration.GetSection("Kusto"); section.Bind(options); }); // We do not use AddMemoryCache here. We use our own cache because we wish to // use a sized cache and some components, such as EFCore, do not implement their caching // in such a way that will work with sizing. services.AddSingleton <DarcRemoteMemoryCache>(); services.AddSingleton <IRemoteFactory, DarcRemoteFactory>(); services.AddSingleton(typeof(IActorProxyFactory <>), typeof(ActorProxyFactory <>)); services.AddMergePolicies(); }
public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, ExecutionContext exCtx, TraceWriter log) { _logger = log; _logger.Info($"Function-({_invocationId}): Triggered a Function which processess email"); //string superSecret = System.Environment.GetEnvironmentVariable("SuperSecret"); // parse query parameter string RunId = req.GetQueryNameValuePairs() .FirstOrDefault(q => string.Compare(q.Key, "RunId", true) == 0) .Value; if (RunId == null) { // Get request body dynamic data = await req.Content.ReadAsAsync <object>(); RunId = data?.RunId; } string ProcessName = req.GetQueryNameValuePairs() .FirstOrDefault(q => string.Compare(q.Key, "ProcessName", true) == 0) .Value; if (ProcessName == null) { // Get request body dynamic data = await req.Content.ReadAsAsync <object>(); ProcessName = data?.ProcessName; } if (ProcessName is null) { ProcessName = "NULL"; } var str = "Server = tcp:sc-az-datacontrol-srv1.database.windows.net,1433; Initial Catalog = CandelaKPI-DEV; Persist Security Info = False; User ID = Dev; Password =fba4bUyzBV7QvXEq; MultipleActiveResultSets = False; Encrypt = True; TrustServerCertificate = False; Connection Timeout = 30;"; try { using (SqlConnection conn = new SqlConnection(str)) { conn.Open(); //SecretRequest secretRequest = await req.Content.ReadAsAsync<SecretRequest>(); //if (string.IsNullOrEmpty(secretRequest.Secret)) // return req.CreateResponse(HttpStatusCode.BadRequest, "Request does not contain a valid Secret."); // Commented for time being AzureServiceTokenProvider serviceTokenProvider = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(serviceTokenProvider.KeyVaultTokenCallback)); //var secretUri = SecretUri(secretRequest.Secret); SecretBundle emailAccount; SecretBundle emailPassword; try { string secretUri = "https://CandelaBIKV.vault.azure.net/Secrets/EmailAccount"; emailAccount = await keyVaultClient.GetSecretAsync(secretUri).ConfigureAwait(false); secretUri = "https://CandelaBIKV.vault.azure.net/Secrets/EmailPassword"; emailPassword = await keyVaultClient.GetSecretAsync(secretUri).ConfigureAwait(false); //log.Info($"Function-({_invocationId}): Success in fetching the secret value from KeyVault "); Logger("Success in fetching the secret value from KeyVault", "INFO", null, ProcessName, RunId, conn); } catch (Exception kex) { Logger("Error in getting the Secret value from KeyVault for the secret: VisionBIServiceAccount", "ERROR", kex.Message.Replace("'", ""), ProcessName, RunId, conn); //log.Error($"Function-({_invocationId}): Error in getting the Secret value from KeyVault for the secret: VisionBIServiceAccount ", kex); return(req.CreateResponse(HttpStatusCode.ExpectationFailed, $"{kex}")); } string fromEmail = emailAccount.Value;//"*****@*****.**";// "vamshi @snp.com"; //string fromEmail = "*****@*****.**"; string toEmail = "*****@*****.**"; int smtpPort = 587; bool smtpEnableSsl = true; string smtpHost = "smtp.office365.com"; // your smtp host string smtpUser = emailAccount.Value; //"*****@*****.**";// "Vamshi @snp.com"; // your smtp user Configuration["Values:SMTPUser"]; // //string smtpUser = "******"; // your smtp user Configuration["Values:SMTPUser"]; // string smtpPass = emailPassword.Value; // ""; // your smtp password //string smtpPass = ""; // your smtp password string subject = "DataLoad Process"; string message = ""; //int emailstobesend; string Error = ""; MailMessage mail = new MailMessage(fromEmail, toEmail); SmtpClient client = new SmtpClient(); client.Port = smtpPort; client.EnableSsl = smtpEnableSsl; client.DeliveryMethod = SmtpDeliveryMethod.Network; client.UseDefaultCredentials = false; client.Host = smtpHost; client.Credentials = new System.Net.NetworkCredential(smtpUser, smtpPass); mail.Priority = MailPriority.High; mail.IsBodyHtml = true; mail.CC.Add("*****@*****.**"); //mail.Bcc.Add("*****@*****.**"); Logger("Generating Email Body is started", "INFO", null, ProcessName, RunId, conn); string sql = "SELECT [ProcessName],[Summary],[Status],[ErrorInfo],[LoggedTime],[RecordsInSource],[RecordsCopiedToDest],[SkippedRecordsToMove],[CopyDuration(Seconds)] as Duration,LogsPath FROM BI.LG_ProcessLogs where RunId = '" + RunId + "' Order by ID"; subject = "Data Load is completed and below are the details - " + RunId; message = ""; if (conn.State == ConnectionState.Closed) { conn.Open(); } using (var command = new SqlCommand(sql, conn)) { message = message + "<table border=1 ><tr><td style='background:#8EAADB;'><b>PROCESS NAME </b></td><td style='background:#8EAADB;'><b>SUMMARY</b></td><td style='background:#8EAADB;'><b>ERROR INFO</b></td><td style='background:#8EAADB;'><b>PROCESSTIME</b></td><td style='background:#8EAADB;'><b>NO.OF RECORDS IN SOURCE</b></td><td style='background:#8EAADB;'><b>NO.OF RECORDS COPIED TO DESTINATION</b></td><td style='background:#8EAADB;'><b>NO.OF RECORDS SKIPPED</b></td><td style='background:#8EAADB;'><b>DURATION(SECONDS)</b></td><td style='background:#8EAADB;'><b>LOGS PATH</b></td><td style='background:#8EAADB;'><b>STATUS</b></td></tr>"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { message = message + "<tr><td>" + reader["ProcessName"] + "</td><td>" + reader["Summary"] + "</td><td>" + reader["ErrorInfo"] + "</td><td>" + reader["LoggedTime"].ToString() + "</td><td>" + reader["RecordsInSource"].ToString() + "</td><td>" + reader["RecordsCopiedToDest"].ToString() + "</td><td>" + reader["SkippedRecordsToMove"].ToString() + "</td><td>" + reader["Duration"] + "</td><td>" + reader["LogsPath"] + "</td>";//</tr>" if (reader["Status"].Equals("ERROR")) { message = message + "<td><b><span style='color:red'>" + reader["Status"] + "</span></b></td></tr>"; Error = "1"; } else if (reader["Status"].Equals("INFO")) { message = message + "<td><b><span style='color:Green'>" + reader["Status"] + "</span></b></td></tr>"; } else { message = message + "<td><b><span style='color:Yellow'>" + reader["Status"] + "</span></td></b></tr> "; } } } message = message + "</table>"; } message = message + "</body></html>"; if (Error == "1") { subject = "Errors in : " + subject; message = "<html><body> <b><span style='color:red'>Noticed Errors in the data loading please check the below details:</span></b><br><br>" + message; } else { subject = subject; message = "<html><body> " + message; } mail.Subject = subject; mail.Body = message; try { client.Send(mail); Logger("Process Email is sent", "INFO", null, ProcessName, RunId, conn); //log.Verbose("Email sent."); } catch (Exception ex) { Logger("Failed To Send an Email", "ERROR", ex.Message.Replace("'", ""), ProcessName, RunId, conn); return(req.CreateResponse(HttpStatusCode.ExpectationFailed, ex)); //log.Verbose("Error sent."); } } } catch (Exception ex) { _logger.Error($"Function-({_invocationId}): Failed to process email for the ADF Run Id: {RunId}", ex); return(req.CreateResponse(HttpStatusCode.ExpectationFailed, ex)); } return(req.CreateResponse(HttpStatusCode.OK)); }
public static async Task <HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestMessage req, TraceWriter log) { log.Info("C# HTTP trigger function processed a request."); // parse query parameter string requestedNumber = req.GetQueryNameValuePairs() .FirstOrDefault(q => string.Compare(q.Key, "number", true) == 0) .Value; string requestedFirstName = req.GetQueryNameValuePairs() .FirstOrDefault(q => string.Compare(q.Key, "firstname", true) == 0) .Value; if (requestedNumber == null || requestedFirstName == null) { return(req.CreateResponse(HttpStatusCode.BadRequest, "Please supply both firstname and number")); } // Connect to the dataverse var dataverseUrl = Environment.GetEnvironmentVariable("DataverseUrl", EnvironmentVariableTarget.Process); var tokenProviderConnectionString = Environment.GetEnvironmentVariable("TokenProviderConnectionString", EnvironmentVariableTarget.Process); var azureTokenProvider = new AzureServiceTokenProvider(tokenProviderConnectionString); CrmServiceClient.AuthOverrideHook = new CrmClientOverrideAuthHookWrapper(azureTokenProvider); var client = new CrmServiceClient(new Uri(dataverseUrl), true); if (!client.IsReady) { throw new Exception($"CrmService not ready! {client.LastCrmError}"); } var context = new XrmServiceContext(client); var phoneUtil = PhoneNumberUtil.GetInstance(); var phoneNumber = phoneUtil.Parse(requestedNumber, "GB"); var response = (from c in context.ContactSet where c.FirstName.Equals(requestedFirstName) select new GetContactsResponse { ContactId = c.Id, FullName = c.FullName, FirstName = c.FirstName, LastName = c.LastName, MobilePhone = c.MobilePhone, }).ToList(); // Supplement the data foreach (var row in response) { var rowPhoneNumber = phoneUtil.Parse(row.MobilePhone, "GB"); if (phoneUtil.IsNumberMatch(phoneNumber, rowPhoneNumber) == PhoneNumberUtil.MatchType.EXACT_MATCH) { // Populate Journeys with static data for demo purposes row.Journeys = new List <Models.Journey>(); row.Journeys.Add(new Models.Journey { From = "London", To = "Glasgow", JourneyType = Models.JourneyType.Train, Date = new DateTime(2020, 02, 15) }); } } // Return complex object return((response.Count == 0) ? req.CreateResponse(HttpStatusCode.NotFound) : req.CreateResponse(HttpStatusCode.OK, response, "application/json")); }
public override async Task <string> AcquireAccessToken() { var azureServiceTokenProvider = new AzureServiceTokenProvider(azureAdInstance: AzureActiveDirectoryInstance); return(await azureServiceTokenProvider.GetAccessTokenAsync(Audience)); }
public ReservationsDataContext(IDbConnection connection, IOptions <ReservationsConfiguration> configuration, DbContextOptions options, AzureServiceTokenProvider azureServiceTokenProvider, bool configurationIsLocalOrDev) : base(options) { _configuration = configuration.Value; _azureServiceTokenProvider = azureServiceTokenProvider; _configurationIsLocalOrDev = configurationIsLocalOrDev; _connection = connection; }
public static async Task Run([TimerTrigger("0 0 0 * * *")] TimerInfo myTimer, ILogger log) { AzureServiceTokenProvider tokenProvider = new AzureServiceTokenProvider(); string deploymentEnvironment = Environment.GetEnvironmentVariable("DeploymentEnvironment") ?? "Staging"; log.LogInformation($"INFO: Deployment Environment: {deploymentEnvironment}"); log.LogInformation("INFO: Getting storage account keys from KeyVault..."); SecretBundle scorecardsStorageAccountKey = await GetStorageAccountKeyAsync(tokenProvider, Utilities.KeyVaultUri, ScorecardsStorageAccount.KeySecretName); SecretBundle deploymentTableSasToken = await GetStorageAccountKeyAsync(tokenProvider, "https://DotNetEng-Status-Prod.vault.azure.net", "deployment-table-sas-token"); log.LogInformation("INFO: Getting cloud tables..."); CloudTable scorecardsTable = Utilities.GetScorecardsCloudTable(scorecardsStorageAccountKey.Value); CloudTable deploymentsTable = new CloudTable( new Uri($"https://dotnetengstatusprod.table.core.windows.net/deployments{deploymentTableSasToken.Value}")); List <ScorecardEntity> scorecardEntries = await GetAllTableEntriesAsync <ScorecardEntity>(scorecardsTable); scorecardEntries.Sort((x, y) => x.Date.CompareTo(y.Date)); List <AnnotationEntity> deploymentEntries = await GetAllTableEntriesAsync <AnnotationEntity>(deploymentsTable); deploymentEntries.Sort((x, y) => (x.Ended ?? DateTimeOffset.MaxValue).CompareTo(y.Ended ?? DateTimeOffset.MaxValue)); log.LogInformation($"INFO: Found {scorecardEntries?.Count ?? -1} scorecard table entries and {deploymentEntries?.Count ?? -1} deployment table entries." + $"(-1 indicates that null was returned.)"); // The deployments we care about are ones that occurred after the last scorecard IEnumerable <AnnotationEntity> relevantDeployments = deploymentEntries.Where(d => (d.Ended ?? DateTimeOffset.MaxValue) > scorecardEntries.Last().Date.AddDays(ScoringBufferInDays)); log.LogInformation($"INFO: Found {relevantDeployments?.Count() ?? -1} relevant deployments (deployments which occurred " + $"after the last scorecard). (-1 indicates that null was returned.)"); if (relevantDeployments.Count() > 0) { log.LogInformation("INFO: Checking to see if the most recent deployment occurred more than two days ago..."); // We have only want to score if the buffer period has elapsed since the last deployment if ((relevantDeployments.Last().Ended ?? DateTimeOffset.MaxValue) < DateTimeOffset.UtcNow - TimeSpan.FromDays(ScoringBufferInDays)) { var scorecards = new List <Scorecard>(); log.LogInformation("INFO: Rollouts will be scored. Fetching GitHub PAT..."); SecretBundle githubPat; using (KeyVaultClient kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback))) { githubPat = await kv.GetSecretAsync(Utilities.KeyVaultUri, Utilities.GitHubPatSecretName); } // We'll score the deployments by service foreach (var deploymentGroup in relevantDeployments.GroupBy(d => d.Service)) { log.LogInformation($"INFO: Scoring {deploymentGroup?.Count() ?? -1} rollouts for repo '{deploymentGroup.Key}'"); RolloutScorer.RolloutScorer rolloutScorer = new RolloutScorer.RolloutScorer { Repo = deploymentGroup.Key, RolloutStartDate = deploymentGroup.First().Started.GetValueOrDefault().Date, RolloutWeightConfig = Configs.DefaultConfig.RolloutWeightConfig, GithubConfig = Configs.DefaultConfig.GithubConfig, Log = log, }; log.LogInformation($"INFO: Finding repo config for {rolloutScorer.Repo}..."); rolloutScorer.RepoConfig = Configs.DefaultConfig.RepoConfigs .Find(r => r.Repo == rolloutScorer.Repo); log.LogInformation($"INFO: Repo config: {rolloutScorer.RepoConfig.Repo}"); log.LogInformation($"INFO: Finding AzDO config for {rolloutScorer.RepoConfig.AzdoInstance}..."); rolloutScorer.AzdoConfig = Configs.DefaultConfig.AzdoInstanceConfigs .Find(a => a.Name == rolloutScorer.RepoConfig.AzdoInstance); log.LogInformation($"INFO: Fetching AzDO PAT from KeyVault..."); using (KeyVaultClient kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(tokenProvider.KeyVaultTokenCallback))) { rolloutScorer.SetupHttpClient( (await kv.GetSecretAsync(rolloutScorer.AzdoConfig.KeyVaultUri, rolloutScorer.AzdoConfig.PatSecretName)).Value); } rolloutScorer.SetupGithubClient(githubPat.Value); log.LogInformation($"INFO: Attempting to initialize RolloutScorer..."); try { await rolloutScorer.InitAsync(); } catch (ArgumentException e) { log.LogError($"ERROR: Error while processing {rolloutScorer.RolloutStartDate} rollout of {rolloutScorer.Repo}."); log.LogError($"ERROR: {e.Message}"); continue; } log.LogInformation($"INFO: Creating rollout scorecard..."); scorecards.Add(await Scorecard.CreateScorecardAsync(rolloutScorer)); log.LogInformation($"INFO: Successfully created scorecard for {rolloutScorer.RolloutStartDate.Date} rollout of {rolloutScorer.Repo}."); } log.LogInformation($"INFO: Uploading results for {string.Join(", ", scorecards.Select(s => s.Repo))}"); await RolloutUploader.UploadResultsAsync(scorecards, Utilities.GetGithubClient(githubPat.Value), scorecardsStorageAccountKey.Value, Configs.DefaultConfig.GithubConfig, skipPr : deploymentEnvironment != "Production"); } else { log.LogInformation(relevantDeployments.Last().Ended.HasValue ? $"INFO: Most recent rollout occurred less than two days ago " + $"({relevantDeployments.Last().Service} on {relevantDeployments.Last().Ended.Value}); waiting to score." : $"Most recent rollout ({relevantDeployments.Last().Service}) is still in progress."); } } else { log.LogInformation($"INFO: Found no rollouts which occurred after last recorded rollout " + $"({(scorecardEntries.Count > 0 ? $"date {scorecardEntries.Last().Date}" : "no rollouts in table")})"); } }
public KeyVaultManager() { AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(); KeyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); }
static void Main(string[] args) { IConfiguration configuration = new ConfigurationBuilder() .AddJsonFile($"appsettings.json", true, true) .AddEnvironmentVariables() .Build(); string keyvault_endpoint = configuration["KEYVAULT_ENDPOINT"]; if (!string.IsNullOrEmpty(keyvault_endpoint)) { ConsoleWrite("Loading configuration from Azure Key Vault: " + keyvault_endpoint); var azureServiceTokenProvider = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback( azureServiceTokenProvider.KeyVaultTokenCallback)); configuration = new ConfigurationBuilder() .AddConfiguration(configuration) .AddAzureKeyVault(keyvault_endpoint, keyVaultClient, new DefaultKeyVaultSecretManager()) .Build(); } IConfigurationSection smtpConfig = configuration.GetSection("SMTP"); string dbConnectionString = configuration.GetConnectionString(RunnerSettings.ConnectionStringName) ?? string.Empty; if (string.IsNullOrEmpty(dbConnectionString)) { ConsoleWrite("ConnectionString can't be empty"); } else { ConsoleWrite("EmailRunner starting main loop..."); while (true) { try { using (DistanceEdRequestRepository requestRepository = new DistanceEdRequestRepository(dbConnectionString)) { List <DistanceEdRequest> requestsNeedingNotification = requestRepository.GetRequestsRequiringNotification(); EmailHelper email = new EmailHelper(smtpConfig["hostname"], smtpConfig["port"].ToInt(), smtpConfig["username"], smtpConfig["password"], smtpConfig["fromaddress"], smtpConfig["replytoaddress"]); List <string> helpDeskEmailAddresses = smtpConfig["HelpDeskEmail"].Split(new char[] { ';', ',' }).ToList(); if (requestsNeedingNotification.Count > 0) { ConsoleWrite("Found " + requestsNeedingNotification.Count + " requests needing notifications"); foreach (DistanceEdRequest r in requestsNeedingNotification) { ConsoleWrite("Enqueing notifcation for request ID " + r.ID); email.NewMessage(r); } } else { ConsoleWrite("No new requests found"); } Console.WriteLine("Sending..."); List <int> successfulIDs = email.SendAll(helpDeskEmailAddresses); Console.WriteLine("Marking " + successfulIDs.Count + " as successes"); requestRepository.MarkAsHelpDeskNotified(successfulIDs); } } catch (Exception ex) { ConsoleWrite("ERROR: " + ex.Message); if (ex.InnerException != null) { ConsoleWrite(" EXCEPTION: " + ex.InnerException.Message); } } ConsoleWrite("Done!"); ConsoleWrite("Sleeping for " + sleepTimeMinutes + " minutes..."); // Sleep Task.Delay(sleepTimeMinutes * 60 * 1000).Wait(); } } }
public AuthenticationMsiTokenService() { // The constructor is pretty heavy, so prefer to // do it only once: _azureServiceTokenProvider = new AzureServiceTokenProvider(); }
public void ConfigureServices(IServiceCollection services) { services.AddSingleton <ILocalizationProvider, StorageLocalizationProvider>(); services.AddTextLocalization(options => { options.ReturnOnlyKeyIfNotFound = !_environment.IsDevelopment(); options.FallBackNeutralCulture = !_environment.IsDevelopment(); }).Configure <RequestLocalizationOptions>(options => { options.DefaultRequestCulture = new RequestCulture(Settings.SupportedCultures[0]); options.AddSupportedCultures(Settings.SupportedCultures); options.AddSupportedUICultures(Settings.SupportedCultures); }); var dataProtectionBuilder = services.AddDataProtection().SetApplicationName(projectName); services.RegisterStorage(Configuration); services.Configure <ApiBehaviorOptions>(options => { options.SuppressModelStateInvalidFilter = true; }); services.AddIdentity <ApplicationUser, ApplicationRole>() .AddRoles <ApplicationRole>() .AddEntityFrameworkStores <ApplicationDbContext>() .AddDefaultTokenProviders() .AddErrorDescriber <LocalizedIdentityErrorDescriber>(); services.AddScoped <IUserClaimsPrincipalFactory <ApplicationUser>, AdditionalUserClaimsPrincipalFactory>(); var authAuthority = Configuration[$"{projectName}:IS4ApplicationUrl"].TrimEnd('/'); // Adds IdentityServer https://identityserver4.readthedocs.io/en/latest/reference/options.html var identityServerBuilder = services.AddIdentityServer(options => { options.IssuerUri = authAuthority; options.Events.RaiseErrorEvents = true; options.Events.RaiseInformationEvents = true; options.Events.RaiseFailureEvents = true; options.Events.RaiseSuccessEvents = true; options.UserInteraction.ErrorUrl = "/identityserver/error"; }) .AddIdentityServerStores(Configuration) .AddAspNetIdentity <ApplicationUser>(); //https://identityserver4.readthedocs.io/en/latest/reference/aspnet_identity.html X509Certificate2 cert = null; var keysFolder = Path.Combine(_environment.ContentRootPath, "Keys"); if (_environment.IsDevelopment()) { // The AddDeveloperSigningCredential extension creates temporary key material tempkey.jwk for signing tokens. // This might be useful to get started, but needs to be replaced by some persistent key material for production scenarios. // See http://docs.identityserver.io/en/release/topics/crypto.html#refcrypto for more information. // https://stackoverflow.com/questions/42351274/identityserver4-hosting-in-iis identityServerBuilder.AddDeveloperSigningCredential(); dataProtectionBuilder.PersistKeysToFileSystem(new DirectoryInfo(keysFolder)); } else { // running on azure // please make sure to replace your vault URI and your certificate name in appsettings.json! if (Convert.ToBoolean(Configuration["HostingOnAzure:RunsOnAzure"]) == true) { // if we use a key vault if (Convert.ToBoolean(Configuration["HostingOnAzure:AzurekeyVault:UsingKeyVault"]) == true) { //https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview dataProtectionBuilder.PersistKeysToAzureBlobStorage(new Uri("<blobUriWithSasToken>")) .ProtectKeysWithAzureKeyVault("<keyIdentifier>", "<clientId>", "<clientSecret>"); // if managed app identity is used if (Convert.ToBoolean(Configuration["HostingOnAzure:AzurekeyVault:UseManagedAppIdentity"]) == true) { AzureServiceTokenProvider azureServiceTokenProvider = new AzureServiceTokenProvider(); var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback)); var certificateBundle = keyVaultClient.GetSecretAsync(Configuration["HostingOnAzure:AzureKeyVault:VaultURI"], Configuration["HostingOnAzure:AzurekeyVault:CertificateName"]).GetAwaiter().GetResult(); var certificate = Convert.FromBase64String(certificateBundle.Value); cert = new X509Certificate2(certificate, (string)null, X509KeyStorageFlags.MachineKeySet); } } else // if app id and app secret are used { throw new NotImplementedException(); } } else { dataProtectionBuilder.PersistKeysToFileSystem(new DirectoryInfo(keysFolder)); } //TODO this implementation does not consider certificate expiration if (Convert.ToBoolean(Configuration[$"{projectName}:UseLocalCertStore"]) == true) { var certificateThumbprint = Configuration[$"{projectName}:CertificateThumbprint"]; var storeLocation = StoreLocation.LocalMachine; dynamic storeName = "WebHosting"; if (OperatingSystem.IsLinux()) { storeLocation = StoreLocation.CurrentUser; storeName = StoreName.My; } using X509Store store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); var certs = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false); if (certs.Count > 0) { cert = certs[0]; } else { var certPath = Path.Combine(_environment.ContentRootPath, "AuthSample.pfx"); if (File.Exists(certPath)) { string certificatePassword = Configuration[$"{projectName}:CertificatePassword"] ?? "Admin123"; cert = new X509Certificate2(certPath, certificatePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable); } } store.Close(); } // pass the resulting certificate to Identity Server if (cert != null) { identityServerBuilder.AddSigningCredential(cert); Log.Logger.Information($"Added certificate {cert.Subject} to Identity Server"); } else if (OperatingSystem.IsWindows()) { Log.Logger.Debug("Trying to use WebHosting Certificate for Identity Server"); identityServerBuilder.AddWebHostingCertificate(); } else { throw new Exception("Missing Certificate for Identity Server"); } } var authBuilder = services.AddAuthentication(options => { options.DefaultScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme; }) .AddIdentityServerAuthentication(options => { options.Authority = authAuthority; options.SupportedTokens = SupportedTokens.Jwt; options.RequireHttpsMetadata = _environment.IsProduction(); options.ApiName = IdentityServerConfig.LocalApiName; options.Events = new JwtBearerEvents { OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; // If the request is for our hub... var path = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/chathub"))) { // Read the token out of the query string context.Token = accessToken; } return(Task.CompletedTask); } }; }); #region ExternalAuthProviders //https://github.com/dotnet/aspnetcore/blob/master/src/Security/Authentication/samples/SocialSample/Startup.cs //https://docs.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins if (Convert.ToBoolean(Configuration["ExternalAuthProviders:Google:Enabled"] ?? "false")) { authBuilder.AddGoogle(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.ClientId = Configuration["ExternalAuthProviders:Google:ClientId"]; options.ClientSecret = Configuration["ExternalAuthProviders:Google:ClientSecret"]; options.AuthorizationEndpoint += "?prompt=consent"; // Hack so we always get a refresh token, it only comes on the first authorization response options.AccessType = "offline"; options.SaveTokens = true; options.Events = new OAuthEvents() { OnRemoteFailure = HandleOnRemoteFailure }; options.ClaimActions.MapJsonSubKey("urn:google:image", "image", "url"); options.ClaimActions.Remove(ClaimTypes.GivenName); }); } if (Convert.ToBoolean(Configuration["ExternalAuthProviders:Facebook:Enabled"] ?? "false")) { // You must first create an app with Facebook and add its ID and Secret to your user-secrets. // https://developers.facebook.com/apps/ // https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#login authBuilder.AddFacebook(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.AppId = Configuration["ExternalAuthProviders:Facebook:AppId"]; options.AppSecret = Configuration["ExternalAuthProviders:Facebook:AppSecret"]; options.Scope.Add("email"); options.Fields.Add("name"); options.Fields.Add("email"); options.SaveTokens = true; options.Events = new OAuthEvents() { OnRemoteFailure = HandleOnRemoteFailure }; }); } if (Convert.ToBoolean(Configuration["ExternalAuthProviders:Twitter:Enabled"] ?? "false")) { // You must first create an app with Twitter and add its key and Secret to your user-secrets. // https://apps.twitter.com/ // https://developer.twitter.com/en/docs/basics/authentication/api-reference/access_token authBuilder.AddTwitter(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.ConsumerKey = Configuration["ExternalAuthProviders:Twitter:ConsumerKey"]; options.ConsumerSecret = Configuration["ExternalAuthProviders:Twitter:ConsumerSecret"]; // http://stackoverflow.com/questions/22627083/can-we-get-email-id-from-twitter-oauth-api/32852370#32852370 // http://stackoverflow.com/questions/36330675/get-users-email-from-twitter-api-for-external-login-authentication-asp-net-mvc?lq=1 options.RetrieveUserDetails = true; options.SaveTokens = true; options.ClaimActions.MapJsonKey("urn:twitter:profilepicture", "profile_image_url", ClaimTypes.Uri); options.Events = new TwitterEvents() { OnRemoteFailure = HandleOnRemoteFailure }; }); } //https://github.com/xamarin/Essentials/blob/master/Samples/Sample.Server.WebAuthenticator/Startup.cs if (Convert.ToBoolean(Configuration["ExternalAuthProviders:Apple:Enabled"] ?? "false")) { authBuilder.AddApple(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.ClientId = Configuration["ExternalAuthProviders:Apple:ClientId"]; options.KeyId = Configuration["ExternalAuthProviders:Apple:KeyId"]; options.TeamId = Configuration["ExternalAuthProviders:Apple:TeamId"]; options.UsePrivateKey(keyId => _environment.ContentRootFileProvider.GetFileInfo($"AuthKey_{keyId}.p8")); options.SaveTokens = true; }); } // You must first create an app with Microsoft Account and add its ID and Secret to your user-secrets. // https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app if (Convert.ToBoolean(Configuration["ExternalAuthProviders:Microsoft:Enabled"] ?? "false")) { authBuilder.AddMicrosoftAccount(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.ClientId = Configuration["ExternalAuthProviders:Microsoft:ClientId"]; options.ClientSecret = Configuration["ExternalAuthProviders:Microsoft:ClientSecret"]; options.SaveTokens = true; options.Scope.Add("offline_access"); options.Events = new OAuthEvents() { OnRemoteFailure = HandleOnRemoteFailure }; }); } #endregion #region Authorization //Add Policies / Claims / Authorization - https://identityserver4.readthedocs.io/en/latest/topics/add_apis.html#advanced services.AddScoped <EntityPermissions>(); services.AddSingleton <IAuthorizationPolicyProvider, AuthorizationPolicyProvider>(); services.AddTransient <IAuthorizationHandler, DomainRequirementHandler>(); services.AddTransient <IAuthorizationHandler, PermissionRequirementHandler>(); #endregion services.Configure <IdentityOptions>(options => { // Password settings options.Password.RequireDigit = RequireDigit; options.Password.RequiredLength = RequiredLength; options.Password.RequireNonAlphanumeric = RequireNonAlphanumeric; options.Password.RequireUppercase = RequireUppercase; options.Password.RequireLowercase = RequireLowercase; //options.Password.RequiredUniqueChars = 6; // Lockout settings options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30); options.Lockout.MaxFailedAccessAttempts = 10; options.Lockout.AllowedForNewUsers = true; // Require Confirmed Email User settings if (Convert.ToBoolean(Configuration[$"{projectName}:RequireConfirmedEmail"] ?? "false")) { options.User.RequireUniqueEmail = true; options.SignIn.RequireConfirmedEmail = true; } }); #region Cookies // cookie policy to deal with temporary browser incompatibilities services.AddSameSiteCookiePolicy(); //https://docs.microsoft.com/en-us/aspnet/core/security/gdpr services.Configure <CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential // cookies is needed for a given request. options.CheckConsentNeeded = context => false; //consent not required // requires using Microsoft.AspNetCore.Http; //options.MinimumSameSitePolicy = SameSiteMode.None; }); //services.ConfigureExternalCookie(options => // { // macOS login fix //options.Cookie.SameSite = SameSiteMode.None; //}); services.ConfigureApplicationCookie(options => { options.Cookie.IsEssential = true; options.Cookie.HttpOnly = true; options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; options.ExpireTimeSpan = TimeSpan.FromMinutes(60); options.LoginPath = Constants.Settings.LoginPath; //options.AccessDeniedPath = "/Identity/Account/AccessDenied"; // ReturnUrlParameter requires //using Microsoft.AspNetCore.Authentication.Cookies; options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter; options.SlidingExpiration = true; // Suppress redirect on API URLs in ASP.NET Core -> https://stackoverflow.com/a/56384729/54159 options.Events = new CookieAuthenticationEvents() { OnRedirectToAccessDenied = context => { if (context.Request.Path.StartsWithSegments("/api")) { context.Response.StatusCode = Status403Forbidden; } return(Task.CompletedTask); }, OnRedirectToLogin = context => { context.Response.StatusCode = Status401Unauthorized; return(Task.CompletedTask); } }; }); #endregion services.AddMvc().AddNewtonsoftJson(opt => { // Set Breeze defaults for entity serialization var ss = JsonSerializationFns.UpdateWithDefaults(opt.SerializerSettings); if (ss.ContractResolver is DefaultContractResolver resolver) { resolver.NamingStrategy = null; // remove json camelCasing; names are converted on the client. } if (_environment.IsDevelopment()) { ss.Formatting = Newtonsoft.Json.Formatting.Indented; // format JSON for debugging } }) // Add Breeze exception filter to send errors back to the client .AddMvcOptions(o => { o.Filters.Add(new GlobalExceptionFilter()); }) .AddViewLocalization().AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => { return(factory.Create(typeof(Global))); }; }).AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining <LocalizationRecordValidator>()); services.AddServerSideBlazor().AddCircuitOptions(o => { if (_environment.IsDevelopment()) { o.DetailedErrors = true; } }); services.AddSignalR(); if (_enableAPIDoc) { services.AddOpenApiDocument(document => { document.Title = "BlazorBoilerplate API"; document.Version = typeof(Startup).GetTypeInfo().Assembly.GetName().Version.ToString(); document.AddSecurity("bearer", Enumerable.Empty <string>(), new OpenApiSecurityScheme { Type = OpenApiSecuritySchemeType.OAuth2, Description = "Local Identity Server", OpenIdConnectUrl = $"{authAuthority}/.well-known/openid-configuration", //not working Flow = OpenApiOAuth2Flow.AccessCode, Flows = new OpenApiOAuthFlows() { AuthorizationCode = new OpenApiOAuthFlow() { Scopes = new Dictionary <string, string> { { LocalApi.ScopeName, IdentityServerConfig.LocalApiName } }, AuthorizationUrl = $"{authAuthority}/connect/authorize", TokenUrl = $"{authAuthority}/connect/token" }, } });; document.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("bearer")); // new OperationSecurityScopeProcessor("bearer")); }); } services.AddScoped <IUserSession, UserSession>(); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); services.Add(ServiceDescriptor.Scoped(typeof(ITenantSettings <>), typeof(TenantSettingsManager <>))); services.AddTransient <IEmailFactory, EmailFactory>(); services.AddTransient <IAccountManager, AccountManager>(); services.AddTransient <IAdminManager, AdminManager>(); services.AddTransient <IEmailManager, EmailManager>(); services.AddTransient <IExternalAuthManager, ExternalAuthManager>(); #region Automapper //Automapper to map DTO to Models https://www.c-sharpcorner.com/UploadFile/1492b1/crud-operations-using-automapper-in-mvc-application/ var automapperConfig = new MapperConfiguration(configuration => { configuration.AddProfile(new MappingProfile()); }); var autoMapper = automapperConfig.CreateMapper(); services.AddSingleton(autoMapper); #endregion /* ServerSideBlazor */ services.AddScoped <IAccountApiClient, AccountApiClient>(); services.AddScoped <AppState>(); // setup HttpClient for server side in a client side compatible fashion ( with auth cookie ) // if (!services.Any(x => x.ServiceType == typeof(HttpClient))) // { services.AddScoped(s => { // creating the URI helper needs to wait until the JS Runtime is initialized, so defer it. var navigationManager = s.GetRequiredService <NavigationManager>(); var httpContextAccessor = s.GetRequiredService <IHttpContextAccessor>(); var cookies = httpContextAccessor.HttpContext.Request.Cookies; var httpClientHandler = new HttpClientHandler() { UseCookies = false }; if (_environment.IsDevelopment()) { // Return 'true' to allow certificates that are untrusted/invalid httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return(true); }; } var client = new HttpClient(httpClientHandler); if (cookies.Any()) { var cks = new List <string>(); foreach (var cookie in cookies) { cks.Add($"{cookie.Key}={cookie.Value}"); } client.DefaultRequestHeaders.Add("Cookie", string.Join(';', cks)); } client.BaseAddress = new Uri(navigationManager.BaseUri); return(client); }); // } services.AddScoped <ILocalizationApiClient, LocalizationApiClient>(); services.AddScoped <IApiClient, ApiClient>(); // Authentication providers Log.Logger.Debug("Removing AuthenticationStateProvider..."); var serviceDescriptor = services.FirstOrDefault(descriptor => descriptor.ServiceType == typeof(AuthenticationStateProvider)); if (serviceDescriptor != null) { services.Remove(serviceDescriptor); } Log.Logger.Debug("Adding AuthenticationStateProvider..."); services.AddScoped <AuthenticationStateProvider, IdentityAuthenticationStateProvider>(); /**********************/ services.AddModules(); if (Log.Logger.IsEnabled(Serilog.Events.LogEventLevel.Debug)) { Log.Logger.Debug($"Total Services Registered: {services.Count}"); foreach (var service in services) { Log.Logger.Debug($"\n\tService: {service.ServiceType.FullName}\n\tLifetime: {service.Lifetime}\n\tInstance: {service.ImplementationType?.FullName}"); } } }
public KeyVaultClient GetClient() { var azureServiceTokenProvider = new AzureServiceTokenProvider(); return(new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback))); }
public static IWebHostBuilder CreateWebHostBuilder(string[] args) => WebHost.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { var loggerFactory = LoggerFactory.Create(builder => { builder .AddConsole(); }); ILogger logger = loggerFactory.CreateLogger <Program>(); logger.LogInformation("Setting up app configurations..."); var builtConfig = config.Build(); try { AzureServiceTokenProvider azureServiceTokenProvider; string keyvaultConnectionString = null; string KeyVault = builtConfig["KeyVault"]; bool useKey; if (String.IsNullOrEmpty(KeyVault)) { throw new ConfigurationErrorsException("'KeyVault' property is missing from configuration"); } Boolean.TryParse(builtConfig["UseKey"], out useKey); if (useKey) { List <string> keys = new List <string> { "RunAs", "AppId", "TenantId", "AppKey" }; keys.ForEach(key => { if (String.IsNullOrEmpty(builtConfig[key])) { throw new ConfigurationErrorsException($"'{key}' property is missing from configuration"); } keyvaultConnectionString += $"{key}={builtConfig[key]};"; }); // end forEach } // end if azureServiceTokenProvider = new AzureServiceTokenProvider(keyvaultConnectionString); var keyVaultClient = new KeyVaultClient( new KeyVaultClient.AuthenticationCallback( azureServiceTokenProvider.KeyVaultTokenCallback)); config.AddAzureKeyVault( $"https://{KeyVault}.vault.azure.net/", keyVaultClient, new DefaultKeyVaultSecretManager()); logger.LogInformation("Configurations completed successfully..."); } catch (Exception ex) { logger.LogError($"Error while retrieving content from key vault:\n\t{ex.Message}\n"); logger.LogError(ex.StackTrace); throw ex; } // end try/catch }) .UseStartup <Startup>();