/
Container Registration

Container Registration

Autofac Modules

Autofac modules are used to add registration components to the system. There automatically discovered from the application domain and installed at startup.

Configuration Over Conventions for Autofac Modules

ApiSettings class represents the application configuration, as is registered in the container as a singleton. To access registrations by configuration, the following base module has been created.

#if NETSTANDARD
using Autofac;
using EdFi.Ods.Api.Common.Configuration;
using EdFi.Ods.Common.Extensions;
using System.Linq;
using EdFi.Ods.Api.Common.Constants;
using log4net;

namespace EdFi.Ods.Api.Common.Container
{
    public abstract class ConditionalModule : Module
    {
        private readonly ILog _logger = LogManager.GetLogger(typeof(ConditionalModule));

        protected readonly ApiSettings ApiSettings;
        private readonly string _moduleName;

        protected ConditionalModule(ApiSettings apiSettings, string moduleName)
        {
            ApiSettings = apiSettings;
            _moduleName = moduleName;
        }

        public abstract bool IsSelected();

        public abstract void ApplyConfigurationSpecificRegistrations(ContainerBuilder builder);

        protected override void Load(ContainerBuilder builder)
        {
            if (IsSelected())
            {
                ApplyConfigurationSpecificRegistrations(builder);
            }
            else
            {
                _logger.Debug($"{_moduleName} Module is disabled and will not be installed.");
            }
        }
        protected bool IsFeatureEnabled(ApiFeature feature) => ApiSettings.IsFeatureEnabled(feature.GetConfigKeyName());
    }
}
#endif

Windsor Deprecation from Net Core

Windsor is not supported in net core 3.1 and thus is being phased out. This has caused some issues with the chain of responsibility pattern since the original implementation was using a Castle Facility. The base class ChainOfResponsibilityBase<TService, TRequest, TResponse>

is currently used by Pbkdf2HmacSha1SecureHasher but that component is registered as a regular service.

namespace EdFi.Ods.Api.NetCore.Container.Modules
{
    public class SecureHashingModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<ApiClientAuthenticator>()
                .As<IApiClientAuthenticator>();

            builder.RegisterType<EdFiAdminApiClientIdentityProvider>()
                .As<IApiClientIdentityProvider>()
                .As<IApiClientSecretProvider>()
                .SingleInstance();

            builder.RegisterType<PackedHashConverter>()
                .As<IPackedHashConverter>()
                .SingleInstance();

            builder.RegisterType<SecurePackedHashProvider>()
                .As<ISecurePackedHashProvider>()
                .SingleInstance();

            builder.RegisterType<DefaultHashConfigurationProvider>()
                .As<IHashConfigurationProvider>()
                .SingleInstance();

            builder.RegisterType<Pbkdf2HmacSha1SecureHasher>()
                .As<ISecureHasher>()
                .SingleInstance();
        }
    }
}

The decision to hash or not to hash the secret is defined in the following modules:

using Autofac;
using EdFi.Ods.Api.Common.Configuration;
using EdFi.Ods.Api.Common.Container;
using EdFi.Ods.Common.Security;

namespace EdFi.Ods.Api.NetCore.Container.Modules
{
    public class HashedSecretVerifierModule : ConditionalModule
    {
        public HashedSecretVerifierModule(ApiSettings apiSettings)
            : base(apiSettings, nameof(HashedSecretVerifierModule)) { }

        public override bool IsSelected() => ApiSettings.EncryptSecrets;

        public override void ApplyConfigurationSpecificRegistrations(ContainerBuilder builder)
        {
            builder.RegisterType<SecureHashAwareSecretVerifier>().As<ISecretVerifier>();
            builder.RegisterDecorator<AutoUpgradingHashedSecretVerifierDecorator, ISecretVerifier>();
        }
   

and 

using System;
using Autofac;
using EdFi.Ods.Api.Common.Configuration;
using EdFi.Ods.Api.Common.Container;
using EdFi.Ods.Common.Security;

namespace EdFi.Ods.Api.NetCore.Container.Modules
{
    public class PlainTextSecretVerifierModule : ConditionalModule
    {
        public PlainTextSecretVerifierModule(ApiSettings apiSettings)
            : base(apiSettings, nameof(PlainTextSecretVerifierModule)) { }

        public override bool IsSelected() => !ApiSettings.EncryptSecrets;

        public override void ApplyConfigurationSpecificRegistrations(ContainerBuilder builder)
        {
            builder.RegisterType<PlainTextSecretVerifier>().As<ISecretVerifier>();
        }
    }
}


Related content

EdFi.Ods.WebApi.Netcore
EdFi.Ods.WebApi.Netcore
More like this
Platform Dev. Guide - Configuration
Platform Dev. Guide - Configuration
More like this
Platform Dev. Guide - Configuration
Platform Dev. Guide - Configuration
More like this
Platform Dev. Guide - Configuration
Platform Dev. Guide - Configuration
More like this
Adding Custom ODS / API Features
Adding Custom ODS / API Features
More like this
Adding Custom ODS / API Features
Adding Custom ODS / API Features
More like this