/// <summary>
        /// Gets the expected value in a <see cref="X509Certificate2"/> for an <paramref name="configurationKey"/> using the specified <paramref name="services"/>.
        /// </summary>
        /// <param name="configurationKey">The configured key for which the expected certificate value is registered.</param>
        /// <param name="services">The services collections of the HTTP request pipeline to retrieve registered instances.</param>
        public async Task <string> GetExpectedCertificateValueForConfiguredKeyAsync(string configurationKey, IServiceProvider services)
        {
            Guard.NotNullOrWhitespace(configurationKey, nameof(configurationKey), "Configured key cannot be blank");
            Guard.NotNull(services, nameof(services), "Registered services cannot be 'null'");

            ISecretProvider userDefinedSecretProvider =
                services.GetService <ICachedSecretProvider>()
                ?? services.GetService <ISecretProvider>();

            if (userDefinedSecretProvider == null)
            {
                throw new KeyNotFoundException(
                          $"No configured {nameof(ICachedSecretProvider)} or {nameof(ISecretProvider)} implementation found in the request service container. "
                          + "Please configure such an implementation (ex. in the Startup) of your application");
            }

            Task <string> getValueAsync = userDefinedSecretProvider.Get(configurationKey);

            return(getValueAsync == null ? null : await getValueAsync);
        }
        /// <summary>
        /// Called early in the filter pipeline to confirm request is authorized.
        /// </summary>
        /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext" />.</param>
        /// <returns>
        ///     A <see cref="T:System.Threading.Tasks.Task" /> that on completion indicates the filter has executed.
        /// </returns>
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {
            Guard.NotNull(context, nameof(context));
            Guard.NotNull(context.HttpContext, nameof(context.HttpContext));
            Guard.For <ArgumentException>(() => context.HttpContext.Request == null, "Invalid action context given without any HTTP request");
            Guard.For <ArgumentException>(() => context.HttpContext.Request.Headers == null, "Invalid action context given without any HTTP request headers");
            Guard.For <ArgumentException>(() => context.HttpContext.RequestServices == null, "Invalid action context given without any HTTP request services");

            if (context.HttpContext.Request.Headers
                .TryGetValue(_headerName, out StringValues requestSecretHeaders))
            {
                ISecretProvider userDefinedSecretProvider =
                    context.HttpContext.RequestServices.GetService <ICachedSecretProvider>()
                    ?? context.HttpContext.RequestServices.GetService <ISecretProvider>();

                if (userDefinedSecretProvider == null)
                {
                    throw new KeyNotFoundException(
                              $"No configured {nameof(ICachedSecretProvider)} or {nameof(ISecretProvider)} implementation found in the request service container. "
                              + "Please configure such an implementation (ex. in the Startup) of your application");
                }

                string foundSecret = await userDefinedSecretProvider.Get(_secretName);

                if (foundSecret == null)
                {
                    throw new SecretNotFoundException(_secretName);
                }

                if (requestSecretHeaders.Any(headerValue => !String.Equals(headerValue, foundSecret)))
                {
                    context.Result = new UnauthorizedResult();
                }
            }
            else
            {
                context.Result = new UnauthorizedResult();
            }
        }
Ejemplo n.º 3
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)
        {
#if (SharedAccessKeyAuth || JwtAuth)
            #error Please provide a valid secret provider, for example Azure Key Vault: https://security.arcus-azure.net/features/secrets/consume-from-key-vault
            services.AddSingleton <ICachedSecretProvider>(serviceProvider => new CachedSecretProvider(secretProvider: null));
#endif
#if CertificateAuth
            var certificateAuthenticationConfig =
                new CertificateAuthenticationConfigBuilder()
                .WithSubject(X509ValidationLocation.Configuration, "CertificateSubject")
                .Build();

            services.AddScoped(serviceProvider => new CertificateAuthenticationValidator(certificateAuthenticationConfig));
#endif
            services.AddControllers(options =>
            {
                options.ReturnHttpNotAcceptable    = true;
                options.RespectBrowserAcceptHeader = true;

                RestrictToJsonContentType(options);
                AddEnumAsStringRepresentation(options);

#if SharedAccessKeyAuth
                #warning Please provide a valid request header name and secret name to the shared access filter
                options.Filters.Add(new SharedAccessKeyAuthenticationFilter(headerName: "YOUR REQUEST HEADER NAME", queryParameterName: null, secretName: "YOUR SECRET NAME"));
#endif
#if CertificateAuth
                options.Filters.Add(new CertificateAuthenticationFilter());
#endif
#if JwtAuth
                AuthorizationPolicy policy =
                    new AuthorizationPolicyBuilder()
                    .RequireRole("Admin")
                    .RequireAuthenticatedUser()
                    .Build();

                options.Filters.Add(new AuthorizeFilter(policy));
#endif
            });

#if JwtAuth
            #error Use previously registered secret provider, for example Azure Key Vault: https://security.arcus-azure.net/features/secrets/consume-from-key-vault
            ISecretProvider secretProvider = null;
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                string key = secretProvider.Get("JwtSigningKey").GetAwaiter().GetResult();

                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey         = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key)),
                    ValidateIssuer           = true,
                    ValidIssuer      = Configuration.GetValue <string>("Jwt:Issuer"),
                    ValidateAudience = true,
                    ValidAudience    = Configuration.GetValue <string>("Jwt:Audience")
                };
            });
#endif

            services.AddHealthChecks();
#if ExcludeCorrelation
#else
            services.AddCorrelation();
#endif

#if ExcludeOpenApi
#else
//[#if DEBUG]
            var openApiInformation = new OpenApiInfo
            {
                Title   = "Arcus.Templates.WebApi",
                Version = "v1"
            };

            services.AddSwaggerGen(swaggerGenerationOptions =>
            {
                swaggerGenerationOptions.SwaggerDoc("v1", openApiInformation);
                swaggerGenerationOptions.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Arcus.Templates.WebApi.Open-Api.xml"));
            });
//[#endif]
#endif
        }