Prechádzať zdrojové kódy

Soc2 front end (#4060)

Co-authored-by: Jose Diaz-Gonzalez <jose@porter.run>
sdess09 2 rokov pred
rodič
commit
4b04570b5c

+ 15 - 0
dashboard/src/assets/pending.svg

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg fill="#d2a217" width="800px" height="800px" viewBox="0 0 32 32" id="icon" xmlns="http://www.w3.org/2000/svg">
+  <defs>
+    <style>
+      .cls-1 {
+        fill: none;
+      }
+    </style>
+  </defs>
+  <circle cx="9" cy="16" r="2"/>
+  <circle cx="23" cy="16" r="2"/>
+  <circle cx="16" cy="16" r="2"/>
+  <path d="M16,30A14,14,0,1,1,30,16,14.0158,14.0158,0,0,1,16,30ZM16,4A12,12,0,1,0,28,16,12.0137,12.0137,0,0,0,16,4Z" transform="translate(0 0)"/>
+  <rect id="_Transparent_Rectangle_" data-name="&lt;Transparent Rectangle&gt;" class="cls-1" width="32" height="32"/>
+</svg>

+ 279 - 0
dashboard/src/components/SOC2Checks.tsx

@@ -0,0 +1,279 @@
+import React, { useContext, useEffect, useMemo, useState } from "react";
+import styled from "styled-components";
+import { type RouteComponentProps, withRouter } from "react-router";
+import Spacer from "./porter/Spacer";
+import Step from "./porter/Step";
+import Link from "./porter/Link";
+import Text from "./porter/Text";
+import Error from "./porter/Error";
+import healthy from "assets/status-healthy.png";
+import failure from "assets/failure.svg";
+import Loading from "./Loading";
+import ToggleRow from "./porter/ToggleRow";
+import Container from "components/porter/Container";
+import external_link from "assets/external-link.svg";
+import pending from "assets/pending.svg";
+import Fieldset from "./porter/Fieldset";
+import { Context } from "shared/Context";
+//import DonutChart from "./DonutChart";
+// import DonutChart from "components/porter/DonutChart";
+
+type Props = RouteComponentProps & {
+  soc2Data: any
+  error?: string;
+  enableAll: boolean;
+  setSoc2Data: (x: any) => void;
+  readOnly: boolean;
+
+};
+type ItemProps = RouteComponentProps & {
+  checkKey: string
+  checkLabel?: string
+};
+
+
+const SOC2Checks: React.FC<Props> = ({ soc2Data, enableAll, setSoc2Data, readOnly }) => {
+
+  // const { soc2Data, setSoc2Data } = useContext(Context);
+  const soc2Checks = soc2Data?.soc2_checks || {};
+
+  const combinedKeys = new Set([
+    ...Object.keys(soc2Checks)
+  ]);
+
+  useEffect(() => {
+
+    if (enableAll) {
+      const newSOC2Checks = Object.keys(soc2Checks).reduce((acc, key) => {
+        acc[key] = {
+          ...soc2Checks[key],
+          status: soc2Checks[key].enabled ? (soc2Checks[key].status === "PENDING" ? "PENDING" : "ENABLED") : "PENDING",
+        }
+        return acc;
+      }, {});
+      setSoc2Data(prev => ({
+        ...prev,
+        soc2_checks: newSOC2Checks
+      }));
+    }
+    else {
+      const newSOC2Checks = Object.keys(soc2Checks).reduce((acc, key) => {
+        acc[key] = {
+          ...soc2Checks[key],
+          status: !soc2Checks[key].enabled ? "" : (soc2Checks[key].status === "PENDING" ? "PENDING" : "ENABLED"),
+        }
+        return acc;
+      }, {});
+      setSoc2Data(prev => ({
+        ...prev,
+        soc2_checks: newSOC2Checks
+      }));
+    }
+  }, [enableAll]);
+
+  const Soc2Item: React.FC<ItemProps> = ({ checkKey, checkLabel }) => {
+    const checkData = soc2Data?.soc2_checks?.[checkKey];
+    const hasMessage = checkData?.message;
+    const enabled = checkData?.enabled;
+    const status = checkData?.status;
+
+    const [isExpanded, setIsExpanded] = useState(true);
+
+    const handleToggle = (): void => {
+      if (hasMessage && enabled) {
+        setIsExpanded(!isExpanded);
+      }
+    };
+
+    const handleEnable = (): void => {
+      setSoc2Data(prev => ({
+        ...prev,
+        soc2_checks: {
+          ...prev.soc2_checks,
+          [checkKey]: {
+            ...prev.soc2_checks[checkKey],
+            enabled: !prev.soc2_checks[checkKey].enabled,
+            status: !prev.soc2_checks[checkKey].enabled ? "PENDING" : !prev.soc2_checks[checkKey].enabled ? "ENABLED" : "",
+          }
+        }
+      }));
+    };
+
+    return (
+      <CheckItemContainer hasMessage={hasMessage} > {/* Pass isExpanded as a prop */}
+        < CheckItemTop onClick={handleToggle} >
+          {status === "LOADING" &&
+            <Loading
+              offset="0px"
+              width="20px"
+              height="20px" />
+          }
+          {status === "PENDING" &&
+            <StatusIcon src={pending} />
+          }
+          {status === "ENABLED" &&
+            <StatusIcon src={healthy} />
+          }
+          {status === "" &&
+            <StatusIcon height="10px" src={failure} />
+          }
+          <Spacer inline x={1} />
+          <Text style={{ marginLeft: '10px', flex: 1 }}>{checkLabel}</Text>
+          {
+            enabled && <ExpandIcon className="material-icons" isExpanded={isExpanded}>
+              arrow_drop_down
+            </ExpandIcon>
+          }
+        </CheckItemTop >
+        {
+          isExpanded && hasMessage && (
+            <div style={{ marginLeft: '10px' }}>
+              <Spacer y={.5} />
+              <Text>
+                {checkData?.message}
+              </Text>
+              <Spacer y={.5} />
+              {checkData?.metadata &&
+                Object.entries(checkData.metadata).map(([key, value]) => (
+                  <>
+                    <div key={key}>
+                      <ErrorMessageLabel>{key}:</ErrorMessageLabel>
+                      <ErrorMessageContent>{value}</ErrorMessageContent>
+                    </div>
+                  </>
+                ))}
+              <Spacer y={.5} />
+
+              {!checkData?.hideToggle &&
+                <>
+                  <Container row spaced style={{ marginRight: '10px' }}>
+                    <ToggleRow
+                      isToggled={enabled || enableAll}
+                      onToggle={() => {
+                        handleEnable();
+                      }}
+                      disabled={readOnly || enableAll || (enabled && checkData?.locked && status !== "PENDING")}
+                      disabledTooltip={readOnly ? ("Wait for provisioning to complete before editing this field.") : (enableAll ? "Global SOC 2 setting must be disabled to toggle this" : checkData?.disabledTooltip)}
+                    >
+                      <Container row>
+                        <Text>{checkData.enabledField}</Text>
+                        <Spacer inline x={1} />
+                        <Text color="helper">{checkData.info}</Text>
+                      </Container>
+                    </ToggleRow>
+
+
+                    {
+                      checkData.link &&
+                      <Link
+                        onClick={() => {
+                          window.open(checkData.link, "_blank");
+                        }}
+                      >
+                        <TagIcon src={external_link} />
+                        More Info
+                      </Link>
+                    }
+                  </Container>
+                  <Spacer y={.5} />
+                </>
+              }
+            </div>
+          )
+        }
+      </CheckItemContainer >
+    );
+  };
+  return (
+
+    <><Spacer y={1} />
+      <>
+        {/* <Fieldset>
+        <DonutChart soc2Data={soc2Data} />
+      </Fieldset> */}
+        <Spacer y={1} />
+        <AppearingDiv>
+          {Array.from(combinedKeys).map((checkKey) => (
+            <Soc2Item
+              key={checkKey}
+              checkKey={checkKey}
+              checkLabel={checkKey} />
+          ))}
+        </AppearingDiv></></>
+
+  )
+};
+
+
+
+export default withRouter(SOC2Checks);
+
+
+const AppearingDiv = styled.div<{ color?: string }>`
+  animation: floatIn 0.5s;
+  animation-fill-mode: forwards;
+  display: flex;
+  flex-direction: column; 
+  color: ${(props) => props.color || "#ffffff44"};
+ 
+  @keyframes floatIn {
+    from {
+      opacity: 0;
+      transform: translateY(20px);
+    }
+    to {
+      opacity: 1;
+      transform: translateY(0px);
+    }
+  }
+`;
+const StatusIcon = styled.img`
+height: ${props => props.height ? props.height : '14px'};
+`;
+
+const CheckItemContainer = styled.div`
+  display: flex;
+  flex-direction: column;
+  border: ${props => props.isExpanded ? '2px solid #3a48ca' : '1px solid ' + props.theme.border}; // Thicker and blue border if expanded
+  border-radius: 5px;
+  font-size: 13px;
+  width: 100%;
+  margin-bottom: 10px;
+  padding-left: 10px;
+  cursor: ${props => (props.hasMessage ? 'pointer' : 'default')};
+  background: ${props => props.theme.clickable.bg};
+`;
+
+
+
+const CheckItemTop = styled.div`
+  display: flex;
+  align-items: center;
+  padding: 10px;
+  background: ${props => props.theme.clickable.bg};
+`;
+
+const ExpandIcon = styled.i<{ isExpanded: boolean }>`
+  margin-left: 8px;
+  color: #ffffff66;
+  font-size: 20px;
+  cursor: pointer;
+  border-radius: 20px;
+  transform: ${props => props.isExpanded ? "" : "rotate(-90deg)"};
+`;
+const ErrorMessageLabel = styled.span`
+  font-weight: bold;
+  margin-left: 10px;
+`;
+const ErrorMessageContent = styled.div`
+  font-family: 'Courier New', Courier, monospace;
+  padding: 5px 10px;
+  border-radius: 4px;
+  margin-left: 10px;
+  user-select: text;
+  cursor: text
+`;
+const TagIcon = styled.img`
+  height: 12px;
+  margin-right: 3px;
+`;

+ 118 - 129
dashboard/src/main/home/cluster-dashboard/dashboard/Compliance.tsx

@@ -1,7 +1,7 @@
-import React, { useContext, useEffect, useMemo, useState } from "react";
 import type { JsonValue } from "@bufbuild/protobuf";
 import { Cluster, Contract, EKS, EKSLogging } from "@porter-dev/api-contracts";
 import axios from "axios";
+import React, { useContext, useEffect, useMemo, useState } from "react";
 import styled from "styled-components";
 import { match } from "ts-pattern";
 
@@ -13,9 +13,10 @@ import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
 import ToggleRow from "components/porter/ToggleRow";
 
-import api from "shared/api";
-import { Context } from "shared/Context";
 import sparkle from "assets/sparkle.svg";
+import SOC2Checks from "components/SOC2Checks";
+import { Context } from "shared/Context";
+import api from "shared/api";
 
 type Props = {
   credentialId: string;
@@ -23,6 +24,51 @@ type Props = {
   selectedClusterVersion: JsonValue;
 };
 
+
+//  Example SOC2 Check NOTE PLEASE ADD FUNC TO createContract and useEffect(() to correctly READ AND WRITE 
+//  "Display_Name_Of_SOC2_Check": {
+//   "message": "Main Example Message about the Check",
+//   "link": "example link for more docs ",
+//   "enabled": (false or true if porter does it by default),
+//   "status": ""(Keep blank or ENABLED if porter does it by default)
+//  "enabledField": "text that goes next to the toggle",
+//   "info": " more information",
+//   "locked":(true if unmutable field like KMS),
+//   "disabledTooltip": "display if message is disabled",
+//  "hideToggle": true (if you want to hide the toggle
+//}
+const soc2DataDefault = {
+  "soc2_checks": {
+    "Public SSH Access": {
+      "message": "Porter-provisioned instances do not allow remote SSH access. Users are not allowed to invoke commands directly on the host, and all commands are invoked via the EKS Control Plane.",
+      "enabled": true,
+      "hideToggle": true,
+      "status": "ENABLED"
+    },
+    "Cluster Secret Encryption": {
+      "message": "Cluster secrets can be encrypted using an AWS KMS Key. Secrets will be encrypted at rest, and encryption cannot be disabled for secrets.",
+      "enabled": false,
+      "disabledTooltip": "Enable KMS encryption for the cluster to enable SOC 2 compliance.",
+      "link": "https://aws.amazon.com/about-aws/whats-new/2020/03/amazon-eks-adds-envelope-encryption-for-secrets-with-aws-kms/",
+      "locked": true,
+      "status": "",
+    },
+    "Control Plane Log Retention": {
+      "message": "EKS Control Plane logs are by default available for a minimal amount of time, typically 1 hour or less. EKS CloudTrail Forwarding automatically sends control plane logs to CloudTrail for longer retention and later inspection.",
+      "enabled": false,
+      "enabledField": "Retain CloudTrail logs for 365 days",
+      "status": "",
+    },
+    "Enhanced Image Vulnerability Scanning": {
+      "message": "AWS ECR scans for CVEs from the open-source Clair database on push image push. Enhanced scanning provides continuous, automated scans against images as new vulnerabilities appear.",
+      "link": "https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning-enhanced.html",
+      "enabled": false,
+      "info": "",
+      "status": ""
+    }
+  }
+}
+
 const DEFAULT_ERROR_MESSAGE =
   "An error occurred while provisioning your infrastructure. Please try again.";
 
@@ -30,17 +76,14 @@ const Compliance: React.FC<Props> = (props) => {
   const { currentProject, currentCluster, setShouldRefreshClusters } =
     useContext(Context);
 
-  const [cloudTrailEnabled, setCloudTrailEnabled] = useState(false);
-  // const [cloudTrailRetention, setCloudTrailRetention] = useState(false);
-  const [ecrScanningEnabled, setEcrScanningEnabled] = useState(false);
-  const [isReadOnly, setIsReadOnly] = useState(false);
   const [isClicked, setIsClicked] = useState(false);
   const [isLoading, setIsLoading] = useState(false);
-  const [kmsEnabled, setKmsEnabled] = useState(false);
   const [soc2Enabled, setSoc2Enabled] = useState(false);
   const [clusterRegion, setClusterRegion] = useState("");
   const [errorMessage, setErrorMessage] = useState<string>("");
   const [errorDetails, setErrorDetails] = useState<string>("");
+  const [soc2Data, setSoc2Data] = useState(soc2DataDefault);
+  const [isReadOnly, setIsReadOnly] = useState(false);
 
   const applySettings = async (): Promise<void> => {
     if (!currentCluster || !currentProject || !setShouldRefreshClusters) {
@@ -102,6 +145,11 @@ const Compliance: React.FC<Props> = (props) => {
   };
 
   const createContract = (base64Contract: string): Contract => {
+    //
+    const cloudTrailEnabled = soc2Data.soc2_checks["Control Plane Log Retention"].enabled
+    const kmsEnabled = soc2Data.soc2_checks["Cluster Secret Encryption"].enabled
+    const ecrScanningEnabled = soc2Data.soc2_checks["Control Plane Log Retention"].enabled
+
     const contractData = JSON.parse(atob(base64Contract));
     const latestCluster: Cluster = Cluster.fromJson(contractData.cluster, {
       ignoreUnknownFields: true,
@@ -202,13 +250,24 @@ const Compliance: React.FC<Props> = (props) => {
           project_id: currentProject ? currentProject.id : 0,
         }
       );
-    } catch (err) {}
+    } catch (err) { }
   };
 
   const isUserProvisioning = useMemo(() => {
     return isReadOnly && props.provisionerError === "";
   }, [isReadOnly, props.provisionerError]);
 
+  const determineStatus = (enabled: boolean): string => {
+    if (enabled) {
+      if (currentCluster?.status === "UPDATING") {
+        return "PENDING"
+      }
+      else
+        return "ENABLED"
+    }
+    return ""
+  }
+
   useEffect(() => {
     const contract: Contract = Contract.fromJson(props.selectedClusterVersion, {
       ignoreUnknownFields: true,
@@ -223,15 +282,36 @@ const Compliance: React.FC<Props> = (props) => {
         eksValues.logging.enableAuthenticatorLogs &&
         eksValues.logging.enableControllerManagerLogs;
 
-      setCloudTrailEnabled(cloudTrailEnabled);
       setClusterRegion(eksValues.region);
-      setEcrScanningEnabled(eksValues.enableEcrScanning);
-      setKmsEnabled(eksValues.enableKmsEncryption);
+
+      setSoc2Data(prevSoc2Data => {
+        return {
+          ...prevSoc2Data,
+          soc2_checks: {
+            ...prevSoc2Data.soc2_checks,
+            "Control Plane Log Retention": {
+              ...prevSoc2Data.soc2_checks["Control Plane Log Retention"],
+              enabled: cloudTrailEnabled,
+              status: determineStatus(cloudTrailEnabled)
+            },
+            "Cluster Secret Encryption": {
+              ...prevSoc2Data.soc2_checks["Cluster Secret Encryption"],
+              enabled: eksValues.enableKmsEncryption,
+              status: determineStatus(eksValues.enableKmsEncryption)
+            },
+            "Enhanced Image Vulnerability Scanning": {
+              ...prevSoc2Data.soc2_checks["Enhanced Image Vulnerability Scanning"],
+              enabled: eksValues.enableEcrScanning,
+              status: determineStatus(eksValues.enableEcrScanning)
+            }
+          }
+        };
+      });
 
       setSoc2Enabled(
         cloudTrailEnabled &&
-          eksValues.enableKmsEncryption &&
-          eksValues.enableEcrScanning
+        eksValues.enableKmsEncryption &&
+        eksValues.enableEcrScanning
       );
     }
   }, [props.selectedClusterVersion]);
@@ -243,18 +323,10 @@ const Compliance: React.FC<Props> = (props) => {
 
     setIsReadOnly(
       currentCluster.status === "UPDATING" ||
-        currentCluster.status === "UPDATING_UNAVAILABLE"
+      currentCluster.status === "UPDATING_UNAVAILABLE"
     );
   }, []);
 
-  useEffect(() => {
-    if (soc2Enabled) {
-      setCloudTrailEnabled(true);
-      // setCloudTrailRetention(true);
-      setEcrScanningEnabled(true);
-      setKmsEnabled(true);
-    }
-  }, [soc2Enabled]);
   return (
     <StyledCompliance>
       <Spacer y={1} />
@@ -266,115 +338,38 @@ const Compliance: React.FC<Props> = (props) => {
           New
         </NewBadge>
       </Container>
-      <Spacer y={0.5} />
-      <Text color="helper">
-        Configure your AWS infrastructure to be SOC 2 compliant with Porter.
-      </Text>
-      <Spacer y={0.5} />
-      <ToggleRow
-        isToggled={soc2Enabled}
-        onToggle={() => {
-          setSoc2Enabled((prev) => !prev);
-        }}
-        disabled={isReadOnly}
-        disabledTooltip={
-          "Wait for provisioning to complete before editing this field."
-        }
-      >
-        <Container row>
-          <Text>Enable all SOC 2 settings</Text>
-        </Container>
-      </ToggleRow>
-      <Spacer y={0.5} />
-      <GutterContainer>
-        <ToggleRow
-          isToggled={cloudTrailEnabled}
-          onToggle={() => {
-            setCloudTrailEnabled((prev) => !prev);
-          }}
-          disabled={soc2Enabled || isReadOnly}
-          disabledTooltip={
-            soc2Enabled
-              ? "Global SOC 2 setting must be disabled to toggle this"
-              : "Wait for provisioning to complete before editing this field."
-          }
-        >
-          <Container row>
-            <Text>EKS CloudTrail Forwarding</Text>
-            <Spacer inline x={1} />
-            <Text color="helper">
-              Forward all application and control plane logs to CloudTrail.
-            </Text>
-          </Container>
-        </ToggleRow>
-        {/* <Spacer y={0.5} />
-        <ToggleRow
-          isToggled={cloudTrailRetention}
-          onToggle={() => { setCloudTrailRetention((prev) => !prev) }}
-          disabled={soc2Enabled || isReadOnly}
-          disabledTooltip={
-            soc2Enabled ? "Global SOC 2 setting must be disabled to toggle this" : "Wait for provisioning to complete before editing this field."
-          }
-        >
-          <Container row>
-            <Text>Retain CloudTrail logs for 365 days</Text>
-            <Spacer inline x={1} />
-            <Text color="helper">Store CloudTrail logs in an S3 bucket for 365 days.</Text>
-          </Container>
-        </ToggleRow> */}
-        <Spacer y={0.5} />
-        <ToggleRow
-          isToggled={kmsEnabled}
-          onToggle={() => {
-            setKmsEnabled((prev) => !prev);
-          }}
-          disabled={soc2Enabled || isReadOnly || kmsEnabled}
-          disabledTooltip={
-            kmsEnabled
-              ? "KMS encryption can never be disabled."
-              : soc2Enabled
-              ? "Global SOC 2 setting must be disabled to toggle this"
-              : "Wait for provisioning to complete before editing this field."
-          }
+
+      <SOC2Checks
+        enableAll={soc2Enabled}
+        soc2Data={soc2Data}
+        setSoc2Data={setSoc2Data}
+        readOnly={isReadOnly}
+      />
+      <Spacer y={1} />
+      <Container row >
+        <Button
+          disabled={isDisabled() ?? isLoading}
+          onClick={applySettings}
+          status={getStatus()}
         >
-          <Container row>
-            <Text>AWS KMS Secret Encryption</Text>
-            <Spacer inline x={1} />
-            <Text color="helper">
-              Encrypt secrets with AWS Key Management Service.
-            </Text>
-          </Container>
-        </ToggleRow>
-        <Spacer y={0.5} />
+          Save settings
+        </Button>
+        <Spacer inline x={1} />
         <ToggleRow
-          isToggled={ecrScanningEnabled}
+          isToggled={soc2Enabled}
           onToggle={() => {
-            setEcrScanningEnabled((prev) => !prev);
+            setSoc2Enabled((prev) => !prev);
           }}
-          disabled={soc2Enabled || isReadOnly}
+          disabled={isReadOnly}
           disabledTooltip={
-            soc2Enabled
-              ? "Global SOC 2 setting must be disabled to toggle this"
-              : "Wait for provisioning to complete before editing this field."
+            "Wait for provisioning to complete before editing this field."
           }
         >
           <Container row>
-            <Text>Enhanced ECR scanning</Text>
-            <Spacer inline x={1} />
-            <Text color="helper">
-              Scan ECR image repositories for vulnerabilities.
-            </Text>
+            <Text>Enable All</Text>
           </Container>
         </ToggleRow>
-      </GutterContainer>
-      <Spacer y={1} />
-      <Button
-        disabled={isDisabled() ?? isLoading}
-        onClick={applySettings}
-        status={getStatus()}
-      >
-        Save settings
-      </Button>
+      </Container>
     </StyledCompliance>
   );
 };
@@ -383,12 +378,6 @@ export default Compliance;
 
 const StyledCompliance = styled.div``;
 
-const GutterContainer = styled.div`
-  border-left: 1px solid #313237;
-  margin-left: 5px;
-  padding-left: 15px;
-`;
-
 const NewBadge = styled.div`
   font-size: 13px;
   padding: 5px 10px;
@@ -401,4 +390,4 @@ const NewBadge = styled.div`
     height: 14px;
     margin-right: 5px;
   }
-`;
+`;

+ 37 - 1
dashboard/src/shared/Context.tsx

@@ -69,6 +69,8 @@ export interface GlobalContextType {
   setShouldRefreshClusters: (shouldRefreshClusters: boolean) => void;
   featurePreview: boolean;
   setFeaturePreview: (featurePreview: boolean) => void;
+  soc2Data: any;
+  setSoc2Data: (x: any) => void;
 }
 
 /**
@@ -220,6 +222,40 @@ class ContextProvider extends Component<PropsType, StateType> {
     setFeaturePreview: (featurePreview) => {
       this.setState({ featurePreview });
     },
+    soc2Data: {
+      "preflight_checks": {
+        "Public SSH Access": {
+          "message": "Porter-provisioned instances do not allow remote SSH access. Users are not allowed to invoke commands directly on the host, and all commands are invoked via the EKS Control Plane.",
+          "enabled": true,
+          "hideToggle": true,
+          "status": "ENABLED"
+        },
+        "Cluster Secret Encryption": {
+          "message": "Cluster secrets can be encrypted using an AWS KMS Key. Secrets will be encrypted at rest, and encryption cannot be disabled for secrets.",
+          "enabled": false,
+          "disabledTooltip": "Enable KMS encryption for the cluster to enable SOC 2 compliance.",
+          "link": "https://aws.amazon.com/about-aws/whats-new/2020/03/amazon-eks-adds-envelope-encryption-for-secrets-with-aws-kms/",
+          "locked": true,
+          "status": "",
+        },
+        "Control Plane Log Retention": {
+          "message": "EKS Control Plane logs are by default available for a minimal amount of time, typically 1 hour or less. EKS CloudTrail Forwarding automatically sends control plane logs to CloudTrail for longer retention and later inspection.",
+          "enabled": false,
+          "enabledField": "Retain CloudTrail logs for 365 days",
+          "status": "",
+        },
+        "Enhanced Image Vulnerability Scanning": {
+          "message": "AWS ECR scans for CVEs from the open-source Clair database on push image push. Enhanced scanning provides continuous, automated scans against images as new vulnerabilities appear.",
+          "link": "https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning-enhanced.html",
+          "enabled": false,
+          "info": "",
+          "status": ""
+        },
+      }
+    },
+    setSoc2Data: (soc2Data) => {
+      localStorage.setItem("soc2Data", JSON.stringify(soc2Data));
+    }
   };
 
   render() {
@@ -227,4 +263,4 @@ class ContextProvider extends Component<PropsType, StateType> {
   }
 }
 
-export { Context, ContextProvider, ContextConsumer };
+export { Context, ContextConsumer, ContextProvider };

+ 2 - 0
dashboard/src/shared/types.tsx

@@ -410,6 +410,8 @@ export type ContextProps = {
   setEnableGitlab: (enableGitlab: boolean) => void;
   shouldRefreshClusters: boolean;
   setShouldRefreshClusters: (shouldRefreshClusters: boolean) => void;
+  soc2Data: any;
+  setSoc2Data: (x: any) => void;
 };
 
 export enum JobStatusType {