Merge branch 'main' into int

This commit is contained in:
Varun Sharma 2024-03-25 17:17:51 -07:00
commit 04b17a9514
No known key found for this signature in database
GPG key ID: CE30C1F427CE6272
34 changed files with 12598 additions and 12365 deletions

View file

@ -22,7 +22,7 @@ jobs:
permissions:
contents: write
steps:
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v1
- uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v1
with:
egress-policy: audit
allowed-endpoints:
@ -41,3 +41,9 @@ jobs:
env:
PAT: ${{ secrets.PAT }}
canary: true
- name: Canary TLS test
uses: docker://ghcr.io/step-security/integration-test/int:latest
env:
PAT: ${{ secrets.PAT }}
canary-tls: true

View file

@ -11,7 +11,7 @@ jobs:
pull-requests: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
disable-sudo: true
egress-policy: block

View file

@ -41,7 +41,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs

View file

@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
egress-policy: audit

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
@ -22,3 +22,18 @@ jobs:
env:
PAT: ${{ secrets.PAT }}
canary: true
int-tls-tests:
name: int tls tests
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
- name: Canary test
uses: docker://ghcr.io/step-security/integration-test/int:latest
env:
PAT: ${{ secrets.PAT }}
canary-tls: true

View file

@ -25,7 +25,7 @@ jobs:
permissions:
contents: write
steps:
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895
- uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142
with:
egress-policy: audit
allowed-endpoints:

View file

@ -25,7 +25,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
egress-policy: audit

View file

@ -13,10 +13,13 @@ concurrency:
group: ${{ github.workflow }}
jobs:
test:
permissions:
checks: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
disable-sudo: true
egress-policy: audit
@ -35,3 +38,9 @@ jobs:
- name: Run coverage
run: npm test -- --coverage
- uses: codecov/codecov-action@eaaf4bedf32dbdc6b720b63067d99c4d77d6047d # v3.1.4
- name: Publish Test Results
uses: step-security/publish-unit-test-result-action@v1
if: always()
with:
files: |
reports/*.xml

1
.gitignore vendored
View file

@ -20,6 +20,7 @@ lib-cov
# Coverage directory used by tools like istanbul
coverage
reports
*.lcov
# nyc test coverage

116
README.md
View file

@ -13,42 +13,35 @@
</div>
## GitHub Actions Runtime Security
## Harden Github-hosted and self-hosted runners
Harden-Runner provides runtime security for GitHub-hosted and self-hosted environments.
Harden-Runner provides network egress filtering and runtime security for GitHub-hosted and self-hosted runners.
For self-hosted environments, Harden-Runner supports:
1. Kubernetes runners setup using Actions Runner Controller (ARC)
2. Virtual Machine runners (e.g. on EC2) - both ephemeral and persistent runners are supported
[![Harden Runner Demo](images/RuntimeSecurityDemo.gif)](https://youtu.be/fpdwX5hYACo)
![Harden Runner Demo](images/main.png)
## Explore open source projects using Harden-Runner
| [![CISA](https://avatars.githubusercontent.com/u/18539691?s=60&v=4)](https://app.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/6199340224) | [![Microsoft](https://avatars.githubusercontent.com/u/6154722?s=60&v=4)](https://app.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/5559160177) | [![Google](https://avatars.githubusercontent.com/u/2810941?s=60&v=4)](https://app.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/5546354505) | [![DataDog](https://avatars.githubusercontent.com/u/365230?s=60&v=4)](https://app.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/5387101451) | [![Intel](https://avatars.githubusercontent.com/u/17888862?s=60&v=4)](https://app.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/5579910614) | [![Kubernetes](https://avatars.githubusercontent.com/u/36015203?s=60&v=4)](https://app.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/5581511101) | [![Node.js](https://avatars.githubusercontent.com/u/9950313?s=60&v=4)](https://app.stepsecurity.io/github/nodejs/node/actions/runs/5563468674) | [![Mastercard](https://avatars.githubusercontent.com/u/1653148?s=60&v=4)](https://app.stepsecurity.io/github/Mastercard/flow/actions/runs/5542112873) |
| [![CISA](https://avatars.githubusercontent.com/u/18539691?s=60&v=4)](https://app.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/7588528684) | [![Microsoft](https://avatars.githubusercontent.com/u/6154722?s=60&v=4)](https://app.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/7587031851) | [![Google](https://avatars.githubusercontent.com/u/2810941?s=60&v=4)](https://app.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/7576989995) | [![DataDog](https://avatars.githubusercontent.com/u/365230?s=60&v=4)](https://app.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/7446169664) | [![Intel](https://avatars.githubusercontent.com/u/17888862?s=60&v=4)](https://app.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/7590975903) | [![Kubernetes](https://avatars.githubusercontent.com/u/36015203?s=60&v=4)](https://app.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/7591172950) | [![Node.js](https://avatars.githubusercontent.com/u/9950313?s=60&v=4)](https://app.stepsecurity.io/github/nodejs/node/actions/runs/7591405720) | [![AWS](https://avatars.githubusercontent.com/u/2232217?s=60&v=4)](https://app.stepsecurity.io/github/aws/aperf/actions/runs/7631366761) |
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| **CISA**<br>[Explore](https://app.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/6199340224) | **Microsoft**<br>[Explore](https://app.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/5559160177) | **Google**<br>[Explore](https://app.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/5546354505) | **DataDog**<br>[Explore](https://app.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/5387101451) | **Intel**<br>[Explore](https://app.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/5579910614) | **Kubernetes**<br>[Explore](https://app.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/5581511101) | **Node.js**<br>[Explore](https://app.stepsecurity.io/github/nodejs/node/actions/runs/5563468674) | **Mastercard**<br>[Explore](https://app.stepsecurity.io/github/Mastercard/flow/actions/runs/5542112873) |
## Hands-On Tutorials
You can use [GitHub Actions Goat](https://github.com/step-security/github-actions-goat) to try Harden-Runner. You only need a GitHub Account and a web browser.
Hands-on Tutorials for GitHub Actions Runtime Security:
1. [Filter Egress Network Traffic](https://github.com/step-security/github-actions-goat/blob/main/docs/Solutions/RestrictOutboundTraffic.md)
2. [Detect File Tampering](https://github.com/step-security/github-actions-goat/blob/main/docs/Solutions/MonitorSourceCode.md)
| **CISA**<br>[Explore](https://app.stepsecurity.io/github/cisagov/skeleton-generic/actions/runs/7588528684) | **Microsoft**<br>[Explore](https://app.stepsecurity.io/github/microsoft/ebpf-for-windows/actions/runs/7587031851) | **Google**<br>[Explore](https://app.stepsecurity.io/github/GoogleCloudPlatform/functions-framework-ruby/actions/runs/7576989995) | **DataDog**<br>[Explore](https://app.stepsecurity.io/github/DataDog/stratus-red-team/actions/runs/7446169664) | **Intel**<br>[Explore](https://app.stepsecurity.io/github/intel/cve-bin-tool/actions/runs/7590975903) | **Kubernetes**<br>[Explore](https://app.stepsecurity.io/github/kubernetes-sigs/cluster-api-provider-azure/actions/runs/7591172950) | **Node.js**<br>[Explore](https://app.stepsecurity.io/github/nodejs/node/actions/runs/7591405720) | **AWS**<br>[Explore](https://app.stepsecurity.io/github/aws/aperf/actions/runs/7631366761) |
## Why
Compromised workflows, dependencies, and build tools typically make outbound calls to exfiltrate credentials, or may tamper source code, dependencies, or artifacts during the build.
There are two main threats from compromised workflows, dependencies, and build tools in a CI/CD environment:
1. Exfiltration of CI/CD credentials and source code
2. Tampering of source code, dependencies, or artifacts during the build to inject a backdoor
Harden-Runner monitors process, file, and network activity to:
| | Countermeasure | Prevent Security Breach |
| --- | ----------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1. | Block egress traffic at the DNS (Layer 7) and network layers (Layers 3 and 4) to prevent exfiltration of code and CI/CD credentials | To prevent [Codecov breach](https://github.com/step-security/github-actions-goat/blob/main/docs/Vulnerabilities/ExfiltratingCICDSecrets.md) scenario |
| 2. | Detect if source code is being tampered during the build process to inject a backdoor | To detect [SolarWinds incident](https://github.com/step-security/github-actions-goat/blob/main/docs/Vulnerabilities/TamperingDuringBuild.md) scenario |
| 1. | Monitor and block outbound network traffic at the DNS, HTTPS (Layer 7), and network layers (Layers 3 and 4) to prevent exfiltration of code and CI/CD credentials | To prevent the [Codecov breach](https://github.com/step-security/github-actions-goat/blob/main/docs/Vulnerabilities/ExfiltratingCICDSecrets.md) scenario |
| 2. | Detect if source code is being tampered during the build process to inject a backdoor | To detect the [SolarWinds incident](https://github.com/step-security/github-actions-goat/blob/main/docs/Vulnerabilities/TamperingDuringBuild.md) scenario |
| 3. | Detect poisoned workflows and compromised dependencies | To detect [Dependency confusion](https://github.com/step-security/github-actions-goat/blob/main/docs/Vulnerabilities/ExfiltratingCICDSecrets.md#dependency-confusion-attacks) and [Malicious dependencies](https://github.com/step-security/github-actions-goat/blob/main/docs/Vulnerabilities/ExfiltratingCICDSecrets.md#compromised-dependencies) |
Read this [case study](https://infosecwriteups.com/detecting-malware-packages-in-github-actions-7b93a9985635) on how Harden-Runner detected malicious packages in the NPM registry.
@ -57,11 +50,11 @@ Read this [case study](https://infosecwriteups.com/detecting-malware-packages-in
### GitHub-Hosted Runners
1. Add `step-security/harden-runner` GitHub Action to your GitHub Actions workflow file as the first step in each job.
1. Add the `step-security/harden-runner` GitHub Action to your GitHub Actions workflow file as the first step in each job.
```yaml
steps:
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
- uses: step-security/harden-runner@63c24ba6bd7ba022e95695ff85de572c04a18142 # v2.7.0
with:
egress-policy: audit
```
@ -72,51 +65,60 @@ Read this [case study](https://infosecwriteups.com/detecting-malware-packages-in
<img src="images/buildlog1.png" alt="Link in build log" >
</p>
3. Click on the link ([example link](https://app.stepsecurity.io/github/microsoft/msquic/actions/runs/5577342236)). You will see a process monitor view of network and file events correlated with each step of the job.
3. Click on the link ([example link](https://app.stepsecurity.io/github/step-security/github-actions-goat/actions/runs/7704454287)). You will see a process monitor view of network and file events correlated with each step of the job.
<p align="left">
<img src="images/insights-5.png" alt="Insights from harden-runner" >
<img src="images/network-events.png" alt="Insights from harden-runner" >
</p>
4. Under the insights section, you'll find a Recommended Policy. You can either update your workflow file with this Policy, or alternatively, use the [Policy Store](https://docs.stepsecurity.io/harden-runner/how-tos/block-egress-traffic#2-add-the-policy-using-the-policy-store) to apply the policy without modifying the workflow file.
4. In the `Recommended Policy` tab, you'll find a recommended block policy based on outbound calls aggregated from the current and past runs of the job. You can update your workflow file with this policy, or alternatively, use the [Policy Store](https://docs.stepsecurity.io/harden-runner/how-tos/block-egress-traffic#2-add-the-policy-using-the-policy-store) to apply the policy without modifying the workflow file. From now on, any outbound calls not in the allowed list will be blocked.
<p align="left">
<img src="images/rec-policy1.png" alt="Policy recommended by harden-runner" >
<img src="images/recommended-policy.png" alt="Policy recommended by harden-runner" >
</p>
## Hands-On Tutorials
You can use [GitHub Actions Goat](https://github.com/step-security/github-actions-goat) to try Harden-Runner. You only need a GitHub Account and a web browser.
Hands-on Tutorials for GitHub Actions Runtime Security:
1. [Filter Egress Network Traffic](https://github.com/step-security/github-actions-goat/blob/main/docs/Solutions/RestrictOutboundTraffic.md)
2. [Detect File Tampering](https://github.com/step-security/github-actions-goat/blob/main/docs/Solutions/MonitorSourceCode.md)
## Support for Self-Hosted Runners and Private Repositories
Hardening for self-hosted runners and GitHub-hosted runners used in private repositories is supported with a commercial license. Check out the [documentation](https://docs.stepsecurity.io/stepsecurity-platform/billing) for more details.
- To use Harden-Runner in a `Private` repository, you must install the [StepSecurity Actions Security GitHub App](https://github.com/apps/stepsecurity-actions-security).
- This is needed to access the GitHub Actions API and to authenticate users to access the insights URL for private repositories.
- If you use Harden-Runner GitHub Action in a private repository, the generated insights URL is NOT public. Only those who have access to the repository can view it.
Read this [case study on how Kapiche uses Harden-Runner](https://www.stepsecurity.io/case-studies/kapiche/) to improve software supply chain security in their private repositories.
### Self-Hosted Actions Runner Controller (ARC) Runners
> Explore demo workflows using self-hosted ARC Runner and ARC Harden-Runner [here](https://docs.stepsecurity.io/harden-runner/how-tos/enable-runtime-security-arc).
Actions Runner Controller (ARC) is a Kubernetes operator that orchestrates and scales self-hosted runners for GitHub Actions.
Actions Runner Controller (ARC) is a Kubernetes operator that orchestrates self-hosted runners for GitHub Actions.
- Instead of adding the Harden-Runner GitHub Action in each workflow, you'll need to install the ARC Harden-Runner daemonset on your Kubernetes cluster.
- Upon installation, the ARC Harden-Runner daemonset constantly monitors each workflow run; you do NOT need to add the Harden-Runner GitHub Action to each job for `audit` mode. You do need to add the Harden-Runner GitHub Action for `block` mode.
- You can access security insights and runtime detections under the `Runtime Security` tab in your dashboard.
- Instead of adding the Harden-Runner GitHub Action in each job, you'll need to install the ARC Harden-Runner daemonset on your Kubernetes cluster.
- Upon installation, the ARC Harden-Runner daemonset monitors all jobs run on the cluster; you do NOT need to add the Harden-Runner GitHub Action to each job for `audit` mode. You do need to add the Harden-Runner GitHub Action to jobs where you want to enable `block` mode.
- Please email support@stepsecurity.io for instructions on how to install the ARC-Harden-Runner daemonset on your Kubernetes cluster.
### Self-Hosted VM Runners (e.g. on EC2)
> Explore demo workflows using self-hosted VM Runners and Harden-Runner [here](https://docs.stepsecurity.io/harden-runner/how-tos/enable-runtime-security-vm).
- Instead of adding the Harden-Runner GitHub Action in each workflow, you'll need to install the Harden-Runner agent on your runner image (e.g. AMI). This is typically done using packer.
- The Harden-Runner agent monitors each job run on the VM, both ephemeral and persistent runners are supported; you do NOT need to add the Harden-Runner GitHub Action to each job for `audit` mode. You do need to add the Harden-Runner GitHub Action for `block` mode.
- You can access security insights and runtime detections under the `Runtime Security` tab in your dashboard.
## Support for Self-Hosted Runners and Private Repositories
Runtime security for self-hosted runners and private repositories are supported with a commercial license. Check out the [documentation](https://docs.stepsecurity.io/stepsecurity-platform/billing) for more details.
- Install the [StepSecurity Actions Security GitHub App](https://github.com/apps/stepsecurity-actions-security) to use Harden-Runner GitHub Action for `Private` repositories.
- If you use Harden-Runner GitHub Action in a private repository, the generated insights URL is NOT public.
- You need to authenticate first to access insights URL for private repository. Only those who have access to the repository can view it.
Read this [case study on how Kapiche uses Harden-Runner](https://www.stepsecurity.io/case-studies/kapiche/) to improve software supply chain security in their private repositories.
- Instead of adding the Harden-Runner GitHub Action in each job, you'll need to install the Harden-Runner agent on your runner image (e.g. AMI). This is typically done using packer or as a post-install step when using the https://github.com/philips-labs/terraform-aws-github-runner project to setup runners.
- The Harden-Runner agent monitors all jobs run on the VM, both ephemeral and persistent runners are supported; you do NOT need to add the Harden-Runner GitHub Action to each job for `audit` mode. You do need to add the Harden-Runner GitHub Action to jobs where you want to enable `block` mode.
- Please email support@stepsecurity.io for instructions on how to install the Harden-Runner agent on your self-hosted VM runners. This agent is different than the one used for GitHub-hosted runners.
## Features at a glance
For details, check out the documentation at https://docs.stepsecurity.io
### 👀 Monitor egress traffic
### 📶 View outbound network traffic
> Applies to both GitHub-hosted and self-hosted runners
@ -124,9 +126,33 @@ Harden-Runner monitors all outbound traffic from each job at the DNS and network
- After the workflow completes, each outbound call is correlated with each step of the job, and shown in the insights page
- For self-hosted runners, no changes are needed to workflow files to monitor egress traffic
- A filtering (block) egress policy is suggested in the insights page based on past job runs
- A filtering (block) egress policy is suggested in the insights page based on the current and past job runs
### 🚦 Filter egress traffic to allowed endpoints
### 🌐 View outbound HTTPS traffic
> Applies to GitHub-hosted and self-hosted VM runners
Harden-Runner can monitor outbound HTTPS requests. This feature is supported with a commercial license.
- HTTPS events are monitored using eBPF (no MITM proxy is used)
- If a HTTP PUT/ POST/ PATCH call is made to `github.com` or `api.github.com` hosts to a HTTP Path with a different organization than where the workflow is running, the call is marked as anomalous
- As of now, only HTTPS calls to `github.com` and `api.github.com` hosts are monitoried.
<p align="left">
<img src="images/https-events.png" alt="Policy recommended by harden-runner" >
</p>
### ⚠️ Detect anomalous outbound network traffic
> Applies to both GitHub-hosted and self-hosted runners
Harden-Runner creates a baseline of outbound traffic for each job during the first few runs that it monitors
- After the baseline is created, any new outbound destinations are marked as anomalous in the insights page
- You can view the list of all anomalous outbound network traffic in the `Runtime detections` page on the dashboard
### 🚦 Filter outbound network traffic to allowed endpoints
> Applies to both GitHub-hosted and self-hosted runners
@ -137,7 +163,7 @@ Once allowed endpoints are set in the policy in the workflow file, or in the [Po
- Wildcard domains are supported, e.g. you can add `*.data.mcr.microsoft.com:443` to the allowed list, and egress traffic will be allowed to `eastus.data.mcr.microsoft.com:443` and `westus.data.mcr.microsoft.com:443`
<p align="left">
<img src="images/blocked-outbound-call-2.png" alt="Policy recommended by harden-runner" >
<img src="images/blocked-outbound-call-3.png" alt="Policy recommended by harden-runner" >
</p>
### 📁 Detect tampering of source code during build
@ -152,7 +178,7 @@ Harden-Runner monitors file writes and can detect if a file is overwritten.
- For self-hosted runners, no changes are needed to workflow files for file monitoring
<p align="left">
<img src="images/file-overwritten.png" alt="Policy recommended by harden-runner" >
<img src="images/file-events.png" alt="Policy recommended by harden-runner" >
</p>
### 🚫 Run your job without sudo access

View file

@ -33,7 +33,7 @@ branding:
icon: "check-square"
color: "green"
runs:
using: "node16"
using: "node20"
pre: "dist/pre/index.js"
main: "dist/index.js"
post: "dist/post/index.js"

7188
dist/pre/index.js vendored

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
images/file-events.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
images/https-events.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

BIN
images/main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

BIN
images/network-events.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

View file

@ -1,5 +1,9 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
export default {
preset: 'ts-jest',
testEnvironment: 'node',
preset: "ts-jest",
testEnvironment: "node",
reporters: [
"default",
["jest-junit", { outputDirectory: "reports", outputName: "report.xml" }],
],
};

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "step-security-harden-runner",
"version": "2.6.1",
"version": "2.7.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "step-security-harden-runner",
"version": "2.6.1",
"version": "2.7.0",
"license": "Apache License 2.0",
"dependencies": {
"@actions/cache": "^3.1.4",

View file

@ -1,6 +1,6 @@
{
"name": "step-security-harden-runner",
"version": "2.6.1",
"version": "2.7.0",
"description": "Security agent for GitHub-hosted runner: block egress traffic & detect code overwrite to prevent breaches",
"main": "index.js",
"scripts": {

View file

@ -2,16 +2,21 @@ import * as core from "@actions/core";
import * as crypto from "crypto";
import * as fs from "fs";
export function verifyChecksum(downloadPath: string) {
export function verifyChecksum(downloadPath: string, is_tls: boolean) {
const fileBuffer: Buffer = fs.readFileSync(downloadPath);
const checksum: string = crypto
.createHash("sha256")
.update(fileBuffer)
.digest("hex"); // checksum of downloaded file
const expectedChecksum: string =
let expectedChecksum: string =
"ceb925c78e5c79af4f344f08f59bbdcf3376d20d15930a315f9b24b6c4d0328a"; // checksum for v0.13.5
if (is_tls) {
expectedChecksum =
"204c82116e8c0eebf5409bb2b81aa5d96fe32f0c5abc1cb0364ee70937c32056"; // checksum for tls_agent
}
if (checksum !== expectedChecksum) {
core.setFailed(
`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`

5
src/configs.ts Normal file
View file

@ -0,0 +1,5 @@
export const STEPSECURITY_ENV = "agent"; // agent or int
export const STEPSECURITY_API_URL = `https://${STEPSECURITY_ENV}.api.stepsecurity.io/v1`;
export const STEPSECURITY_WEB_URL = "https://app.stepsecurity.io";

View file

@ -9,6 +9,7 @@ export interface Configuration {
disable_telemetry: boolean;
disable_sudo: boolean;
disable_file_monitoring: boolean;
is_github_hosted: boolean;
private: string;
}

View file

@ -1,6 +1,7 @@
import nock from "nock";
import { API_ENDPOINT, fetchPolicy, mergeConfigs } from "./policy-utils";
import { fetchPolicy, mergeConfigs } from "./policy-utils";
import { Configuration, PolicyResponse } from "./interfaces";
import { STEPSECURITY_API_URL } from "./configs";
test("success: fetching policy", async () => {
let owner = "h0x0er";
@ -14,7 +15,7 @@ test("success: fetching policy", async () => {
disable_sudo: false,
disable_file_monitoring: false,
};
const policyScope = nock(`${API_ENDPOINT}`)
const policyScope = nock(`${STEPSECURITY_API_URL}`)
.get(`/github/${owner}/actions/policies/${policyName}`)
.reply(200, response);
@ -37,6 +38,7 @@ test("merge configs", async () => {
disable_sudo: false,
disable_file_monitoring: false,
private: "true",
is_github_hosted: true,
};
let policyResponse: PolicyResponse = {
owner: "h0x0er",
@ -60,6 +62,7 @@ test("merge configs", async () => {
disable_sudo: false,
disable_file_monitoring: false,
private: "true",
is_github_hosted: true,
};
localConfig = mergeConfigs(localConfig, policyResponse);

View file

@ -1,19 +1,17 @@
import { HttpClient } from "@actions/http-client";
import { PolicyResponse, Configuration } from "./interfaces";
export const API_ENDPOINT = "https://agent.api.stepsecurity.io/v1";
import { STEPSECURITY_API_URL } from "./configs";
export async function fetchPolicy(
owner: string,
policyName: string,
idToken: string
): Promise<PolicyResponse> {
if (idToken === "") {
throw new Error("[PolicyFetch]: id-token in empty");
}
let policyEndpoint = `${API_ENDPOINT}/github/${owner}/actions/policies/${policyName}`;
let policyEndpoint = `${STEPSECURITY_API_URL}/github/${owner}/actions/policies/${policyName}`;
let httpClient = new HttpClient();
@ -25,24 +23,24 @@ export async function fetchPolicy(
let err = undefined;
let retry = 0;
while(retry < 3){
try{
console.log(`Attempt: ${retry+1}`)
while (retry < 3) {
try {
console.log(`Attempt: ${retry + 1}`);
response = await httpClient.getJson<PolicyResponse>(
policyEndpoint,
headers
);
break;
}catch(e){
err = e
} catch (e) {
err = e;
}
retry += 1
retry += 1;
await sleep(1000);
}
if(response === undefined && err !== undefined){
throw new Error(`[Policy Fetch] ${err}`)
}else{
if (response === undefined && err !== undefined) {
throw new Error(`[Policy Fetch] ${err}`);
} else {
return response.result;
}
}

View file

@ -23,6 +23,8 @@ import * as cache from "@actions/cache";
import { getCacheEntry } from "@actions/cache/lib/internal/cacheHttpClient";
import * as utils from "@actions/cache/lib/internal/cacheUtils";
import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
import { STEPSECURITY_API_URL, STEPSECURITY_WEB_URL } from "./configs";
import { isGithubHosted, isTLSEnabled } from "./tls-inspect";
(async () => {
try {
@ -52,6 +54,7 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
disable_sudo: core.getBooleanInput("disable-sudo"),
disable_file_monitoring: core.getBooleanInput("disable-file-monitoring"),
private: context?.payload?.repository?.private || false,
is_github_hosted: isGithubHosted(),
};
let policyName = core.getInput("policy");
@ -143,7 +146,7 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
const runnerName = process.env.RUNNER_NAME || "";
core.info(`RUNNER_NAME: ${runnerName}`);
if (!runnerName.startsWith("GitHub Actions")) {
if (!isGithubHosted()) {
fs.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${EOL}`, {
encoding: "utf8",
});
@ -199,13 +202,28 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
let token = core.getInput("token");
let auth = `token ${token}`;
const downloadPath: string = await tc.downloadTool(
`https://step-security-agent.s3.us-west-2.amazonaws.com/refs/heads/${env}/agent`
);
let downloadPath: string;
if (await isTLSEnabled(context.repo.owner)) {
downloadPath = await tc.downloadTool(
"https://packages.stepsecurity.io/github-hosted/harden-runner_1.1.0_linux_amd64.tar.gz"
);
verifyChecksum(downloadPath, true); // NOTE: verifying tls_agent's checksum, before extracting
} else {
downloadPath = await tc.downloadTool(
`https://step-security-agent.s3.us-west-2.amazonaws.com/refs/heads/${env}/agent`
);
//verifyChecksum(downloadPath, false); // NOTE: verifying agent's checksum, before extracting
}
const extractPath = await tc.extractTar(downloadPath);
let cmd = "cp",
args = [downloadPath, "/home/agent/agent"];
args = [path.join(extractPath, "agent"), "/home/agent/agent"];
cp.execFileSync(cmd, args);
cp.execSync("chmod +x /home/agent/agent");
fs.writeFileSync("/home/agent/agent.json", confgStr);
@ -247,6 +265,8 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
} catch (error) {
core.setFailed(error.message);
}
// see https://github.com/ruby/setup-ruby/issues/543
process.exit(0);
})();
export function sleep(ms) {

29
src/tls-inspect.test.ts Normal file
View file

@ -0,0 +1,29 @@
import nock from "nock";
import { STEPSECURITY_API_URL } from "./configs";
import { isTLSEnabled } from "./tls-inspect";
test("tls-inspect enabled", async () => {
let owner = "h0x0er";
let expected = true;
const resp = nock(`${STEPSECURITY_API_URL}`)
.get(`/github/${owner}/actions/tls-inspection-status`)
.reply(200, "");
let got = await isTLSEnabled(owner);
expect(got).toEqual(expected);
});
test("tls-inspect not enabled", async () => {
let owner = "step-security";
let expected = false;
const resp = nock(`${STEPSECURITY_API_URL}`)
.get(`/github/${owner}/actions/tls-inspection-status`)
.reply(401, "");
let got = await isTLSEnabled(owner);
expect(got).toEqual(expected);
});

29
src/tls-inspect.ts Normal file
View file

@ -0,0 +1,29 @@
import { HttpClient } from "@actions/http-client";
import { STEPSECURITY_API_URL } from "./configs";
import * as core from "@actions/core";
export async function isTLSEnabled(owner: string): Promise<boolean> {
let tlsStatusEndpoint = `${STEPSECURITY_API_URL}/github/${owner}/actions/tls-inspection-status`;
let httpClient = new HttpClient();
httpClient.requestOptions = { socketTimeout: 3 * 1000 };
core.info(`[!] Checking TLS_STATUS: ${owner}`);
let isEnabled = false;
try {
let resp = await httpClient.get(tlsStatusEndpoint);
if (resp.message.statusCode === 200) {
isEnabled = true;
core.info(`[!] TLS_ENABLED: ${owner}`);
} else {
core.info(`[!] TLS_NOT_ENABLED: ${owner}`);
}
} catch (e) {
core.info(`[!] Unable to check TLS_STATUS`);
}
return isEnabled;
}
export function isGithubHosted() {
const runnerName = process.env.RUNNER_NAME || "";
return runnerName.startsWith("GitHub Actions");
}