diff --git a/.github/workflows/action.yaml b/.github/workflows/action.yaml new file mode 100644 index 0000000..56fbf67 --- /dev/null +++ b/.github/workflows/action.yaml @@ -0,0 +1,31 @@ +name: Report CI workflow + +on: + push: + branches: [ main, master ] + pull_request: + branches: [ main, master ] + + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Use nodejs + uses: actions/setup-node@v3 + with: + node-version: '20' + + - name: Install deps + run: npm ci + + - name: Lint and format + run: | + npm run lint + npm run format + + - name: Build + run: npm run build diff --git a/.gitignore b/.gitignore index 485dee6..d9be7be 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,6 @@ .idea +node_modules/ +test-output/ +dist/ +biome.json +knoxctl-results diff --git a/README.md b/README.md index 97b6a5f..8b6a77d 100644 --- a/README.md +++ b/README.md @@ -1,127 +1,3 @@ # report-action -Github actions to trigger report generation for runtime security. - -## Learn More - -- [About Kubearmor](https://github.com/kubearmor/KubeArmor) -- [About Discovery Engine](https://github.com/accuknox/discovery-engine) - -## Inputs - -```yaml -inputs: - baseline-report-path: - description: 'baseline report path' - required: true - default: "baseline/report.json" - - labels: - description: 'labels. possible value: kubearmor-app: kubearmor-relay' - required: false - default: "" - - operation: - description: 'operation. possible values: process, file, network, syscall' - required: false - default: "" - - container-name: - description: 'container name' - required: false - default: "" - - namespaces: - description: 'namespaces' - required: false - default: "" - - workloads: - description: 'workloads. possible values: deployment/mysql, statefulsets/vault, deployment/*' - required: false - default: "" - - source: - description: 'source' - required: false - default: "" - - process-ignore-paths: - description: 'process ignore paths. possible value: /sbin ' - required: false - default: "" - - file-ignore-paths: - description: 'file ignore paths. possible value: /sbin ' - required: false - default: "" - - ignore-return-code: - description: 'ignore return code. possible values: true/false' - required: false - default: "" - - view: - description: 'view type. possible value: tabular' - required: false - default: "tabular" - -``` - -## Usage - -Steps for using install-action in a workflow yaml file -- Checkout into the repo using checkout action. -- Set up a k8's cluster. -- Use [accuknox-install](https://github.com/marketplace/actions/accuknox-install) action to install Kubearmor and Discovery Engine. -- Use accuknox-report action to generate report using Kubearmor and Discovery Engine. - -### Generate report at specific path - -```yaml -- name: accuknox-report - uses: accuknox/report-action@v0.1.2 - with: - baseline-report-path: "baseline/report.json" - -``` - - -## Sample Configuration - -```yaml -name: learn-accuknox-report-action -on: - pull_request: - branches: [main] - types: [opened, synchronize, reopened] - push: - branches: [main] -jobs: - check-working: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v3 - with: - submodules: true - - - name: Checkout kubearmor repo - uses: actions/checkout@v3 - with: - repository: kubearmor/KubeArmor - ref: main - path: Kubearmor - - - name: Setup a Kubernetes environment - run: | - ./Kubearmor/contribution/k3s/install_k3s.sh - sudo apt install socat - - - name: Install accuknoxcli, KubeArmor and Discovery Engine - uses: accuknox/install-action@v0.1.1 - - - name: Generate Report - uses: accuknox/report-action@v0.1.2 - -``` +TO-DO diff --git a/action.yml b/action.yml index d907033..689e302 100644 --- a/action.yml +++ b/action.yml @@ -1,104 +1,25 @@ -name: accuknox-report -description: 'Generate reports using kubearmor and discovery engine' +name: CI/CD Scan by AccuKnox +description: 'Secure your CI/CD pipelines, powered by KubeArmor' +branding: + icon: shield + color: green +author: AccuKnox + inputs: - baseline-report-path: - description: 'baseline report path' - required: true - default: "baseline/report.json" - labels: - description: 'labels. possible value: kubearmor-app: kubearmor-relay' - required: false - default: "" - operation: - description: 'operation. possible values: process, file, network, syscall' - required: false - default: "" - container-name: - description: 'container name' - required: false - default: "" - namespaces: - description: 'namespaces' - required: false - default: "" - workloads: - description: 'workloads. possible values: deployment/mysql, statefulsets/vault, deployment/*' - required: false - default: "" - source: - description: 'source' + all: + description: 'Scan for all events collected by KubeArmor' required: false - default: "" - process-ignore-paths: - description: 'process ignore paths. possible value: /sbin ' + default: 'true' + system: + description: 'Scan for only system events' required: false - default: "" - file-ignore-paths: - description: 'file ignore paths. possible value: /sbin ' + default: 'false' + output: + description: 'Output path for the files to be placed' required: false - default: "" - ignore-return-code: - description: 'ignore return code. possible values: true/false' - required: false - default: "" - view: - description: 'view type. possible value: tabular' - required: false - default: "tabular" + default: './knoxctl-results' runs: - using: "composite" - steps: - - name: Generate report - run: | - accuknox-cli version - - setupArgs="" - if [ "${{ inputs.baseline-report-path }}" != "" ]; then - setupArgs+=" -b ${{ inputs.baseline-report-path }}" - fi - if [ "${{ inputs.labels }}" != "" ]; then - setupArgs+=" -l ${{ inputs.labels }}" - fi - if [ "${{ inputs.operation }}" != "" ]; then - setupArgs+=" -t ${{ inputs.operation }}" - fi - if [ "${{ inputs.container-name }}" != "" ]; then - setupArgs+=" --container ${{ inputs.container-name }}" - fi - if [ "${{ inputs.namespaces }}" != "" ]; then - setupArgs+=" -n ${{ inputs.namespaces }}" - fi - if [ "${{ inputs.source }}" != "" ]; then - setupArgs+=" -s ${{ inputs.source }}" - fi - if [ "${{ inputs.file-ignore-paths }}" != "" ]; then - setupArgs+=" -i ${{ inputs.file-ignore-paths }}" - fi - if [ "${{ inputs.process-ignore-paths }}" != "" ]; then - setupArgs+=" -i ${{ inputs.process-ignore-paths }}" - fi - - sleep 360 - accuknox-cli report $setupArgs - - mkdir downloads - mv /tmp/report-*.json downloads/report.json - mv /tmp/diff-report-*.json downloads/diff-report.json - mv /tmp/diff-report-*.md downloads/diff-report.md - shell: bash - - - name: Upload artifacts - uses: actions/upload-artifact@v2 - with: - name: Baseline report - path: downloads - - - name: PR comment with file - uses: thollander/actions-comment-pull-request@v2 - with: - filePath: downloads/diff-report.md - -branding: - icon: 'check-circle' - color: 'green' \ No newline at end of file + using: 'node20' + main: 'dist/main/index.js' + post: 'dist/post/index.js' diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..c32c398 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,689 @@ +{ + "name": "report-action", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "report-action", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/github": "^6.0.0" + }, + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@types/node": "^20.14.12", + "@vercel/ncc": "^0.38.1", + "ts-node": "^10.9.1", + "typescript": "^5.0.0" + } + }, + "node_modules/@actions/core": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", + "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "dependencies": { + "@actions/http-client": "^2.0.1", + "uuid": "^8.3.2" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/github": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", + "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", + "license": "MIT", + "dependencies": { + "@actions/http-client": "^2.2.0", + "@octokit/core": "^5.0.1", + "@octokit/plugin-paginate-rest": "^9.0.0", + "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz", + "integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==", + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==" + }, + "node_modules/@biomejs/biome": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.8.3.tgz", + "integrity": "sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.8.3", + "@biomejs/cli-darwin-x64": "1.8.3", + "@biomejs/cli-linux-arm64": "1.8.3", + "@biomejs/cli-linux-arm64-musl": "1.8.3", + "@biomejs/cli-linux-x64": "1.8.3", + "@biomejs/cli-linux-x64-musl": "1.8.3", + "@biomejs/cli-win32-arm64": "1.8.3", + "@biomejs/cli-win32-x64": "1.8.3" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.8.3.tgz", + "integrity": "sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.8.3.tgz", + "integrity": "sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.8.3.tgz", + "integrity": "sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.8.3.tgz", + "integrity": "sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.8.3.tgz", + "integrity": "sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.8.3.tgz", + "integrity": "sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.8.3.tgz", + "integrity": "sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.8.3.tgz", + "integrity": "sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.0.tgz", + "integrity": "sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.3.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", + "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.0.tgz", + "integrity": "sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.3.0", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "22.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-22.2.0.tgz", + "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", + "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz", + "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.1", + "@octokit/request-error": "^5.1.0", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", + "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.5.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", + "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^22.2.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.14.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", + "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@vercel/ncc": { + "version": "0.38.1", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", + "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", + "dev": true, + "license": "MIT", + "bin": { + "ncc": "dist/ncc/cli.js" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.3.tgz", + "integrity": "sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "license": "Apache-2.0" + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "license": "ISC" + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "license": "ISC" + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8d954ed --- /dev/null +++ b/package.json @@ -0,0 +1,32 @@ +{ + "name": "report-action", + "version": "1.0.0", + "description": "Github actions to trigger report generation for runtime security.", + "main": "dist/main/index.js", + "scripts": { + "build": "npm run build:main && npm run build:post", + "build:main": "npx ncc build src/main/index.ts -o dist/main --source-map --license licenses.txt", + "build:post": "npx ncc build src/post/index.ts -o dist/post --source-map --license licenses.txt", + "start:main": "node dist/main/index.js", + "start:post": "node dist/post/index.js", + "dev:main": "npx ts-node src/main/index.ts", + "dev:post": "npx ts-node src/post/index.ts", + "lint": "npx biome check .", + "format": "npx biome format . --write" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@actions/core": "^1.10.1", + "@actions/exec": "^1.1.1", + "@actions/github": "^6.0.0" + }, + "devDependencies": { + "@biomejs/biome": "1.8.3", + "@types/node": "^20.14.12", + "@vercel/ncc": "^0.38.1", + "ts-node": "^10.9.1", + "typescript": "^5.0.0" + } +} diff --git a/src/common/common.ts b/src/common/common.ts new file mode 100644 index 0000000..8dc7a46 --- /dev/null +++ b/src/common/common.ts @@ -0,0 +1,61 @@ +import * as core from "@actions/core"; +import * as fs from "node:fs"; +import * as path from "node:path"; + +export const PID_FILE_NAME = "knoxctl_scan_pid"; +export const RESULTS_DIR_NAME = "knoxctl-results"; +export const ENCODING = "utf8"; + +export const IS_GITHUB_ACTIONS = !!process.env.GITHUB_ACTIONS; +export const WORKSPACE = process.env.GITHUB_WORKSPACE; + +export function log( + message: string, + type: "info" | "warning" | "error" = "info", +): void { + if (IS_GITHUB_ACTIONS) { + switch (type) { + case "warning": + core.warning(message); + break; + case "error": + core.error(message); + break; + default: + core.info(message); + } + } else { + console.log(message); + } +} + +export function getPidFilePath(): string { + return WORKSPACE + ? path.join(WORKSPACE, PID_FILE_NAME) + : path.join(__dirname, "..", "..", PID_FILE_NAME); +} + +export function getOutputDir(): string { + return WORKSPACE + ? WORKSPACE + : path.join(__dirname, "..", "..", RESULTS_DIR_NAME); +} + +export function mockCoreForLocalTesting(): void { + if (!IS_GITHUB_ACTIONS) { + (core as any).getInput = (name: string): string => { + const inputs: { [key: string]: string } = { + all: "true", + system: "false", + output: "./knoxctl-results", + }; + return inputs[name] || ""; + }; + + (core as any).getBooleanInput = (name: string): boolean => { + return (core as any).getInput(name) === "true"; + }; + + (core as any).setFailed = console.error; + } +} diff --git a/src/main/index.ts b/src/main/index.ts new file mode 100644 index 0000000..a4be546 --- /dev/null +++ b/src/main/index.ts @@ -0,0 +1,160 @@ +import * as core from "@actions/core"; +import * as exec from "@actions/exec"; +import * as https from "node:https"; +import * as fs from "node:fs"; +import { spawn, ChildProcess } from "node:child_process"; +import * as path from "node:path"; +import { + log, + getPidFilePath, + getOutputDir, + IS_GITHUB_ACTIONS, + mockCoreForLocalTesting, +} from "@common/common"; + +async function getLatestKubeArmorVersion(): Promise { + return new Promise((resolve, reject) => { + https + .get( + "https://api.github.com/repos/kubearmor/KubeArmor/releases/latest", + { + headers: { "User-Agent": "GitHub-Action" }, + }, + (res) => { + let data = ""; + res.on("data", (chunk) => (data += chunk)); + res.on("end", () => { + const version = JSON.parse(data).tag_name.replace("v", ""); + resolve(version); + }); + }, + ) + .on("error", reject); + }); +} + +async function downloadKubeArmor(version: string): Promise { + const url = `https://github.com/kubearmor/KubeArmor/releases/download/v${version}/kubearmor_${version}_linux-amd64.deb`; + const filePath = `./kubearmor_${version}_linux-amd64.deb`; + + return new Promise((resolve, reject) => { + https + .get(url, (res) => { + const writeStream = fs.createWriteStream(filePath); + res.pipe(writeStream); + writeStream.on("finish", () => { + writeStream.close(); + resolve(filePath); + }); + }) + .on("error", reject); + }); +} + +async function installKubeArmor(filePath: string): Promise { + await exec.exec(`sudo apt --no-install-recommends install -y ${filePath}`); +} + +async function installKnoxctl(): Promise { + const installCmd = + "curl -sfL https://knoxctl.accuknox.com/install.sh | sudo sh -s -- -b /usr/local/bin"; + await exec.exec(installCmd); + await exec.exec("knoxctl version"); +} + +async function startKubeArmor(): Promise { + await exec.exec("sudo systemctl start kubearmor"); + await exec.exec("sudo systemctl status kubearmor"); +} + +async function runKnoxctlScan(): Promise { + const knoxctlOptions = [ + { name: "all", flag: "--all", type: "boolean" }, + { name: "system", flag: "--system", type: "boolean" }, + { name: "output", flag: "--output", type: "string" }, + ]; + + let command: string[] = ["knoxctl", "scan"]; + let outputDir = getOutputDir(); + + knoxctlOptions.forEach((option) => { + let value: boolean | string; + + if (option.type === "boolean") { + value = core.getBooleanInput(option.name); + if (value) { + command.push(option.flag); + } + } else if (option.type === "string") { + value = core.getInput(option.name); + if (value) { + if (option.name === "output") { + outputDir = value; + } + command.push(option.flag, value); + } + } + }); + + if (!fs.existsSync(outputDir)) { + log(`Creating output directory: ${outputDir}`); + fs.mkdirSync(outputDir, { recursive: true }); + } + + const commandString = command.join(" "); + log(`Executing command: ${commandString}`); + + const scanProcess: ChildProcess = spawn(command[0], command.slice(1), { + stdio: "inherit", + detached: true, + }); + + log(`knoxctl scan started with PID: ${scanProcess.pid}`); + + const pidFile = getPidFilePath(); + fs.writeFileSync(pidFile, scanProcess.pid!.toString()); + + scanProcess.unref(); + + log(`knoxctl scan PID written to ${pidFile}`); + log( + "knoxctl scan is running in the background. Use the post script to stop it.", + ); +} + +async function run(): Promise { + try { + mockCoreForLocalTesting(); + + if (!IS_GITHUB_ACTIONS) { + log( + "Running in local test mode. Skipping KubeArmor and knoxctl installation.", + ); + } else { + const version = await getLatestKubeArmorVersion(); + log(`Latest KubeArmor version: ${version}`); + + const filePath = await downloadKubeArmor(version); + log(`Downloaded KubeArmor to: ${filePath}`); + + await installKubeArmor(filePath); + log("KubeArmor installed successfully"); + + await startKubeArmor(); + log("KubeArmor started successfully"); + + await installKnoxctl(); + log("Installed knoxctl binary"); + } + + await runKnoxctlScan(); + } catch (error) { + if (error instanceof Error) { + core.setFailed(error.message); + } else { + core.setFailed("An unknown error occurred"); + } + } +} + +run(); diff --git a/src/post/index.ts b/src/post/index.ts new file mode 100644 index 0000000..e317347 --- /dev/null +++ b/src/post/index.ts @@ -0,0 +1,114 @@ +import * as core from "@actions/core"; +import * as fs from "node:fs"; +import * as path from "node:path"; +import { + log, + getPidFilePath, + getOutputDir, + IS_GITHUB_ACTIONS, + ENCODING, +} from "@common/common"; + +const NETWORK_EVENTS_PREFIX = "knoxctl_scan_network_events_md_"; +const PROCESS_TREE_PREFIX = "knoxctl_scan_process_tree_"; + +function stopKnoxctlScan(): void { + const pidFile = getPidFilePath(); + + if (fs.existsSync(pidFile)) { + const pid = fs.readFileSync(pidFile, ENCODING).toString(); + log(`Stopping knoxctl scan process with PID: ${pid}`); + + try { + process.kill(Number.parseInt(pid), "SIGINT"); + log("knoxctl scan process stopped successfully"); + } catch (error) { + log("Failed to stop knoxctl scan process:", "error"); + log(error instanceof Error ? error.message : String(error), "error"); + } + + fs.unlinkSync(pidFile); + } else { + log("No knoxctl scan PID file found"); + } +} + +function getLatestFile(directory: string, prefix: string): string | null { + const files = fs + .readdirSync(directory) + .filter((file) => file.startsWith(prefix) && file.endsWith(".md")) + .map((file) => ({ + name: file, + time: fs.statSync(path.join(directory, file)).mtime.getTime(), + })) + .sort((a, b) => b.time - a.time); + + return files.length > 0 ? files[0].name : null; +} + +function addToSummary(content: string): void { + if (IS_GITHUB_ACTIONS) { + core.summary.addRaw(content).addEOL(); + } else { + console.log(content); + } +} + +function processResultFile( + outputDir: string, + prefix: string, + title: string, +): void { + const file = getLatestFile(outputDir, prefix); + if (file) { + const content = fs.readFileSync(path.join(outputDir, file), ENCODING); + addToSummary(`## ${title}\n\n${content}`); + } else { + log(`No ${title.toLowerCase()} file found`); + } +} + +function processResults(): void { + const outputDir = getOutputDir(); + + if (!outputDir) { + throw new Error("Output directory is not defined"); + } + + log("Processing knoxctl results"); + + if (!IS_GITHUB_ACTIONS) { + log( + "Running in local environment. Results will be displayed in the console.", + "warning", + ); + } + + processResultFile(outputDir, NETWORK_EVENTS_PREFIX, "Network Events"); + processResultFile(outputDir, PROCESS_TREE_PREFIX, "Process Tree"); + + if (!IS_GITHUB_ACTIONS) { + log( + "\nResults processing complete. In a GitHub Actions environment, these results would be added to the job summary.", + ); + } +} + +async function run(): Promise { + try { + stopKnoxctlScan(); + processResults(); + if (IS_GITHUB_ACTIONS) { + await core.summary.write(); + } + } catch (error) { + if (IS_GITHUB_ACTIONS) { + core.setFailed(error instanceof Error ? error.message : String(error)); + } else { + console.error("Error in post-job script:", error); + process.exit(1); + } + } +} + +run(); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4b6e411 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "es2018", + "module": "commonjs", + "outDir": "dist/", + "rootDir": "src", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "baseUrl": "src", + "paths": { + "@common/*": ["common/*"] + } + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +}