Kaynağa Gözat

properly show oneleet checks from the fe (#4272)

ianedwards 2 yıl önce
ebeveyn
işleme
acfed737f5

+ 2 - 0
api/server/handlers/cluster/compliance_checks.go

@@ -63,6 +63,8 @@ func (c *ListComplianceChecksHandler) ServeHTTP(w http.ResponseWriter, r *http.R
 		switch request.Vendor {
 		case compliance.Vendor_Vanta:
 			vendor = porterv1.EnumComplianceVendor_ENUM_COMPLIANCE_VENDOR_VANTA
+		case compliance.Vendor_OneLeet:
+			vendor = porterv1.EnumComplianceVendor_ENUM_COMPLIANCE_VENDOR_ONE_LEET
 		default:
 			err := telemetry.Error(ctx, span, nil, "invalid vendor")
 			c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusBadRequest))

+ 7 - 7
dashboard/package-lock.json

@@ -95,7 +95,7 @@
         "@babel/preset-typescript": "^7.15.0",
         "@ianvs/prettier-plugin-sort-imports": "^4.1.1",
         "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
-        "@porter-dev/api-contracts": "^0.2.98",
+        "@porter-dev/api-contracts": "^0.2.103",
         "@testing-library/jest-dom": "^4.2.4",
         "@testing-library/react": "^9.3.2",
         "@testing-library/user-event": "^7.1.2",
@@ -2754,9 +2754,9 @@
       }
     },
     "node_modules/@porter-dev/api-contracts": {
-      "version": "0.2.98",
-      "resolved": "https://registry.npmjs.org/@porter-dev/api-contracts/-/api-contracts-0.2.98.tgz",
-      "integrity": "sha512-i+8L7Ji/kuwcCTDM3TXh0kpsspLGSygTW1qhP7sK/yq5K8O86K8alucl44I5pVkJB+1pooXCCWS3AeOJNYpfIw==",
+      "version": "0.2.103",
+      "resolved": "https://registry.npmjs.org/@porter-dev/api-contracts/-/api-contracts-0.2.103.tgz",
+      "integrity": "sha512-D8Ky1jBWSi4oLsMIl1DCQSy6QRfxXsrkRuj6eT16YGkwQ1tTwsb9zP2l0mCvYHzZyDb/4l4l57E+IJzxd9uEhw==",
       "dev": true,
       "dependencies": {
         "@bufbuild/protobuf": "^1.1.0"
@@ -20056,9 +20056,9 @@
       "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
     },
     "@porter-dev/api-contracts": {
-      "version": "0.2.98",
-      "resolved": "https://registry.npmjs.org/@porter-dev/api-contracts/-/api-contracts-0.2.98.tgz",
-      "integrity": "sha512-i+8L7Ji/kuwcCTDM3TXh0kpsspLGSygTW1qhP7sK/yq5K8O86K8alucl44I5pVkJB+1pooXCCWS3AeOJNYpfIw==",
+      "version": "0.2.103",
+      "resolved": "https://registry.npmjs.org/@porter-dev/api-contracts/-/api-contracts-0.2.103.tgz",
+      "integrity": "sha512-D8Ky1jBWSi4oLsMIl1DCQSy6QRfxXsrkRuj6eT16YGkwQ1tTwsb9zP2l0mCvYHzZyDb/4l4l57E+IJzxd9uEhw==",
       "dev": true,
       "requires": {
         "@bufbuild/protobuf": "^1.1.0"

+ 1 - 1
dashboard/package.json

@@ -102,7 +102,7 @@
     "@babel/preset-typescript": "^7.15.0",
     "@ianvs/prettier-plugin-sort-imports": "^4.1.1",
     "@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
-    "@porter-dev/api-contracts": "^0.2.98",
+    "@porter-dev/api-contracts": "^0.2.103",
     "@testing-library/jest-dom": "^4.2.4",
     "@testing-library/react": "^9.3.2",
     "@testing-library/user-event": "^7.1.2",

+ 31 - 0
dashboard/src/assets/oneleet.svg

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="131px" height="131px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g><path style="opacity:0.016" fill="#ff433e" d="M 10.5,1.5 C 46.9977,0.335611 83.6644,0.168945 120.5,1C 83.8348,1.49999 47.1682,1.66665 10.5,1.5 Z"/></g>
+<g><path style="opacity:0.016" fill="#fe403f" d="M 8.5,1.5 C 9.83333,2.16667 9.83333,2.16667 8.5,1.5 Z"/></g>
+<g><path style="opacity:0.999" fill="#e74227" d="M 122.5,3.5 C 124.168,5.34004 125.668,7.34004 127,9.5C 127.5,46.8318 127.667,84.1652 127.5,121.5C 126.662,121.842 126.328,122.508 126.5,123.5C 125.833,123.5 125.5,123.833 125.5,124.5C 124.833,124.5 124.5,124.833 124.5,125.5C 123.833,125.5 123.5,125.833 123.5,126.5C 122.508,126.328 121.842,126.662 121.5,127.5C 83.4571,127.821 45.4571,127.488 7.5,126.5C 6.83333,125.167 5.83333,124.167 4.5,123.5C 4.06795,122.29 3.40128,121.29 2.5,120.5C 2.33335,83.8318 2.50001,47.1652 3,10.5C 3.68979,7.80402 5.18979,5.63735 7.5,4C 26.7709,2.85132 46.1042,2.35132 65.5,2.5C 84.5421,2.5122 103.542,2.84553 122.5,3.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 122.5,2.5 C 123.833,3.16667 123.833,3.16667 122.5,2.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 126.5,5.5 C 127.833,6.16667 127.833,6.16667 126.5,5.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 127.5,7.5 C 128.833,8.16667 128.833,8.16667 127.5,7.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 1.5,8.5 C 2.83333,9.16667 2.83333,9.16667 1.5,8.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 128.5,9.5 C 129.525,9.89657 129.692,10.5632 129,11.5C 128.536,10.9056 128.369,10.2389 128.5,9.5 Z"/></g>
+<g><path style="opacity:0.016" fill="#ff423f" d="M 0.5,10.5 C 1.66437,46.6644 1.83103,82.9977 1,119.5C 0.500014,83.1682 0.333347,46.8349 0.5,10.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 128.5,12.5 C 129.664,47.3309 129.831,82.3309 129,117.5C 128.5,82.5016 128.333,47.5016 128.5,12.5 Z"/></g>
+<g><path style="opacity:1" fill="#fefdfd" d="M 57.5,99.5 C 50.8333,99.5 44.1667,99.5 37.5,99.5C 37.5,81.8333 37.5,64.1667 37.5,46.5C 33.5,46.5 29.5,46.5 25.5,46.5C 25.5,41.1667 25.5,35.8333 25.5,30.5C 36.1667,30.5 46.8333,30.5 57.5,30.5C 57.5,53.5 57.5,76.5 57.5,99.5 Z"/></g>
+<g><path style="opacity:1" fill="#fefdfc" d="M 72.5,30.5 C 79.1667,30.5 85.8333,30.5 92.5,30.5C 92.17,48.008 92.5033,65.3414 93.5,82.5C 97.5,82.5 101.5,82.5 105.5,82.5C 105.5,88.1667 105.5,93.8333 105.5,99.5C 94.5,99.5 83.5,99.5 72.5,99.5C 72.5,76.5 72.5,53.5 72.5,30.5 Z"/></g>
+<g><path style="opacity:1" fill="#f29d90" d="M 57.5,99.5 C 57.5,76.5 57.5,53.5 57.5,30.5C 46.8333,30.5 36.1667,30.5 25.5,30.5C 25.5,35.8333 25.5,41.1667 25.5,46.5C 24.5111,41.0247 24.1778,35.358 24.5,29.5C 35.8333,29.5 47.1667,29.5 58.5,29.5C 58.8309,53.006 58.4975,76.3393 57.5,99.5 Z"/></g>
+<g><path style="opacity:1" fill="#f19f91" d="M 72.5,30.5 C 79.3134,29.5088 86.3134,29.1755 93.5,29.5C 93.5,47.1667 93.5,64.8333 93.5,82.5C 92.5033,65.3414 92.17,48.008 92.5,30.5C 85.8333,30.5 79.1667,30.5 72.5,30.5 Z"/></g>
+<g><path style="opacity:0.016" fill="#ff5933" d="M 128.5,118.5 C 129.525,118.897 129.692,119.563 129,120.5C 128.536,119.906 128.369,119.239 128.5,118.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 2.5,120.5 C 1.83333,121.167 1.83333,121.167 2.5,120.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#ff6d22" d="M 127.5,121.5 C 128.833,122.167 128.833,122.833 127.5,123.5C 127.5,122.833 127.5,122.167 127.5,121.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 4.5,123.5 C 4.63101,124.239 4.46434,124.906 4,125.5C 3.30831,124.563 3.47498,123.897 4.5,123.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 126.5,123.5 C 126.833,123.5 127.167,123.5 127.5,123.5C 127.315,124.17 126.981,124.17 126.5,123.5 Z"/></g>
+<g><path style="opacity:0.016" fill="#fe403f" d="M 125.5,124.5 C 125.833,124.5 126.167,124.5 126.5,124.5C 126.315,125.17 125.981,125.17 125.5,124.5 Z"/></g>
+<g><path style="opacity:0.016" fill="#fe403f" d="M 124.5,125.5 C 124.833,125.5 125.167,125.5 125.5,125.5C 125.315,126.17 124.981,126.17 124.5,125.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 7.5,126.5 C 7.5,126.833 7.5,127.167 7.5,127.5C 6.82986,127.019 6.82986,126.685 7.5,126.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 123.5,126.5 C 123.833,126.5 124.167,126.5 124.5,126.5C 124.315,127.17 123.981,127.17 123.5,126.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 7.5,127.5 C 8.83333,128.167 8.83333,128.167 7.5,127.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 121.5,128.5 C 121.5,128.167 121.5,127.833 121.5,127.5C 122.167,127.5 122.833,127.5 123.5,127.5C 123.158,128.338 122.492,128.672 121.5,128.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#fe8000" d="M 9.5,129.5 C 10.6009,128.402 11.9343,128.235 13.5,129C 12.2068,129.49 10.8734,129.657 9.5,129.5 Z"/></g>
+<g><path style="opacity:0.008" fill="#ff7519" d="M 121.5,128.5 C 120.399,129.598 119.066,129.765 117.5,129C 118.793,128.51 120.127,128.343 121.5,128.5 Z"/></g>
+</svg>

+ 0 - 1
dashboard/src/components/porter/Select.tsx

@@ -4,7 +4,6 @@ import styled from "styled-components";
 import arrow from "assets/arrow-down.svg";
 
 import Container from "./Container";
-import Spacer from "./Spacer";
 
 type Props = {
   options: Array<{

+ 3 - 1
dashboard/src/lib/hooks/useCluster.ts

@@ -135,7 +135,9 @@ export const useLatestClusterContract = ({
 
       const res = await api.getContracts(
         "<token>",
-        {},
+        {
+          latest: true,
+        },
         { project_id: currentProject.id }
       );
 

+ 11 - 0
dashboard/src/main/home/compliance-dashboard/ActionBanner.tsx

@@ -22,6 +22,7 @@ export const ActionBanner: React.FC<ActionBannerProps> = ({
   const history = useHistory();
   const {
     profile,
+    vendor,
     updateInProgress,
     latestContractDB,
     latestContractProto,
@@ -87,6 +88,16 @@ export const ActionBanner: React.FC<ActionBannerProps> = ({
     complianceEnabled,
   ]);
 
+  const isHipaaForOneleet = profile === "hipaa" && vendor === "oneleet";
+
+  if (isHipaaForOneleet) {
+    return (
+      <Banner type="warning">
+        HIPAA controls are not yet available for OneLeet
+      </Banner>
+    );
+  }
+
   if (isInfraPending) {
     return (
       <Banner

+ 8 - 1
dashboard/src/main/home/compliance-dashboard/ComplianceContext.tsx

@@ -28,6 +28,7 @@ import {
 } from "./types";
 
 type ComplianceProfileType = "soc2" | "hipaa";
+type ComplianceVendorType = "vanta" | "oneleet";
 
 type ProjectComplianceContextType = {
   projectId: number;
@@ -41,6 +42,8 @@ type ProjectComplianceContextType = {
   updateInProgress: boolean;
   profile: ComplianceProfileType;
   setProfile: Dispatch<SetStateAction<ComplianceProfileType>>;
+  vendor: ComplianceVendorType;
+  setVendor: Dispatch<SetStateAction<ComplianceVendorType>>;
   updateContractWithProfile: () => Promise<void>;
 };
 
@@ -69,6 +72,7 @@ export const ProjectComplianceProvider: React.FC<
   const queryClient = useQueryClient();
   const [updateInProgress, setUpdateInProgress] = useState(false);
   const [profile, setProfile] = useState<ComplianceProfileType>("soc2");
+  const [vendor, setVendor] = useState<ComplianceVendorType>("vanta");
 
   const {
     contractDB: latestContractDB,
@@ -86,13 +90,14 @@ export const ProjectComplianceProvider: React.FC<
         clusterId,
         condition: latestContractDB?.condition ?? "",
         profile,
+        vendor,
         name: "getComplianceChecks",
       },
     ],
     async () => {
       const res = await api.getComplianceChecks(
         "<token>",
-        { vendor: "vanta", profile },
+        { vendor, profile },
         { projectId, clusterId }
       );
 
@@ -181,6 +186,8 @@ export const ProjectComplianceProvider: React.FC<
         updateInProgress,
         profile,
         setProfile,
+        vendor,
+        setVendor,
         updateContractWithProfile,
       }}
     >

+ 16 - 11
dashboard/src/main/home/compliance-dashboard/ConfigSelectors.tsx

@@ -7,6 +7,7 @@ import Spacer from "components/porter/Spacer";
 
 import aws from "assets/aws.png";
 import framework from "assets/framework.svg";
+import oneleet from "assets/oneleet.svg";
 import provider from "assets/provider.svg";
 import typeSvg from "assets/type.svg";
 import vanta from "assets/vanta.svg";
@@ -14,7 +15,7 @@ import vanta from "assets/vanta.svg";
 import { useCompliance } from "./ComplianceContext";
 
 export const ConfigSelectors: React.FC = () => {
-  const { profile, setProfile } = useCompliance();
+  const { profile, setProfile, vendor, setVendor } = useCompliance();
   return (
     <Container row>
       <Select
@@ -25,7 +26,6 @@ export const ConfigSelectors: React.FC = () => {
             label: "HIPAA",
           },
         ]}
-        width="200px"
         value={profile}
         setValue={(value) => {
           if (value === "soc2") {
@@ -58,7 +58,6 @@ export const ConfigSelectors: React.FC = () => {
             disabled: true,
           },
         ]}
-        width="180px"
         value={"aws"}
         setValue={() => {}}
         prefix={
@@ -74,19 +73,25 @@ export const ConfigSelectors: React.FC = () => {
         options={[
           { value: "vanta", label: "Vanta", icon: vanta },
           {
-            value: "drata",
-            label: "Drata (coming soon)",
-            disabled: true,
+            value: "oneleet",
+            label: "Oneleet",
+            icon: oneleet,
           },
           {
-            value: "oneleet",
-            label: "Oneleet (coming soon)",
+            value: "drata",
+            label: "Drata (coming soon)",
             disabled: true,
           },
         ]}
-        width="200px"
-        value={"vanta"}
-        setValue={() => {}}
+        value={vendor}
+        setValue={(value) => {
+          if (value === "vanta") {
+            setVendor("vanta");
+            return;
+          }
+
+          setVendor("oneleet");
+        }}
         prefix={
           <Container row>
             <Image src={provider} size={15} opacity={0.6} />

+ 29 - 12
dashboard/src/main/home/compliance-dashboard/ProfileHeader.tsx

@@ -7,44 +7,61 @@ import Spacer from "components/porter/Spacer";
 import Text from "components/porter/Text";
 
 import linkExternal from "assets/link-external.svg";
+import oneleet from "assets/oneleet.svg";
 import vanta from "assets/vanta.svg";
 
 import { useCompliance } from "./ComplianceContext";
 
 export const ProfileHeader: React.FC = () => {
-  const { profile } = useCompliance();
+  const { profile, vendor } = useCompliance();
 
   const header = useMemo(() => {
-    return match(profile)
-      .with("soc2", () => ({
+    return match({ profile, vendor })
+      .with({ profile: "soc2", vendor: "vanta" }, () => ({
         text: "AWS SOC 2 Controls (Vanta)",
         link: "https://app.vanta.com/tests?framework=soc2&service=aws&taskType=TEST",
+        logo: vanta,
       }))
-      .with("hipaa", () => ({
+      .with({ profile: "hipaa", vendor: "vanta" }, () => ({
         text: "AWS HIPAA Controls (Vanta)",
         link: "https://app.vanta.com/tests?framework=hipaa&service=aws&taskType=TEST",
+        logo: vanta,
+      }))
+      .with({ profile: "soc2", vendor: "oneleet" }, () => ({
+        text: "AWS SOC 2 Controls (OneLeet)",
+        link: "https://app.oneleet.io/controls?framework=soc2&service=aws",
+        logo: oneleet,
+      }))
+      .with({ profile: "hipaa", vendor: "oneleet" }, () => ({
+        text: "AWS HIPAA Controls (OneLeet)",
+        link: "https://app.oneleet.io/controls?framework=hipaa&service=aws",
+        logo: oneleet,
       }))
       .exhaustive();
-  }, [profile]);
+  }, [profile, vendor]);
 
   return (
     <Container row>
-      <Image src={vanta} size={25} />
+      <Image src={header.logo} size={25} />
       <Spacer inline x={1} />
       <Text
         size={21}
         additionalStyles=":hover { text-decoration: underline } cursor: pointer;"
         onClick={() => {
-          window.open(header.link, "_blank");
+          if (vendor === "vanta") {
+            window.open(header.link, "_blank");
+          }
         }}
       >
         {header.text}
         <Spacer inline x={0.5} />
-        <Image
-          src={linkExternal}
-          size={16}
-          additionalStyles="margin-bottom: -2px"
-        />
+        {vendor === "vanta" && (
+          <Image
+            src={linkExternal}
+            size={16}
+            additionalStyles="margin-bottom: -2px"
+          />
+        )}
       </Text>
     </Container>
   );

+ 16 - 11
dashboard/src/main/home/compliance-dashboard/VendorChecksList.tsx

@@ -20,7 +20,8 @@ import { type VendorCheck } from "./types";
 type Filter = "all" | "passing" | "action-required" | "not-applicable";
 
 export const VendorChecksList: React.FC = () => {
-  const { profile, vendorChecks, latestContractProto } = useCompliance();
+  const { profile, vendor, vendorChecks, latestContractProto } =
+    useCompliance();
   const { showIntercomWithMessage } = useIntercom();
 
   const [statusFilter, setStatusFilter] = useState<Filter>("all");
@@ -213,20 +214,24 @@ export const VendorChecksList: React.FC = () => {
                 }}
                 additionalStyles=":hover { text-decoration: underline }"
                 onClick={() => {
-                  window.open(
-                    `https://app.vanta.com/tests/${check.vendor_check_id}`,
-                    "_blank"
-                  );
+                  if (vendor === "vanta") {
+                    window.open(
+                      `https://app.vanta.com/tests/${check.vendor_check_id}`,
+                      "_blank"
+                    );
+                  }
                 }}
               >
                 {check.check}
                 <Spacer inline x={0.5} />
-                <Image
-                  src={linkExternal}
-                  opacity={check.status === "not_applicable" ? 0.25 : 1}
-                  size={12}
-                  additionalStyles="margin-bottom: -2px"
-                />
+                {vendor === "vanta" && (
+                  <Image
+                    src={linkExternal}
+                    opacity={check.status === "not_applicable" ? 0.25 : 1}
+                    size={12}
+                    additionalStyles="margin-bottom: -2px"
+                  />
+                )}
               </Text>
             </Container>
             <Spacer y={1} />

+ 2 - 2
dashboard/src/shared/api.tsx

@@ -1529,7 +1529,7 @@ const createContract = baseApi<Contract, { project_id: number }>(
   }
 );
 
-const getContracts = baseApi<{ cluster_id?: number }, { project_id: number }>(
+const getContracts = baseApi<{ cluster_id?: number, latest?: boolean }, { project_id: number }>(
   "GET",
   ({ project_id }) => {
     return `/api/projects/${project_id}/contracts`;
@@ -1551,7 +1551,7 @@ const getClusterState = baseApi<{}, { project_id: number; cluster_id: number }>(
 );
 
 const getComplianceChecks = baseApi<
-  { vendor: "vanta"; profile: "soc2" | "hipaa" },
+  { vendor: "vanta" | "oneleet"; profile: "soc2" | "hipaa" },
   { projectId: number; clusterId: number }
 >("GET", ({ projectId, clusterId }) => {
   return `/api/projects/${projectId}/clusters/${clusterId}/compliance/checks`;

+ 1 - 1
go.mod

@@ -83,7 +83,7 @@ require (
 	github.com/matryer/is v1.4.0
 	github.com/nats-io/nats.go v1.24.0
 	github.com/open-policy-agent/opa v0.44.0
-	github.com/porter-dev/api-contracts v0.2.103
+	github.com/porter-dev/api-contracts v0.2.104
 	github.com/riandyrn/otelchi v0.5.1
 	github.com/santhosh-tekuri/jsonschema/v5 v5.0.1
 	github.com/stefanmcshane/helm v0.0.0-20221213002717-88a4a2c6e77d

+ 2 - 2
go.sum

@@ -1523,8 +1523,8 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw=
-github.com/porter-dev/api-contracts v0.2.103 h1:z6tMxs5aF7owi4SRiFUKN/IzXYkOHKIb5Ekqlw8N5U8=
-github.com/porter-dev/api-contracts v0.2.103/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8=
+github.com/porter-dev/api-contracts v0.2.104 h1:4ddEMSPlqR12lZWhhY92yZxdHCqoypIuvFiAwfL1g2U=
+github.com/porter-dev/api-contracts v0.2.104/go.mod h1:fX6JmP5QuzxDLvqP3evFOTXjI4dHxsG0+VKNTjImZU8=
 github.com/porter-dev/switchboard v0.0.3 h1:dBuYkiVLa5Ce7059d6qTe9a1C2XEORFEanhbtV92R+M=
 github.com/porter-dev/switchboard v0.0.3/go.mod h1:xSPzqSFMQ6OSbp42fhCi4AbGbQbsm6nRvOkrblFeXU4=
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=

+ 2 - 0
internal/compliance/convert.go

@@ -59,6 +59,8 @@ type Vendor string
 const (
 	// Vendor_Vanta is use to indicate that the compliance results are based on checks from Vanta
 	Vendor_Vanta Vendor = "vanta"
+	// Vendor_OneLeet is use to indicate that the compliance results are based on checks from OneLeet
+	Vendor_OneLeet Vendor = "oneleet"
 )
 
 // Profile is used to indicate which compliance profile the compliance check results are from