diff --git a/storage/file/file.go b/storage/file/file.go index 31c1833..ba096aa 100644 --- a/storage/file/file.go +++ b/storage/file/file.go @@ -166,6 +166,14 @@ func (s *FileStorage) StoreAuthenticate(r *mdm.Request, msg *mdm.Authenticate) e return err } } + if err := e.resetNumericFile(TokenUpdateTallyFilename); err != nil { + return err + } + // remove the BootstrapToken when we receive an Authenticate message + // BS tokens are only valid when a new one is escrowed after enrollment. + if err := os.Remove(e.dirPrefix(BootstrapTokenFile)); err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } return e.writeFile(AuthenticateFilename, []byte(msg.Raw)) } @@ -229,9 +237,6 @@ func (s *FileStorage) Disable(r *mdm.Request) error { if err := e.writeFile(DisabledFilename, nil); err != nil { return err } - if err := e.resetNumericFile(TokenUpdateTallyFilename); err != nil { - return err - } } return e.removeSubEnrollments() } diff --git a/storage/mysql/mysql.go b/storage/mysql/mysql.go index 2af0e83..e5c991f 100644 --- a/storage/mysql/mysql.go +++ b/storage/mysql/mysql.go @@ -109,6 +109,8 @@ ON DUPLICATE KEY UPDATE identity_cert = new.identity_cert, serial_number = new.serial_number, + bootstrap_token_b64 = NULL, + bootstrap_token_at = NULL, authenticate = new.authenticate, authenticate_at = CURRENT_TIMESTAMP;`, r.ID, pemCert, nullEmptyString(msg.SerialNumber), msg.Raw, diff --git a/storage/pgsql/postgresql.go b/storage/pgsql/postgresql.go index 9f3c4dc..2c3680a 100644 --- a/storage/pgsql/postgresql.go +++ b/storage/pgsql/postgresql.go @@ -109,6 +109,8 @@ ON CONFLICT ON CONSTRAINT devices_pkey DO UPDATE SET identity_cert = EXCLUDED.identity_cert, serial_number = EXCLUDED.serial_number, + bootstrap_token_b64 = NULL, + bootstrap_token_at = NULL, authenticate = EXCLUDED.authenticate, authenticate_at = CURRENT_TIMESTAMP;`, r.ID, nullEmptyString(string(pemCert)), nullEmptyString(msg.SerialNumber), msg.Raw, diff --git a/test/e2e/bstoken.go b/test/e2e/bstoken.go index 55732ee..ee7e504 100644 --- a/test/e2e/bstoken.go +++ b/test/e2e/bstoken.go @@ -26,7 +26,7 @@ func bstoken(t *testing.T, ctx context.Context, d bstokenDevice) { } if tok != nil { - t.Errorf("token for supposedly new device %s was not nil", d.ID()) + t.Errorf("token for supposedly freshly enrolled device %s was not nil", d.ID()) } input := []byte("hello world") diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index b28765a..acbb8ba 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -2,6 +2,7 @@ package e2e import ( "context" + "fmt" "net/http" "testing" @@ -93,6 +94,18 @@ func TestE2E(t *testing.T, ctx context.Context, store storage.AllStorage) { t.Run("bstoken", func(t *testing.T) { bstoken(t, ctx, d.Enrollment) }) + // re-enroll device + // this is to try and catch any leftover crud that a storage backend didn't + // clean up (like the tally count, BS token, etc.) + err = d.DoEnroll(ctx) + if err != nil { + t.Fatal(fmt.Errorf("re-enrolling device %s: %w", d.ID(), err)) + } + + t.Run("tally-after-reenroll", func(t *testing.T) { tally(t, ctx, d, store, 1) }) + + t.Run("bstoken-after-reenroll", func(t *testing.T) { bstoken(t, ctx, d.Enrollment) }) + err = store.ClearQueue(d.NewMDMRequest(ctx)) if err != nil { t.Fatal() diff --git a/test/enrollment/enrollment.go b/test/enrollment/enrollment.go index 11d7582..841ef7c 100644 --- a/test/enrollment/enrollment.go +++ b/test/enrollment/enrollment.go @@ -191,7 +191,7 @@ func (e *Enrollment) doTokenUpdate(ctx context.Context) error { return HTTPErrors(resp) } -// DoEnroll enrolls this enrollment into MDM. +// DoEnroll enrolls (or re-enrolls) this enrollment into MDM. // Authenticate and TokenUpdate check-in messages are sent via the // transport to the MDM server. func (e *Enrollment) DoEnroll(ctx context.Context) error { @@ -199,7 +199,7 @@ func (e *Enrollment) DoEnroll(ctx context.Context) error { defer e.enrollM.Unlock() if e.enrolled { - return ErrAlreadyEnrolled + e.enrolled = false } // generate Authenticate check-in message