Merge pull request #749 from navi-infra/infra-4080-jit-database-access

INFRA-4080 | Harinder | Adding database name field in JIT request from when environment is Prod and resourceType is DB
This commit is contained in:
Harinder Singh
2025-01-15 16:22:04 +05:30
committed by GitHub
6 changed files with 90 additions and 16 deletions

View File

@@ -14,7 +14,12 @@ import { FormikAutocomplete } from '../common/FormikAutocomplete';
import _, { get, set, values } from 'lodash'; import _, { get, set, values } from 'lodash';
import { DropDownListProps, JitRequest } from './structs'; import { DropDownListProps, JitRequest } from './structs';
import { useStyles } from './styles'; import { useStyles } from './styles';
import { submitJustInTimeAccessRequest } from './utils'; import {
isEnvironmentProd,
isResourceTypeAWSCustom,
isResourceTypeDB,
submitJustInTimeAccessRequest,
} from './utils';
import { ReviewsComponent } from './ReviewsComponent'; import { ReviewsComponent } from './ReviewsComponent';
import { RequestsComponent } from './RequestsComponent'; import { RequestsComponent } from './RequestsComponent';
import { import {
@@ -32,6 +37,7 @@ const JustInTimeAccessPage = () => {
vertical: '', vertical: '',
environment: '', environment: '',
resourceType: '', resourceType: '',
resourceId: '',
resourceAction: '', resourceAction: '',
awsResourceType: '', awsResourceType: '',
awsResourceNames: [''], awsResourceNames: [''],
@@ -44,7 +50,9 @@ const JustInTimeAccessPage = () => {
const classes = useStyles(); const classes = useStyles();
let isResourceTypeAWSCustom = false; let isResourceTypeAWSCustomVar = false;
let isResourceTypeDBVar = false;
let isEnvironmentProdVar = false;
let resourceActionList = Array<string>(); let resourceActionList = Array<string>();
let resourceEnvironmentList = Array<string>(); let resourceEnvironmentList = Array<string>();
let resourceVerticalList = Array<string>(); let resourceVerticalList = Array<string>();
@@ -82,21 +90,23 @@ const JustInTimeAccessPage = () => {
const classes = useStyles(); const classes = useStyles();
const { values }: { values: any } = useFormikContext(); const { values }: { values: any } = useFormikContext();
const resourceTypeField = 'resourceType'; const resourceTypeField = 'resourceType';
const environmentField = 'environment';
if (typeof getIn(values, resourceTypeField) !== undefined && values[resourceTypeField] !== '') { if (typeof getIn(values, resourceTypeField) !== undefined && values[resourceTypeField] !== '') {
if (values[resourceTypeField] === 'AWS-CUSTOM') { if (isResourceTypeAWSCustom(values[resourceTypeField])) {
resourceActionList = CUSTOM_RESOURCE_ACTION_LIST_MAP[values['awsResourceType']]; resourceActionList = CUSTOM_RESOURCE_ACTION_LIST_MAP[values['awsResourceType']];
awsCustomResourceTypeList = AWS_CUSTOM_RESOURCE_TYPE; awsCustomResourceTypeList = AWS_CUSTOM_RESOURCE_TYPE;
isResourceTypeAWSCustom = true; isResourceTypeAWSCustomVar = true;
} else { } else {
isResourceTypeAWSCustom = false; isResourceTypeAWSCustomVar = false;
} }
resourceEnvironmentList = resourceEnvironmentList =
values[resourceTypeField] === 'KAFKA' ? KAFKA_ENVIRONMENT_LIST : environmentList; values[resourceTypeField] === 'KAFKA' ? KAFKA_ENVIRONMENT_LIST : environmentList;
resourceVerticalList = resourceVerticalList =
values[resourceTypeField] === 'KAFKA' ? KAFKA_VERTICAL_LIST : verticalList; values[resourceTypeField] === 'KAFKA' ? KAFKA_VERTICAL_LIST : verticalList;
resourceActionList = RESOURCE_ACTION_MAP[values[resourceTypeField]]; resourceActionList = RESOURCE_ACTION_MAP[values[resourceTypeField]];
// } isResourceTypeDBVar = isResourceTypeDB(values[resourceTypeField]);
isEnvironmentProdVar = isEnvironmentProd(values[environmentField]);
} }
return ( return (
@@ -166,7 +176,14 @@ const JustInTimeAccessPage = () => {
list={resourceEnvironmentList} list={resourceEnvironmentList}
style={classes.field} style={classes.field}
/> />
{isResourceTypeAWSCustom ? ( {isResourceTypeDBVar && isEnvironmentProdVar ? (
<FormikTextField
className={classes.field}
label="Database Name"
name="resourceId"
/>
) : null}
{isResourceTypeAWSCustomVar ? (
<DropDownList <DropDownList
label="AWS Resource Type" label="AWS Resource Type"
fieldName="awsResourceType" fieldName="awsResourceType"
@@ -180,7 +197,7 @@ const JustInTimeAccessPage = () => {
list={resourceActionList} list={resourceActionList}
style={classes.field} style={classes.field}
/> />
{isResourceTypeAWSCustom ? ( {isResourceTypeAWSCustomVar ? (
<FormikTextField <FormikTextField
multiline multiline
label="AWS Resource Names" label="AWS Resource Names"

View File

@@ -1,10 +1,19 @@
import * as yup from 'yup'; import * as yup from 'yup';
import { isResourceTypeDB, isEnvironmentProd } from './utils';
export const justInTimeAccessValidationSchema = yup.object({ export const justInTimeAccessValidationSchema = yup.object({
team: yup.string().required('is Required'), team: yup.string().required('is Required'),
vertical: yup.string().required('is Required'), vertical: yup.string().required('is Required'),
environment: yup.string().required('is Required'), environment: yup.string().required('is Required'),
resourceType: yup.string().required('is Required'), resourceType: yup.string().required('is Required'),
resourceId: yup.string().test('is required', 'is Required', (value, context) => {
const resourceType = context.parent.resourceType;
const environment = context.parent.environment;
if (isResourceTypeDB(resourceType) && isEnvironmentProd(environment) && !value) {
return false;
}
return true;
}),
resourceAction: yup.string().required('is Required'), resourceAction: yup.string().required('is Required'),
justification: yup.string().required('is Required'), justification: yup.string().required('is Required'),
grantWindow: yup grantWindow: yup

View File

@@ -50,9 +50,18 @@ export const RequestsComponent = () => {
}, },
{ {
key: 'Requested For', key: 'Requested For',
value: ({ resourceType, awsResourceType, resourceAction, awsResourceNames }: RequestsInfo) => value: ({
environment,
resourceType,
resourceId,
awsResourceType,
resourceAction,
awsResourceNames,
}: RequestsInfo) =>
renderResourceTypeAndAction( renderResourceTypeAndAction(
environment,
resourceType, resourceType,
resourceId,
awsResourceType, awsResourceType,
resourceAction, resourceAction,
awsResourceNames, awsResourceNames,

View File

@@ -54,9 +54,18 @@ export const ReviewsComponent = () => {
}, },
{ {
key: 'Requested For', key: 'Requested For',
value: ({ resourceType, awsResourceType, resourceAction, awsResourceNames }: ReviewsInfo) => value: ({
environment,
resourceType,
resourceId,
awsResourceType,
resourceAction,
awsResourceNames,
}: ReviewsInfo) =>
renderResourceTypeAndAction( renderResourceTypeAndAction(
environment,
resourceType, resourceType,
resourceId,
awsResourceType, awsResourceType,
resourceAction, resourceAction,
awsResourceNames, awsResourceNames,

View File

@@ -10,6 +10,7 @@ export type JitRequest = {
vertical: string; vertical: string;
environment: string; environment: string;
resourceType: string; resourceType: string;
resourceId: string;
resourceAction: string; resourceAction: string;
awsResourceType: string; awsResourceType: string;
awsResourceNames: Array<string>; awsResourceNames: Array<string>;
@@ -24,6 +25,7 @@ export type RequestsInfo = {
vertical: string; vertical: string;
environment: string; environment: string;
resourceType: string; resourceType: string;
resourceId: string;
awsResourceType: string; awsResourceType: string;
awsResourceNames: Array<string>; awsResourceNames: Array<string>;
resourceAction: string; resourceAction: string;
@@ -41,6 +43,7 @@ export type ReviewsInfo = {
vertical: string; vertical: string;
environment: string; environment: string;
resourceType: string; resourceType: string;
resourceId: string;
awsResourceType: string; awsResourceType: string;
awsResourceNames: Array<string>; awsResourceNames: Array<string>;
resourceAction: string; resourceAction: string;

View File

@@ -14,6 +14,17 @@ const delayedReload = () => {
}, RELOAD_INTERVAL); }, RELOAD_INTERVAL);
}; };
enum Environment {
PROD = 'PROD',
DEV = 'DEV',
QA = 'QA',
}
enum ResourceType {
DB = 'DB',
AWS_CUSTOM = 'AWS-CUSTOM',
}
export const renderGrantDuration = ( export const renderGrantDuration = (
grantAt: number, grantAt: number,
grantWindow: number, grantWindow: number,
@@ -27,19 +38,35 @@ export const renderGrantDuration = (
); );
}; };
export const isResourceTypeDB = (resourceType: string): boolean => {
return resourceType === ResourceType.DB;
};
export const isResourceTypeAWSCustom = (resourceType: string): boolean => {
return resourceType === ResourceType.AWS_CUSTOM;
};
export const isEnvironmentProd = (environment: string): boolean => {
return environment === Environment.PROD;
};
export const renderResourceTypeAndAction = ( export const renderResourceTypeAndAction = (
environment: string,
resourceType: string, resourceType: string,
resourceId: string,
awsResourceType: string, awsResourceType: string,
resourceAction: string, resourceAction: string,
awsResourceNames: Array<string>, awsResourceNames: Array<string>,
classes: ClassNameMap, classes: ClassNameMap,
): React.ReactElement => { ): React.ReactElement => {
const message = let message = `${resourceType} - ${resourceAction}`;
resourceType === 'AWS-CUSTOM' if (isResourceTypeAWSCustom(resourceType)) {
? `${resourceType} - ${awsResourceType} with ${resourceAction} on ${awsResourceNames.join( message = `${resourceType} - ${awsResourceType} with ${resourceAction} on ${awsResourceNames.join(
', ', ', ',
)}` )}`;
: `${resourceType} - ${resourceAction}`; } else if (isResourceTypeDB(resourceType) && isEnvironmentProd(environment)) {
message = `${resourceType} - ${resourceAction} on ${resourceId}`;
}
return ( return (
<div className={classes.resourceTypeAndAction}> <div className={classes.resourceTypeAndAction}>