Merge remote-tracking branch 'origin' into improve-service-accounts

This commit is contained in:
Tuan Dang
2023-04-14 14:08:28 +03:00
8 changed files with 60 additions and 42 deletions
+14 -1
View File
@@ -48,4 +48,17 @@ export const getStripeSecretKey = () => infisical.get('STRIPE_SECRET_KEY')!;
export const getStripeWebhookSecret = () => infisical.get('STRIPE_WEBHOOK_SECRET')!; export const getStripeWebhookSecret = () => infisical.get('STRIPE_WEBHOOK_SECRET')!;
export const getTelemetryEnabled = () => infisical.get('TELEMETRY_ENABLED')! !== 'false' && true; export const getTelemetryEnabled = () => infisical.get('TELEMETRY_ENABLED')! !== 'false' && true;
export const getLoopsApiKey = () => infisical.get('LOOPS_API_KEY')!; export const getLoopsApiKey = () => infisical.get('LOOPS_API_KEY')!;
export const getSmtpConfigured = () => infisical.get('SMTP_HOST') == '' || infisical.get('SMTP_HOST') == undefined ? false : true export const getSmtpConfigured = () => infisical.get('SMTP_HOST') == '' || infisical.get('SMTP_HOST') == undefined ? false : true
export const getHttpsEnabled = () => {
if (getNodeEnv() != "production") {
// no https for anything other than prod
return false
}
if (infisical.get('HTTPS_ENABLED') == undefined || infisical.get('HTTPS_ENABLED') == "") {
// default when no value present
return true
}
return infisical.get('HTTPS_ENABLED') === 'true' && true
}
+7 -7
View File
@@ -15,10 +15,10 @@ import { BadRequestError } from '../../utils/errors';
import { EELogService } from '../../ee/services'; import { EELogService } from '../../ee/services';
import { getChannelFromUserAgent } from '../../utils/posthog'; // TODO: move this import { getChannelFromUserAgent } from '../../utils/posthog'; // TODO: move this
import { import {
getNodeEnv,
getJwtRefreshSecret, getJwtRefreshSecret,
getJwtAuthLifetime, getJwtAuthLifetime,
getJwtAuthSecret getJwtAuthSecret,
getHttpsEnabled
} from '../../config'; } from '../../config';
declare module 'jsonwebtoken' { declare module 'jsonwebtoken' {
@@ -126,21 +126,21 @@ export const login2 = async (req: Request, res: Response) => {
httpOnly: true, httpOnly: true,
path: '/', path: '/',
sameSite: 'strict', sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false secure: getHttpsEnabled()
}); });
const loginAction = await EELogService.createAction({ const loginAction = await EELogService.createAction({
name: ACTION_LOGIN, name: ACTION_LOGIN,
userId: user._id userId: user._id
}); });
loginAction && await EELogService.createLog({ loginAction && await EELogService.createLog({
userId: user._id, userId: user._id,
actions: [loginAction], actions: [loginAction],
channel: getChannelFromUserAgent(req.headers['user-agent']), channel: getChannelFromUserAgent(req.headers['user-agent']),
ipAddress: req.ip ipAddress: req.ip
}); });
// return (access) token in response // return (access) token in response
return res.status(200).send({ return res.status(200).send({
token: tokens.token, token: tokens.token,
@@ -182,14 +182,14 @@ export const logout = async (req: Request, res: Response) => {
httpOnly: true, httpOnly: true,
path: '/', path: '/',
sameSite: 'strict', sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false secure: getHttpsEnabled() as boolean
}); });
const logoutAction = await EELogService.createAction({ const logoutAction = await EELogService.createAction({
name: ACTION_LOGOUT, name: ACTION_LOGOUT,
userId: req.user._id userId: req.user._id
}); });
logoutAction && await EELogService.createLog({ logoutAction && await EELogService.createLog({
userId: req.user._id, userId: req.user._id,
actions: [logoutAction], actions: [logoutAction],
+4 -4
View File
@@ -17,9 +17,9 @@ import {
} from '../../variables'; } from '../../variables';
import { getChannelFromUserAgent } from '../../utils/posthog'; // TODO: move this import { getChannelFromUserAgent } from '../../utils/posthog'; // TODO: move this
import { import {
getNodeEnv,
getJwtMfaLifetime, getJwtMfaLifetime,
getJwtMfaSecret getJwtMfaSecret,
getHttpsEnabled
} from '../../config'; } from '../../config';
declare module 'jsonwebtoken' { declare module 'jsonwebtoken' {
@@ -163,7 +163,7 @@ export const login2 = async (req: Request, res: Response) => {
httpOnly: true, httpOnly: true,
path: '/', path: '/',
sameSite: 'strict', sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false secure: getHttpsEnabled()
}); });
// case: user does not have MFA enablgged // case: user does not have MFA enablgged
@@ -302,7 +302,7 @@ export const verifyMfaToken = async (req: Request, res: Response) => {
httpOnly: true, httpOnly: true,
path: '/', path: '/',
sameSite: 'strict', sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false secure: getHttpsEnabled()
}); });
interface VerifyMfaTokenRes { interface VerifyMfaTokenRes {
+23 -23
View File
@@ -8,7 +8,7 @@ import {
import { issueAuthTokens } from '../../helpers/auth'; import { issueAuthTokens } from '../../helpers/auth';
import { INVITED, ACCEPTED } from '../../variables'; import { INVITED, ACCEPTED } from '../../variables';
import request from '../../config/request'; import request from '../../config/request';
import { getNodeEnv, getLoopsApiKey } from '../../config'; import { getLoopsApiKey, getHttpsEnabled } from '../../config';
/** /**
* Complete setting up user by adding their personal and auth information as part of the * Complete setting up user by adding their personal and auth information as part of the
@@ -24,9 +24,9 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
email, email,
firstName, firstName,
lastName, lastName,
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag, protectedKeyTag,
publicKey, publicKey,
encryptedPrivateKey, encryptedPrivateKey,
encryptedPrivateKeyIV, encryptedPrivateKeyIV,
@@ -38,9 +38,9 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
email: string; email: string;
firstName: string; firstName: string;
lastName: string; lastName: string;
protectedKey: string; protectedKey: string;
protectedKeyIV: string; protectedKeyIV: string;
protectedKeyTag: string; protectedKeyTag: string;
publicKey: string; publicKey: string;
encryptedPrivateKey: string; encryptedPrivateKey: string;
encryptedPrivateKeyIV: string; encryptedPrivateKeyIV: string;
@@ -48,11 +48,11 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
salt: string; salt: string;
verifier: string; verifier: string;
organizationName: string; organizationName: string;
} = req.body; } = req.body;
// get user // get user
user = await User.findOne({ email }); user = await User.findOne({ email });
if (!user || (user && user?.publicKey)) { if (!user || (user && user?.publicKey)) {
// case 1: user doesn't exist. // case 1: user doesn't exist.
// case 2: user has already completed account // case 2: user has already completed account
@@ -66,10 +66,10 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
userId: user._id.toString(), userId: user._id.toString(),
firstName, firstName,
lastName, lastName,
encryptionVersion: 2, encryptionVersion: 2,
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag, protectedKeyTag,
publicKey, publicKey,
encryptedPrivateKey, encryptedPrivateKey,
encryptedPrivateKeyIV, encryptedPrivateKeyIV,
@@ -127,7 +127,7 @@ export const completeAccountSignup = async (req: Request, res: Response) => {
httpOnly: true, httpOnly: true,
path: '/', path: '/',
sameSite: 'strict', sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false secure: getHttpsEnabled()
}); });
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
@@ -158,9 +158,9 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
email, email,
firstName, firstName,
lastName, lastName,
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag, protectedKeyTag,
publicKey, publicKey,
encryptedPrivateKey, encryptedPrivateKey,
encryptedPrivateKeyIV, encryptedPrivateKeyIV,
@@ -192,10 +192,10 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
userId: user._id.toString(), userId: user._id.toString(),
firstName, firstName,
lastName, lastName,
encryptionVersion: 2, encryptionVersion: 2,
protectedKey, protectedKey,
protectedKeyIV, protectedKeyIV,
protectedKeyTag, protectedKeyTag,
publicKey, publicKey,
encryptedPrivateKey, encryptedPrivateKey,
encryptedPrivateKeyIV, encryptedPrivateKeyIV,
@@ -232,7 +232,7 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
httpOnly: true, httpOnly: true,
path: '/', path: '/',
sameSite: 'strict', sameSite: 'strict',
secure: getNodeEnv() === 'production' ? true : false secure: getHttpsEnabled()
}); });
} catch (err) { } catch (err) {
Sentry.setUser(null); Sentry.setUser(null);
@@ -241,7 +241,7 @@ export const completeAccountInvite = async (req: Request, res: Response) => {
message: 'Failed to complete account setup' message: 'Failed to complete account setup'
}); });
} }
return res.status(200).send({ return res.status(200).send({
message: 'Successfully set up account', message: 'Successfully set up account',
user, user,
+1 -1
View File
@@ -157,7 +157,7 @@ const getAuthSTDPayload = async ({
}, { }, {
new: true new: true
}) })
.select('+encryptedKey +iv +tag').populate('user'); .select('+encryptedKey +iv +tag').populate('user serviceAccount');
if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' }); if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' });
+9 -5
View File
@@ -8,7 +8,9 @@ import {
} from '../config'; } from '../config';
import { import {
IUser, IUser,
User,
IServiceAccount, IServiceAccount,
ServiceAccount,
IServiceTokenData IServiceTokenData
} from '../models'; } from '../models';
import { import {
@@ -56,7 +58,7 @@ class Telemetry {
}: { }: {
user?: IUser; user?: IUser;
serviceAccount?: IServiceAccount; serviceAccount?: IServiceAccount;
serviceTokenData?: IServiceTokenData; serviceTokenData?: any; // TODO: fix (it's ServiceTokenData with user populated)
}) => { }) => {
let distinctId = ''; let distinctId = '';
@@ -65,11 +67,13 @@ class Telemetry {
} }
if (serviceAccount) { if (serviceAccount) {
distinctId = `sa.${serviceAccount._id}`; distinctId = `sa.${serviceAccount._id.toString()}`;
} }
if (serviceTokenData) { if (serviceTokenData?.user && serviceTokenData?.user instanceof User) {
distinctId = `st.${serviceTokenData._id}`; distinctId = serviceTokenData.user.email;
} else if (serviceTokenData?.serviceAccount && serviceTokenData?.serviceAccount instanceof ServiceAccount) {
distinctId = `sa.${serviceTokenData.serviceAccount._id.toString()}`;
} }
if (distinctId === '') { if (distinctId === '') {
@@ -96,6 +96,7 @@ Resources:
echo "JWT_AUTH_SECRET=${!JWT_AUTH_SECRET}" >> .env echo "JWT_AUTH_SECRET=${!JWT_AUTH_SECRET}" >> .env
echo "JWT_SERVICE_SECRET=${!JWT_SERVICE_SECRET}" >> .env echo "JWT_SERVICE_SECRET=${!JWT_SERVICE_SECRET}" >> .env
echo "MONGO_URL=${!DOCUMENT_DB_CONNECTION_URL}" >> .env echo "MONGO_URL=${!DOCUMENT_DB_CONNECTION_URL}" >> .env
echo "HTTPS_ENABLED=false" >> .env
docker-compose up -d docker-compose up -d
+1 -1
View File
@@ -17,7 +17,7 @@ Self-hosted Infisical allows you to maintain your sensitive information within y
- 1 DocumentDB instance - 1 DocumentDB instance
- Security groups - Security groups
<a href="https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/create/review?templateURL=https://ec2-instance-cloudformation.s3.amazonaws.com/cloudformation.template&stackName=infisical"> <a href="https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/create/review?templateURL=https://ec2-instance-cloudformation.s3.amazonaws.com/infisical-ec2-deployment.template&stackName=infisical">
<img width="200" src="../images/deploy-aws-button.png" /> <img width="200" src="../images/deploy-aws-button.png" />
</a> </a>