Skip to content

Commit

Permalink
feat: encrypt emails at rest for demo login (#5759)
Browse files Browse the repository at this point in the history
## About the changes
This allows us to encrypt emails at signup for demo users to further
secure our demo instance. Currently, emails are anonymized before
displaying events performed by demo users. But this means that emails
are stored at rest in our DB. By encrypting the emails at login, we're
adding another layer of protection.

This can be enabled with a flag and requires the encryption key and the
initialization vector (IV for short) to be present as environment
variables.
  • Loading branch information
gastonfournier committed Jan 5, 2024
1 parent 27f70cd commit 1724219
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/lib/__snapshots__/create-config.test.ts.snap
Expand Up @@ -85,6 +85,7 @@ exports[`should create default config 1`] = `
"embedProxy": true,
"embedProxyFrontend": true,
"enableLicense": false,
"encryptEmails": false,
"featureSearchAPI": false,
"featureSearchFeedback": false,
"featureSearchFeedbackPosting": false,
Expand Down
11 changes: 9 additions & 2 deletions src/lib/middleware/demo-authentication.ts
Expand Up @@ -6,15 +6,22 @@ import ApiUser from '../types/api-user';
import { ApiTokenType } from '../types/models/api-token';
import { IAuthRequest } from 'lib/server-impl';
import { IApiRequest } from 'lib/routes/unleash-types';
import { encrypt } from '../util';

function demoAuthentication(
app: Application,
basePath: string,
{ userService }: Pick<IUnleashServices, 'userService'>,
{ authentication }: Pick<IUnleashConfig, 'authentication'>,
{
authentication,
flagResolver,
}: Pick<IUnleashConfig, 'authentication' | 'flagResolver'>,
): void {
app.post(`${basePath}/auth/demo/login`, async (req: IAuthRequest, res) => {
const { email } = req.body;
let { email } = req.body;
email = flagResolver.isEnabled('encryptEmails', { email })
? encrypt(email)
: email;
try {
const user = await userService.loginUserWithoutPassword(
email,
Expand Down
5 changes: 5 additions & 0 deletions src/lib/types/experimental.ts
Expand Up @@ -5,6 +5,7 @@ import { getDefaultVariant } from 'unleash-client/lib/variant';
export type IFlagKey =
| 'accessLogs'
| 'anonymiseEventLog'
| 'encryptEmails'
| 'enableLicense'
| 'embedProxy'
| 'embedProxyFrontend'
Expand Down Expand Up @@ -169,6 +170,10 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_NEW_STRATEGY_CONFIGURATION_FEEDBACK,
false,
),
encryptEmails: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_ENCRYPT_EMAILS,
false,
),
edgeBulkMetricsKillSwitch: parseEnvVarBoolean(
process.env.UNLEASH_EXPERIMENTAL_EDGE_BULK_METRICS_KILL_SWITCH,
false,
Expand Down
20 changes: 19 additions & 1 deletion src/lib/util/anonymise.ts
@@ -1,4 +1,22 @@
import { createHash } from 'crypto';
import { createCipheriv, createHash } from 'crypto';

export function encrypt(s?: string): string {
const key = process.env.UNLEASH_ENCRYPTION_KEY;
const iv = process.env.UNLEASH_ENCRYPTION_IV;
if (!s || !key || !iv) {
return s ?? '';
}

const algorithm = 'aes-256-cbc';

const cipher = createCipheriv(
algorithm,
Buffer.from(key, 'hex'),
Buffer.from(iv, 'hex'),
);
const encrypted = cipher.update(s, 'utf8', 'hex') + cipher.final('hex');
return `${encrypted}@unleash.run`;
}

export function anonymise(s?: string): string {
if (!s) {
Expand Down

0 comments on commit 1724219

Please sign in to comment.