@@ -122,6 +122,18 @@ func NewLoginMFABackend(core *Core, logger hclog.Logger) *LoginMFABackend {
122122}
123123
124124func NewMFABackend (core * Core , logger hclog.Logger , prefix string , schemaFuncs []func () * memdb.TableSchema ) * MFABackend {
125+ db , _ := SetupMFAMemDB (schemaFuncs )
126+ return & MFABackend {
127+ Core : core ,
128+ mfaLock : & sync.RWMutex {},
129+ db : db ,
130+ mfaLogger : logger .Named ("mfa" ),
131+ namespacer : core ,
132+ methodTable : prefix ,
133+ }
134+ }
135+
136+ func SetupMFAMemDB (schemaFuncs []func () * memdb.TableSchema ) (* memdb.MemDB , error ) {
125137 mfaSchemas := & memdb.DBSchema {
126138 Tables : make (map [string ]* memdb.TableSchema ),
127139 }
@@ -134,15 +146,24 @@ func NewMFABackend(core *Core, logger hclog.Logger, prefix string, schemaFuncs [
134146 mfaSchemas .Tables [schema .Name ] = schema
135147 }
136148
137- db , _ := memdb .NewMemDB (mfaSchemas )
138- return & MFABackend {
139- Core : core ,
140- mfaLock : & sync.RWMutex {},
141- db : db ,
142- mfaLogger : logger .Named ("mfa" ),
143- namespacer : core ,
144- methodTable : prefix ,
149+ db , err := memdb .NewMemDB (mfaSchemas )
150+ if err != nil {
151+ return nil , err
145152 }
153+ return db , nil
154+ }
155+
156+ func (b * LoginMFABackend ) ResetLoginMFAMemDB () error {
157+ var err error
158+
159+ db , err := SetupMFAMemDB (loginMFASchemaFuncs ())
160+ if err != nil {
161+ return err
162+ }
163+
164+ b .db = db
165+
166+ return nil
146167}
147168
148169func (i * IdentityStore ) handleMFAMethodListTOTP (ctx context.Context , req * logical.Request , d * framework.FieldData ) (* logical.Response , error ) {
@@ -474,6 +495,103 @@ func (i *IdentityStore) handleLoginMFAAdminDestroyUpdate(ctx context.Context, re
474495 return nil , nil
475496}
476497
498+ // loadMFAMethodConfigs loads MFA method configs for login MFA
499+ func (b * LoginMFABackend ) loadMFAMethodConfigs (ctx context.Context , ns * namespace.Namespace ) error {
500+ b .mfaLogger .Trace ("loading login MFA configurations" )
501+ barrierView , err := b .Core .barrierViewForNamespace (ns .ID )
502+ if err != nil {
503+ return fmt .Errorf ("error getting namespace view, namespaceid %s, error %w" , ns .ID , err )
504+ }
505+ existing , err := barrierView .List (ctx , loginMFAConfigPrefix )
506+ if err != nil {
507+ return fmt .Errorf ("failed to list MFA configurations for namespace path %s and prefix %s: %w" , ns .Path , loginMFAConfigPrefix , err )
508+ }
509+ b .mfaLogger .Trace ("methods collected" , "num_existing" , len (existing ))
510+
511+ for _ , key := range existing {
512+ b .mfaLogger .Trace ("loading method" , "method" , key )
513+
514+ // Read the config from storage
515+ mConfig , err := b .getMFAConfig (ctx , loginMFAConfigPrefix + key , barrierView )
516+ if err != nil {
517+ return err
518+ }
519+
520+ if mConfig == nil {
521+ b .mfaLogger .Trace ("failed to find the config related to a method" , "namespace" , ns .Path , "prefix" , loginMFAConfigPrefix , "method" , key )
522+ continue
523+ }
524+
525+ // Load the config in MemDB
526+ err = b .MemDBUpsertMFAConfig (ctx , mConfig )
527+ if err != nil {
528+ return fmt .Errorf ("failed to load configuration ID %s prefix %s in MemDB: %w" , mConfig .ID , loginMFAConfigPrefix , err )
529+ }
530+ }
531+
532+ b .mfaLogger .Trace ("configurations restored" , "namespace" , ns .Path , "prefix" , loginMFAConfigPrefix )
533+
534+ return nil
535+ }
536+
537+ // loadMFAEnforcementConfigs loads MFA method configs for login MFA
538+ func (b * LoginMFABackend ) loadMFAEnforcementConfigs (ctx context.Context , ns * namespace.Namespace ) ([]* mfa.MFAEnforcementConfig , error ) {
539+ b .mfaLogger .Trace ("loading login MFA enforcement configurations" )
540+ barrierView , err := b .Core .barrierViewForNamespace (ns .ID )
541+ if err != nil {
542+ return nil , fmt .Errorf ("error getting namespace view, namespaceid %s, error %w" , ns .ID , err )
543+ }
544+ existing , err := barrierView .List (ctx , mfaLoginEnforcementPrefix )
545+ if err != nil {
546+ return nil , fmt .Errorf ("failed to list MFA enforcement configurations for namespace %s with prefix %s: %w" , ns .Path , mfaLoginEnforcementPrefix , err )
547+ }
548+ b .mfaLogger .Trace ("enforcements configs collected" , "num_existing" , len (existing ))
549+
550+ eConfigs := make ([]* mfa.MFAEnforcementConfig , 0 )
551+ for _ , key := range existing {
552+ b .mfaLogger .Trace ("loading enforcement" , "config" , key )
553+
554+ // Read the config from storage
555+ mConfig , err := b .getMFALoginEnforcementConfig (ctx , mfaLoginEnforcementPrefix + key , barrierView )
556+ if err != nil {
557+ return nil , err
558+ }
559+
560+ if mConfig == nil {
561+ b .mfaLogger .Trace ("failed to find an enforcement config" , "namespace" , ns .Path , "prefix" , mfaLoginEnforcementPrefix , "config" , key )
562+ continue
563+ }
564+
565+ // Load the config in MemDB
566+ err = b .MemDBUpsertMFALoginEnforcementConfig (ctx , mConfig )
567+ if err != nil {
568+ return nil , fmt .Errorf ("failed to load enforcement configuration ID %s with prefix %s in MemDB: %w" , mConfig .ID , mfaLoginEnforcementPrefix , err )
569+ }
570+
571+ eConfigs = append (eConfigs , mConfig )
572+ }
573+
574+ b .mfaLogger .Trace ("enforcement configurations restored" , "namespace" , ns .Path , "prefix" , mfaLoginEnforcementPrefix )
575+
576+ return eConfigs , nil
577+ }
578+
579+ func (b * LoginMFABackend ) loginMFAMethodExistenceCheck (eConfig * mfa.MFAEnforcementConfig ) error {
580+ var aggErr * multierror.Error
581+ for _ , confID := range eConfig .MFAMethodIDs {
582+ config , memErr := b .MemDBMFAConfigByID (confID )
583+ if memErr != nil {
584+ aggErr = multierror .Append (aggErr , memErr )
585+ return aggErr .ErrorOrNil ()
586+ }
587+ if config == nil {
588+ aggErr = multierror .Append (aggErr , fmt .Errorf ("found an MFA method ID in enforcement config, but failed to find the MFA method config method ID %s" , confID ))
589+ }
590+ }
591+
592+ return aggErr .ErrorOrNil ()
593+ }
594+
477595func (b * LoginMFABackend ) handleMFALoginValidate (ctx context.Context , req * logical.Request , d * framework.FieldData ) (retResp * logical.Response , retErr error ) {
478596 // mfaReqID is the ID of the login request
479597 mfaReqID := d .Get ("mfa_request_id" ).(string )
@@ -551,6 +669,22 @@ func (b *LoginMFABackend) handleMFALoginValidate(ctx context.Context, req *logic
551669 return resp , nil
552670}
553671
672+ func (c * Core ) teardownLoginMFA () error {
673+ if ! c .IsDRSecondary () {
674+ // Clear any cached auth response
675+ c .mfaResponseAuthQueueLock .Lock ()
676+ c .mfaResponseAuthQueue = nil
677+ c .mfaResponseAuthQueueLock .Unlock ()
678+
679+ c .loginMFABackend .usedCodes = nil
680+
681+ if err := c .loginMFABackend .ResetLoginMFAMemDB (); err != nil {
682+ return err
683+ }
684+ }
685+ return nil
686+ }
687+
554688// LoginMFACreateToken creates a token after the login MFA is validated.
555689// It also applies the lease quotas on the original login request path.
556690func (c * Core ) LoginMFACreateToken (ctx context.Context , reqPath string , cachedAuth * logical.Auth ) (* logical.Response , error ) {
@@ -2529,6 +2663,25 @@ func (b *MFABackend) getMFAConfig(ctx context.Context, path string, barrierView
25292663 return & mConfig , nil
25302664}
25312665
2666+ func (b * LoginMFABackend ) getMFALoginEnforcementConfig (ctx context.Context , path string , barrierView * BarrierView ) (* mfa.MFAEnforcementConfig , error ) {
2667+ entry , err := barrierView .Get (ctx , path )
2668+ if err != nil {
2669+ return nil , err
2670+ }
2671+
2672+ if entry == nil {
2673+ return nil , nil
2674+ }
2675+
2676+ var mConfig mfa.MFAEnforcementConfig
2677+ err = proto .Unmarshal (entry .Value , & mConfig )
2678+ if err != nil {
2679+ return nil , err
2680+ }
2681+
2682+ return & mConfig , nil
2683+ }
2684+
25322685func (b * LoginMFABackend ) putMFALoginEnforcementConfig (ctx context.Context , eConfig * mfa.MFAEnforcementConfig ) error {
25332686 entryIndex := mfaLoginEnforcementPrefix + eConfig .ID
25342687 marshaledEntry , err := proto .Marshal (eConfig )
@@ -2547,28 +2700,6 @@ func (b *LoginMFABackend) putMFALoginEnforcementConfig(ctx context.Context, eCon
25472700 })
25482701}
25492702
2550- func (b * LoginMFABackend ) getMFALoginEnforcementConfig (ctx context.Context , key , namespaceId string ) (* mfa.MFAEnforcementConfig , error ) {
2551- barrierView , err := b .Core .barrierViewForNamespace (namespaceId )
2552- if err != nil {
2553- return nil , err
2554- }
2555- entry , err := barrierView .Get (ctx , mfaLoginEnforcementPrefix + key )
2556- if err != nil {
2557- return nil , err
2558- }
2559- if entry == nil {
2560- return nil , nil
2561- }
2562-
2563- var eConfig mfa.MFAEnforcementConfig
2564- err = proto .Unmarshal (entry .Value , & eConfig )
2565- if err != nil {
2566- return nil , err
2567- }
2568-
2569- return & eConfig , nil
2570- }
2571-
25722703var mfaHelp = map [string ][2 ]string {
25732704 "methods-list" : {
25742705 "Lists all the available MFA methods by their name." ,
0 commit comments