Skip to content

Commit

Permalink
feat: register e2ei root cert before the first enrollment (#16557)
Browse files Browse the repository at this point in the history
* feat: register e2ei root cert before the first enrollment

* test: add method to core mocks

* test: add check if register server certs method was called after init

* chore: bump core
  • Loading branch information
PatrykBuniX authored Jan 19, 2024
1 parent eb572d2 commit 5628abb
Show file tree
Hide file tree
Showing 8 changed files with 29 additions and 25 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"@peculiar/x509": "1.9.6",
"@wireapp/avs": "9.6.9",
"@wireapp/commons": "5.2.4",
"@wireapp/core": "43.6.0",
"@wireapp/core": "43.7.1",
"@wireapp/react-ui-kit": "9.12.6",
"@wireapp/store-engine-dexie": "2.1.7",
"@wireapp/webapp-events": "0.20.1",
Expand Down
1 change: 1 addition & 0 deletions src/__mocks__/@wireapp/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class Account extends EventEmitter {
getUsersIdentities: jest.fn(() => new Map()),
getDeviceIdentities: jest.fn(),
getConversationState: jest.fn(),
registerServerCertificates: jest.fn(),
},
mls: {
schedulePeriodicKeyMaterialRenewals: jest.fn(),
Expand Down
31 changes: 16 additions & 15 deletions src/script/E2EIdentity/E2EIdentityEnrollment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,22 @@ describe('E2EIHandler', () => {
});

it('should create instance with valid params', async () => {
const instance = E2EIHandler.getInstance().initialize(params);
const instance = await E2EIHandler.getInstance().initialize(params);
expect(instance).toBeInstanceOf(E2EIHandler);
});

it('should always return the same instance', async () => {
const instance1 = E2EIHandler.getInstance().initialize(params);
const instance2 = E2EIHandler.getInstance().initialize(params);
const instance1 = await E2EIHandler.getInstance().initialize(params);
const instance2 = await E2EIHandler.getInstance().initialize(params);
expect(instance1).toBe(instance2);
});

it('should set currentStep to INITIALIZE after initialize is called', async () => {
const instance = E2EIHandler.getInstance();
instance.initialize(params);
await instance.initialize(params);
void instance.attemptEnrollment();
await wait(1);
expect(container.resolve(Core).service?.e2eIdentity?.registerServerCertificates).toHaveBeenCalled();
expect(instance['currentStep']).toBe(E2EIHandlerStep.INITIALIZED);
});

Expand All @@ -133,7 +134,7 @@ describe('E2EIHandler', () => {

jest.spyOn(container.resolve(Core), 'enrollE2EI').mockResolvedValueOnce(true);

const instance = E2EIHandler.getInstance().initialize(params);
const instance = await E2EIHandler.getInstance().initialize(params);
void instance['enroll']();
await wait(1);
expect(instance['currentStep']).toBe(E2EIHandlerStep.SUCCESS);
Expand All @@ -144,14 +145,14 @@ describe('E2EIHandler', () => {
jest.spyOn(container.resolve(Core), 'enrollE2EI').mockImplementationOnce(jest.fn(() => Promise.reject()));
jest.spyOn(container.resolve(UserState), 'self').mockImplementationOnce(() => user);

const instance = E2EIHandler.getInstance().initialize(params);
const instance = await E2EIHandler.getInstance().initialize(params);
void instance['enroll']();
await wait(1);
expect(instance['currentStep']).toBe(E2EIHandlerStep.ERROR);
});

it('should display user info message when initialized', async () => {
const instance = E2EIHandler.getInstance().initialize(params);
const instance = await E2EIHandler.getInstance().initialize(params);
void instance.attemptEnrollment();
await wait(1);
expect(getModalOptions).toHaveBeenCalledWith(
Expand All @@ -168,7 +169,7 @@ describe('E2EIHandler', () => {
});

it('should display loading message when enroled', async () => {
const handler = E2EIHandler.getInstance().initialize(params);
const handler = await E2EIHandler.getInstance().initialize(params);
void handler['enroll']();
await wait(1);
expect(getModalOptions).toHaveBeenCalledWith(
Expand All @@ -181,7 +182,7 @@ describe('E2EIHandler', () => {
it('should display success message when enrollment is done', async () => {
jest.spyOn(container.resolve(Core), 'enrollE2EI').mockResolvedValueOnce(true);

const handler = E2EIHandler.getInstance().initialize(params);
const handler = await E2EIHandler.getInstance().initialize(params);
handler['showLoadingMessage'] = jest.fn();
void handler['enroll']();
await wait(1);
Expand All @@ -195,7 +196,7 @@ describe('E2EIHandler', () => {
it('should display error message when enrollment fails', async () => {
jest.spyOn(container.resolve(Core), 'enrollE2EI').mockRejectedValueOnce(false);

const handler = E2EIHandler.getInstance().initialize(params);
const handler = await E2EIHandler.getInstance().initialize(params);
handler['showLoadingMessage'] = jest.fn();
void handler['enroll']();
await wait(1);
Expand All @@ -218,7 +219,7 @@ describe('E2EIHandler', () => {
const renewCertificateSpy = jest.spyOn(handler as any, 'renewCertificate');

// Initialize E2EI
handler.initialize(params);
await handler.initialize(params);
void handler.attemptRenewal();
await wait(1);

Expand All @@ -238,7 +239,7 @@ describe('E2EIHandler', () => {
const enrollSpy = jest.spyOn(handler, 'enroll');

// Initialize E2EI
handler.initialize(params);
await handler.initialize(params);
void handler.attemptRenewal();
await wait(1);

Expand Down Expand Up @@ -270,7 +271,7 @@ describe('E2EIHandler', () => {
const renewCertificateSpy = jest.spyOn(handler as any, 'renewCertificate');

// Initialize E2EI
handler.initialize(params);
await handler.initialize(params);
void handler.attemptRenewal();
await wait(1);

Expand All @@ -288,7 +289,7 @@ describe('E2EIHandler', () => {
const startEnrollmentSpy = jest.spyOn(handler as any, 'startEnrollment');

// Initialize E2EI
handler.initialize(params);
await handler.initialize(params);
void handler.attemptEnrollment();
await wait(1);

Expand Down Expand Up @@ -316,7 +317,7 @@ describe('E2EIHandler', () => {
jest.spyOn(handler as any, 'shouldRefresh').mockReturnValue(false);

// Initialize E2EI
handler.initialize(params);
await handler.initialize(params);
void handler.attemptRenewal();
await wait(1);

Expand Down
4 changes: 3 additions & 1 deletion src/script/E2EIdentity/E2EIdentityEnrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class E2EIHandler extends TypedEventEmitter<Events> {
return this.currentStep !== E2EIHandlerStep.UNINITIALIZED;
}

public initialize({discoveryUrl, gracePeriodInSeconds}: E2EIHandlerParams) {
public async initialize({discoveryUrl, gracePeriodInSeconds}: E2EIHandlerParams) {
const gracePeriodInMs = gracePeriodInSeconds * TIME_IN_MILLIS.SECOND;
this.config = {
discoveryUrl,
Expand All @@ -131,6 +131,8 @@ export class E2EIHandler extends TypedEventEmitter<Events> {
onSnoozeExpired: () => this.startEnrollment(ModalType.ENROLL),
}),
};

await this.coreE2EIService.registerServerCertificates(discoveryUrl);
this.currentStep = E2EIHandlerStep.INITIALIZED;
return this;
}
Expand Down
2 changes: 1 addition & 1 deletion src/script/main/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ export class App {
telemetry.timeStep(AppInitTimingsStep.INITIALIZED_CRYPTOGRAPHY);

const {members: teamMembers, features: teamFeatures} = await teamRepository.initTeam(selfUser.teamId);
const e2eiHandler = configureE2EI(this.logger, teamFeatures);
const e2eiHandler = await configureE2EI(this.logger, teamFeatures);
if (e2eiHandler) {
/* We first try to do the initial enrollment (if the user has not yet enrolled)
* We need to enroll before anything else (in particular joining MLS conversations)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function FeatureConfigChangeHandler({teamState}: Props): null {
useEffect(() => {
if (config) {
// initialize feature handlers
configureE2EI(logger, config)?.attemptEnrollment();
void configureE2EI(logger, config)?.then(client => client.attemptEnrollment());
}
}, [config]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {supportsMLS} from 'Util/util';

import {hasE2EIVerificationExpiration, hasMLSDefaultProtocol} from '../../../../../guards/Protocol';

export const configureE2EI = (logger: Logger, config: FeatureList): undefined | E2EIHandler => {
export const configureE2EI = (logger: Logger, config: FeatureList): undefined | Promise<E2EIHandler> => {
const e2eiConfig = config[FEATURE_KEY.MLSE2EID];
const mlsConfig = config[FEATURE_KEY.MLS];
// Check if MLS or MLS E2EIdentity feature is existent
Expand Down
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4874,9 +4874,9 @@ __metadata:
languageName: node
linkType: hard

"@wireapp/core@npm:43.6.0":
version: 43.6.0
resolution: "@wireapp/core@npm:43.6.0"
"@wireapp/core@npm:43.7.1":
version: 43.7.1
resolution: "@wireapp/core@npm:43.7.1"
dependencies:
"@wireapp/api-client": ^26.10.0
"@wireapp/commons": ^5.2.4
Expand All @@ -4896,7 +4896,7 @@ __metadata:
long: ^5.2.0
uuidjs: 4.2.13
zod: 3.22.4
checksum: 3e2333344241b46253faed7f86be71e8bffc38fd5dd3cb1f02f08aeef0c170d8e12f3c49ec8b64194cff30b0f74c78ca993d391cfd4ad41b80d0490c485751a4
checksum: e143f09d5106d98f40bcd1e66b77baac4ea6be1321c3a96e2d541340ba56f704a99b13a30a7d28861d2c5a1e1eaeccadc74f26ed7af8f56e577500cc0413b532
languageName: node
linkType: hard

Expand Down Expand Up @@ -17568,7 +17568,7 @@ __metadata:
"@wireapp/avs": 9.6.9
"@wireapp/commons": 5.2.4
"@wireapp/copy-config": 2.1.14
"@wireapp/core": 43.6.0
"@wireapp/core": 43.7.1
"@wireapp/eslint-config": 3.0.5
"@wireapp/prettier-config": 0.6.3
"@wireapp/react-ui-kit": 9.12.6
Expand Down

0 comments on commit 5628abb

Please sign in to comment.