-
Notifications
You must be signed in to change notification settings - Fork 47
/
org-rules.ts
210 lines (179 loc) · 7.55 KB
/
org-rules.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* ©️ 2016 - present FlowCrypt a.s. Limitations apply. Contact [email protected] */
'use strict';
import { Str } from './core/common.js';
import { AcctStore } from './platform/store/acct-store.js';
import { KeyAlgo } from './core/crypto/key.js';
type DomainRules$flag = 'NO_PRV_CREATE' | 'NO_PRV_BACKUP' | 'PRV_AUTOIMPORT_OR_AUTOGEN' | 'PASS_PHRASE_QUIET_AUTOGEN' |
'ENFORCE_ATTESTER_SUBMIT' | 'NO_ATTESTER_SUBMIT' | 'NO_KEY_MANAGER_PUB_LOOKUP' | 'USE_LEGACY_ATTESTER_SUBMIT' |
'DEFAULT_REMEMBER_PASS_PHRASE' | 'HIDE_ARMOR_META' | 'FORBID_STORING_PASS_PHRASE';
export type DomainRulesJson = {
flags?: DomainRules$flag[],
custom_keyserver_url?: string,
key_manager_url?: string,
disallow_attester_search_for_domains?: string[],
enforce_keygen_algo?: string,
enforce_keygen_expire_months?: number,
};
/**
* Organisational rules, set domain-wide, and delivered from FlowCrypt Backend
* These either enforce, alter or forbid various behavior to fit customer needs
*/
export class OrgRules {
private static readonly default = { flags: [] };
public static newInstance = async (acctEmail: string): Promise<OrgRules> => {
const email = Str.parseEmail(acctEmail).email;
if (!email) {
throw new Error(`Not a valid email`);
}
const storage = await AcctStore.get(email, ['rules']);
return new OrgRules(storage.rules || OrgRules.default, Str.getDomainFromEmailAddress(acctEmail));
}
protected constructor(
private domainRules: DomainRulesJson,
public domainName: string
) { }
// optional urls
/**
* Internal company SKS-like public key server to trust above Attester
*/
public getCustomSksPubkeyServer = (): string | undefined => {
return this.domainRules.custom_keyserver_url;
}
/**
* an internal org FlowCrypt Email Key Manager instance, can manage both public and private keys
* use this method when using for PRV sync
*/
public getKeyManagerUrlForPrivateKeys = (): string | undefined => {
return this.domainRules.key_manager_url;
}
/**
* an internal org FlowCrypt Email Key Manager instance, can manage both public and private keys
* use this method when using for PUB sync
*/
public getKeyManagerUrlForPublicKeys = (): string | undefined => {
if ((this.domainRules.flags || []).includes('NO_KEY_MANAGER_PUB_LOOKUP')) {
return undefined;
}
return this.domainRules.key_manager_url;
}
/**
* use when finding out if EKM is in use, to change functionality without actually neededing the EKM
*
*/
public usesKeyManager = (): boolean => {
return !!this.domainRules.key_manager_url;
}
// optional vars
/**
* Enforce a key algo for keygen, eg rsa2048,rsa4096,curve25519
*/
public getEnforcedKeygenAlgo = (): KeyAlgo | undefined => {
return this.domainRules.enforce_keygen_algo as KeyAlgo | undefined;
}
/**
* Some orgs want to have newly generated keys include self-signatures that expire some time in the future.
*/
public getEnforcedKeygenExpirationMonths = (): number | undefined => {
return this.domainRules.enforce_keygen_expire_months;
}
// bools
/**
* Some orgs expect 100% of their private keys to be imported from elsewhere (and forbid keygen in the extension)
*/
public canCreateKeys = (): boolean => {
return !(this.domainRules.flags || []).includes('NO_PRV_CREATE');
}
/**
* Some orgs want to forbid backing up of public keys (such as inbox or other methods)
*/
public canBackupKeys = (): boolean => {
return !(this.domainRules.flags || []).includes('NO_PRV_BACKUP');
}
/**
* (normally, during setup, if a public key is submitted to Attester and there is
* a conflicting key already submitted, the issue will be skipped)
* Some orgs want to make sure that their public key gets submitted to attester and conflict errors are NOT ignored:
*/
public mustSubmitToAttester = (): boolean => {
return (this.domainRules.flags || []).includes('ENFORCE_ATTESTER_SUBMIT');
}
/**
* Normally, during setup, "remember pass phrase" is unchecked
* This option will cause "remember pass phrase" option to be checked by default
* This behavior is also enabled as a byproduct of PASS_PHRASE_QUIET_AUTOGEN
*/
public rememberPassPhraseByDefault = (): boolean => {
return (this.domainRules.flags || []).includes('DEFAULT_REMEMBER_PASS_PHRASE') || this.mustAutogenPassPhraseQuietly();
}
public forbidStoringPassPhrase = (): boolean => {
return (this.domainRules.flags || []).includes('FORBID_STORING_PASS_PHRASE');
}
/**
* This is to be used for customers who run their own FlowCrypt Email Key Manager
* If a key can be found on FEKM, it will be auto imported
* If not, it will be autogenerated and stored there
*/
public mustAutoImportOrAutogenPrvWithKeyManager = (): boolean => {
if (!(this.domainRules.flags || []).includes('PRV_AUTOIMPORT_OR_AUTOGEN')) {
return false;
}
if (!this.getKeyManagerUrlForPrivateKeys()) {
throw new Error('Wrong org rules config: using PRV_AUTOIMPORT_OR_AUTOGEN without key_manager_url');
}
return true;
}
/**
* When generating keys, user will not be prompted to choose a pass phrase
* Instead a pass phrase will be automatically generated, and stored locally
* The pass phrase will NOT be displayed to user, and it will never be asked of the user
* This creates the smoothest user experience, for organisations that use full-disk-encryption and don't need pass phrase protection
*/
public mustAutogenPassPhraseQuietly = (): boolean => {
return this.usesKeyManager() && (this.domainRules.flags || []).includes('PASS_PHRASE_QUIET_AUTOGEN');
}
public userMustChoosePassPhraseDuringPrvAutoimport = (): boolean => {
return this.usesKeyManager() && !this.mustAutogenPassPhraseQuietly();
}
/**
* Some orgs prefer to forbid publishing public keys publicly
*/
public canSubmitPubToAttester = (): boolean => {
return !(this.domainRules.flags || []).includes('NO_ATTESTER_SUBMIT');
}
/**
* Some orgs have a list of email domains where they do NOT want such emails to be looked up on public sources (such as Attester)
* This is because they already have other means to obtain public keys for these domains, such as from their own internal keyserver
*/
public canLookupThisRecipientOnAttester = (emailAddr: string): boolean => {
if (this.disallowLookupOnAttester()) {
return false;
}
const disallowedDomains = this.domainRules.disallow_attester_search_for_domains || [];
const userDomain = Str.getDomainFromEmailAddress(emailAddr);
if (!userDomain) {
throw new Error(`Not a valid email ${emailAddr}`);
}
return !disallowedDomains.includes(userDomain);
}
/**
*
* Some orgs might want to disallow lookup on attester completely
*/
public disallowLookupOnAttester = (): boolean => {
return (this.domainRules.disallow_attester_search_for_domains || []).includes('*');
}
/**
* Some orgs use flows that are only implemented in POST /initial/legacy_submit and not in POST /pub/[email protected]:
* -> enforcing that submitted keys match customer key server
* Until the newer endpoint is ready, this flag will point users in those orgs to the original endpoint
*/
public useLegacyAttesterSubmit = (): boolean => {
return (this.domainRules.flags || []).includes('USE_LEGACY_ATTESTER_SUBMIT');
}
/**
* With this option, sent messages won't have any comment/version in armor, imported keys get imported without armor
*/
public shouldHideArmorMeta = (): boolean => {
return (this.domainRules.flags || []).includes('HIDE_ARMOR_META');
}
}