diff --git a/.gitignore b/.gitignore index 01e6f22..0a98f60 100644 --- a/.gitignore +++ b/.gitignore @@ -107,4 +107,7 @@ dist .netlify #deploy -/bin \ No newline at end of file +/bin + +#vscode +*.vscode \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 244211f..0b36cfa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,9 @@ RUN wget https://github.com/FairwindsOps/polaris/releases/download/5.0.0/polaris RUN tar xf polaris_linux_amd64.tar.gz RUN cp polaris /usr/local/bin +RUN curl -s https://raw.githubusercontent.com/armosec/kubescape/master/install.sh | /bin/bash +RUN cp kubescape /usr/lcoal/bin + FROM golang:1.17 ARG FUNCTION_DIR="/var/task" @@ -25,6 +28,8 @@ COPY --from=deps /usr/local/bin/kubeval /usr/local/bin/kubeval RUN chmod +x /usr/local/bin/kubeval COPY --from=deps /usr/local/bin/polaris /usr/local/bin/polaris RUN chmod +x /usr/local/bin/polaris +COPY --from=deps /usr/local/bin/kubescape /usr/local/bin/kubescape +RUN chmod +x /usr/local/bin/kubescape # Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile) diff --git a/Makefile b/Makefile index 3ddd243..761da1d 100644 --- a/Makefile +++ b/Makefile @@ -17,8 +17,12 @@ run-container-local: docker run -it --entrypoint /bin/bash validkube start-local-backend: + export ALLOWED_ORIGIN=http://localhost:3000 go run backend/development/localdev.go +start-local-frontend: + cd frontend && yarn start + deploy-backend: clean build sls deploy --verbose diff --git a/backend/api/kubescape/kubescape.go b/backend/api/kubescape/kubescape.go new file mode 100644 index 0000000..e2f4b23 --- /dev/null +++ b/backend/api/kubescape/kubescape.go @@ -0,0 +1,63 @@ +package kubescape + +import ( + "fmt" + "io/ioutil" + "net/http" + "os/exec" + + "github.com/gin-gonic/gin" + "github.com/komodorio/validkube/backend/api/utils" + "github.com/komodorio/validkube/backend/internal/routing" + "sigs.k8s.io/yaml" +) + +const Path = "/kubescape" +const Method = routing.POST + +func kubescapeWrapper(inputYaml []byte) ([]byte, error) { + err := utils.CreateDirectory("/tmp/yaml") + if err != nil { + return nil, err + } + + err = utils.WriteFile("/tmp/yaml/target_yaml.yaml", inputYaml) + if err != nil { + return nil, err + } + + outputFile := "/tmp/yaml/output.json" + exec.Command("kubescape", "scan", "/tmp/yaml/target_yaml.yaml", "-o", outputFile, "-f", "json").Output() + + outputFromKubescapeAsJson, err := ioutil.ReadFile(outputFile) + if err != nil { + return nil, err + } + + outputFromKubescapeAsYaml, err := yaml.JSONToYAML(outputFromKubescapeAsJson) + if err != nil { + return nil, err + } + return outputFromKubescapeAsYaml, nil +} + +func ProcessRequest(c *gin.Context) { + body, err := ioutil.ReadAll(c.Request.Body) + if err != nil { + fmt.Printf("Erorr has with reading request body: %v", err) + c.JSON(http.StatusOK, gin.H{"data": "", "err": err.Error()}) + return + } + bodyAsMap, err := utils.JsonToMap(body) + if err != nil { + c.JSON(http.StatusOK, gin.H{"data": "", "err": err.Error()}) + return + } + yamlAsInterface := bodyAsMap["yaml"] + kubescapeOutput, err := kubescapeWrapper(utils.InterfaceToBytes(yamlAsInterface)) + if err != nil { + c.JSON(http.StatusOK, gin.H{"data": "", "err": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"data": string(kubescapeOutput), "err": nil}) +} diff --git a/backend/api/utils/files.go b/backend/api/utils/files.go index 2f2f6f7..2c967a5 100644 --- a/backend/api/utils/files.go +++ b/backend/api/utils/files.go @@ -1,6 +1,8 @@ package utils -import "os" +import ( + "os" +) func WriteFile(path string, data []byte) error { file, err := os.Create(path) diff --git a/backend/endpoints/endpoints.go b/backend/endpoints/endpoints.go index 36a9416..6d1a137 100644 --- a/backend/endpoints/endpoints.go +++ b/backend/endpoints/endpoints.go @@ -4,6 +4,7 @@ import ( "github.com/gin-gonic/gin" "github.com/komodorio/validkube/backend/api/hello" "github.com/komodorio/validkube/backend/api/kubeneat" + "github.com/komodorio/validkube/backend/api/kubescape" "github.com/komodorio/validkube/backend/api/kubeval" "github.com/komodorio/validkube/backend/api/polaris" "github.com/komodorio/validkube/backend/api/trivy" @@ -41,4 +42,9 @@ var Endpoints = []Endpoint{ Method: polaris.Method, Function: polaris.ProcessRequest, }, + { + Path: kubescape.Path, + Method: kubescape.Method, + Function: kubescape.ProcessRequest, + }, } diff --git a/frontend/src/components/MainView/YamlBox/NewYaml.tsx b/frontend/src/components/MainView/YamlBox/NewYaml.tsx index d5c3e20..24781ed 100644 --- a/frontend/src/components/MainView/YamlBox/NewYaml.tsx +++ b/frontend/src/components/MainView/YamlBox/NewYaml.tsx @@ -17,7 +17,13 @@ import { } from "./YamlBoxComponents"; import CodeEditor from "@uiw/react-textarea-code-editor"; -export const API_ENDPOINTS = ["kubeval", "kubeneat", "trivy", "polaris"]; +export const API_ENDPOINTS = [ + "kubeval", + "kubeneat", + "trivy", + "polaris", + "kubescape", +]; const Container = styled.div``; @@ -76,7 +82,13 @@ const NewYaml: React.FC = ({ curTab, setCurTab, }) => { - const tabs = ["Validate", "Clean", "Secure (Trivy)", "Audit (Polaris)"]; + const tabs = [ + "Validate", + "Clean", + "Secure (Trivy)", + "Audit (Polaris)", + "Secure (Kubescape)", + ]; return ( diff --git a/frontend/src/tests/App.test.tsx b/frontend/src/tests/App.test.tsx deleted file mode 100644 index 23cb966..0000000 --- a/frontend/src/tests/App.test.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from "react"; -import { render, screen } from "@testing-library/react"; -import App from "../App"; - -test("renders learn react link", () => { - render(); - const linkElement = screen.getByText(/learn react/i); - expect(linkElement).toBeInTheDocument(); -}); diff --git a/frontend/src/tests/setupTests.ts b/frontend/src/tests/setupTests.ts deleted file mode 100644 index 8f2609b..0000000 --- a/frontend/src/tests/setupTests.ts +++ /dev/null @@ -1,5 +0,0 @@ -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -import '@testing-library/jest-dom'; diff --git a/serverless.yml b/serverless.yml index b2729ac..9627061 100644 --- a/serverless.yml +++ b/serverless.yml @@ -51,7 +51,7 @@ functions: - http: path: /kubeval method: post - cors: true + cors: true Polaris: image: name: validkube @@ -60,6 +60,14 @@ functions: path: /polaris method: post cors: true + Kubescape: + image: + name: validkube + events: + - http: + path: /kubescape + method: post + cors: true resources: - ${file(s3-bucket.yml)}