[CORL-1192] Reduced Security Mode (#3027)

* feat: add support for disabling persisted query requirements

* fix: fixed type errors

* fix: rename flag

* fix: fixed logic around validation

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Wyatt Johnson
2020-07-16 19:34:16 +00:00
committed by GitHub
co-authored by kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
parent f26ab60398
commit 4f5c0e285c
3 changed files with 40 additions and 24 deletions
@@ -1,9 +1,13 @@
import { AppOptions } from "coral-server/app";
import { RawQueryNotAuthorized } from "coral-server/errors";
import { getPersistedQuery } from "coral-server/graph/persisted";
import { hasFeatureFlag } from "coral-server/models/tenant";
import { RequestHandler } from "coral-server/types/express";
import { GQLUSER_ROLE } from "coral-server/graph/schema/__generated__/types";
import {
GQLFEATURE_FLAG,
GQLUSER_ROLE,
} from "coral-server/graph/schema/__generated__/types";
type PersistedQueryMiddlewareOptions = Pick<
AppOptions,
@@ -19,33 +23,14 @@ const persistedQueryMiddleware = ({
next
) => {
try {
if (!req.coral) {
throw new Error("coral was not set");
}
// Pull out some useful properties from Coral.
const { tenant } = req.coral;
if (!tenant) {
if (!req.coral || !req.coral.tenant) {
throw new Error("tenant was not set");
}
// Handle the payload if it is a persisted query.
const body = req.method === "GET" ? req.query : req.body;
const persisted = await getPersistedQuery(persistedQueryCache, body);
if (!persisted) {
// Check to see if this is from an ADMIN token which is allowed to run
// un-persisted queries.
if (
persistedQueriesRequired &&
(!req.user || req.user.role !== GQLUSER_ROLE.ADMIN)
) {
throw new RawQueryNotAuthorized(
tenant.id,
body && body.query ? body.query : null,
req.user ? req.user.id : null
);
}
} else {
if (persisted) {
// The query was found for this operation, replace the query with the one
// provided.
body.query = persisted.query;
@@ -53,9 +38,34 @@ const persistedQueryMiddleware = ({
// Associate the persisted query with the request so it can be attached to
// the context.
req.coral.persisted = persisted;
return next();
}
return next();
// If persisted queries are not required, then it's ok that we're not
// submitting a persisted query.
if (!persistedQueriesRequired) {
return next();
}
// If the feature flag for reduced security mode is enabled, then we will
// allow non-persisted queries.
if (
hasFeatureFlag(req.coral.tenant, GQLFEATURE_FLAG.REDUCED_SECURITY_MODE)
) {
return next();
}
// If the user is an administrator, then permit the non-persisted query.
if (req.user?.role === GQLUSER_ROLE.ADMIN) {
return next();
}
throw new RawQueryNotAuthorized(
req.coral.tenant.id,
body.query || null,
req.user?.id || null
);
} catch (err) {
return next(err);
}
@@ -396,6 +396,12 @@ enum FEATURE_FLAG {
modeartion scope to a user.
"""
SITE_MODERATOR
"""
REDUCED_SECURITY_MODE when true will allow unpersisted queries to be executed
in production environments.
"""
REDUCED_SECURITY_MODE
}
# The moderation mode of the site.
+1 -1
View File
@@ -43,7 +43,7 @@ export function hasFeatureFlag(
tenant: Pick<Tenant, "featureFlags">,
flag: GQLFEATURE_FLAG
) {
if (tenant.featureFlags && tenant.featureFlags.includes(flag)) {
if (tenant.featureFlags?.includes(flag)) {
return true;
}