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);
                }
            }
        }
Beispiel #2
0
        public Task <string> Generate()
        {
            var azureServiceTokenProvider = new AzureServiceTokenProvider();

            return(azureServiceTokenProvider.GetAccessTokenAsync(_config.IdentifierUri));
        }
Beispiel #3
0
        /// <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
Beispiel #6
0
        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
            });
        }
Beispiel #8
0
        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."));
        }
    }
Beispiel #11
0
        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);
        }
Beispiel #12
0
        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));
        }
Beispiel #15
0
        // 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);
        }
Beispiel #17
0
        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)
                });
            }
        }
Beispiel #18
0
        /// <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.");
            }
        }
Beispiel #19
0
        // 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));
        }
Beispiel #21
0
        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));
        }
Beispiel #23
0
 public ReservationsDataContext(IDbConnection connection, IOptions <ReservationsConfiguration> configuration, DbContextOptions options, AzureServiceTokenProvider azureServiceTokenProvider, bool configurationIsLocalOrDev) : base(options)
 {
     _configuration             = configuration.Value;
     _azureServiceTokenProvider = azureServiceTokenProvider;
     _configurationIsLocalOrDev = configurationIsLocalOrDev;
     _connection = connection;
 }
Beispiel #24
0
        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();
                }
            }
        }
Beispiel #27
0
 public AuthenticationMsiTokenService()
 {
     // The constructor is pretty heavy, so prefer to
     // do it only once:
     _azureServiceTokenProvider = new AzureServiceTokenProvider();
 }
Beispiel #28
0
        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)));
        }
Beispiel #30
0
        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>();