Compare commits

...
20 Commits
Author SHA1 Message Date
Varun Sharma bb112d061b Update isGitHubHosted implementation 2024-06-04 16:59:55 -07:00
Varun Sharma f4f3f445f3 Merge pull request #407 from step-security/dependabot/github_actions/actions/dependency-review-action-4.3.2
Bump actions/dependency-review-action from 3.1.3 to 4.3.2
2024-05-22 21:30:51 -07:00
dependabot[bot] 7a946b57df Bump actions/dependency-review-action from 3.1.3 to 4.3.2
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 3.1.3 to 4.3.2.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](https://github.com/actions/dependency-review-action/compare/7bbfa034e752445ea40215fff1c3bf9597993d3f...0c155c5e8556a497adf53f2c18edabf945ed8e70)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-23 04:24:37 +00:00
Varun Sharma 75a01c2f00 Merge pull request #417 from step-security/dependabot/github_actions/step-security/harden-runner-2.8.0
Bump step-security/harden-runner from 2.7.1 to 2.8.0
2024-05-22 21:23:53 -07:00
dependabot[bot] 53413f1a91 Bump step-security/harden-runner from 2.7.1 to 2.8.0
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.7.1 to 2.8.0.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/a4aa98b93cab29d9b1101a6143fb8bce00e2eac4...f086349bfa2bd1361f7909c78558e816508cdc10)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-22 23:38:54 +00:00
Varun Sharma f086349bfa Merge pull request #416 from step-security/rc-8
Release 2.8.0
2024-05-21 17:40:44 -07:00
Varun Sharma b9c325d8ce Update image 2024-05-21 16:52:18 -07:00
Varun Sharma 808a771f66 Add info about file and process events 2024-05-21 16:48:23 -07:00
Varun Sharma 71714298b4 Update agent 2024-05-20 23:43:04 -07:00
Varun Sharma 9ff9d14760 Merge pull request #406 from step-security/dependabot/github_actions/step-security/harden-runner-2.7.1
Bump step-security/harden-runner from 2.7.0 to 2.7.1
2024-04-29 22:11:17 -07:00
dependabot[bot] ac5fa0194e Bump step-security/harden-runner from 2.7.0 to 2.7.1
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.7.0 to 2.7.1.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/63c24ba6bd7ba022e95695ff85de572c04a18142...a4aa98b93cab29d9b1101a6143fb8bce00e2eac4)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 23:28:16 +00:00
Varun Sharma a4aa98b93c Release v2.7.1 (#397) 2024-04-29 13:53:33 -07:00
Varun Sharma 6c3b1c91e8 Merge pull request #379 from step-security/dependabot/github_actions/step-security/harden-runner-2.7.0
Bump step-security/harden-runner from 2.6.1 to 2.7.0
2024-01-31 16:09:18 -08:00
dependabot[bot] 3498091f2b Bump step-security/harden-runner from 2.6.1 to 2.7.0
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.6.1 to 2.7.0.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](https://github.com/step-security/harden-runner/compare/eb238b55efaa70779f274895e782ed17c84f2895...63c24ba6bd7ba022e95695ff85de572c04a18142)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-31 23:16:23 +00:00
Varun Sharma 63a88e2cd7 Merge pull request #378 from step-security/update-readme3
Update README
2024-01-30 16:41:10 -08:00
Varun Sharma 07e5965e5b Update README 2024-01-30 16:21:51 -08:00
Varun Sharma 63c24ba6bd Merge pull request #376 from step-security/rc-7
Release 2.7.0
2024-01-30 12:51:16 -08:00
Varun Sharma 95691d3d1c Update dist 2024-01-29 12:41:26 -08:00
Varun Sharma 6339621ce7 Update to node20 2024-01-29 12:13:17 -08:00
jatin 4a63cdab74 Add tls-inspection capability (#368) 2024-01-29 12:06:18 -08:00
42 changed files with 382 additions and 102 deletions
+7 -1
View File
@@ -22,7 +22,7 @@ jobs:
permissions:
contents: write
steps:
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v1
- uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # 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
+1 -1
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@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
disable-sudo: true
egress-policy: block
+1 -1
View File
@@ -41,7 +41,7 @@ jobs:
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10
with:
egress-policy: audit # TODO: change to 'egress-policy: block' after couple of runs
+2 -2
View File
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
egress-policy: audit
- name: 'Checkout Repository'
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: 'Dependency Review'
uses: actions/dependency-review-action@7bbfa034e752445ea40215fff1c3bf9597993d3f # v3.1.3
uses: actions/dependency-review-action@0c155c5e8556a497adf53f2c18edabf945ed8e70 # v4.3.2
+16 -1
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@f086349bfa2bd1361f7909c78558e816508cdc10
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@f086349bfa2bd1361f7909c78558e816508cdc10
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
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
permissions:
contents: write
steps:
- uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895
- uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10
with:
egress-policy: audit
allowed-endpoints:
+1 -1
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@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
egress-policy: audit
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@eb238b55efaa70779f274895e782ed17c84f2895 # v2.6.1
uses: step-security/harden-runner@f086349bfa2bd1361f7909c78558e816508cdc10 # v2.8.0
with:
disable-sudo: true
egress-policy: audit
+70 -30
View File
@@ -17,42 +17,30 @@
Harden-Runner provides network egress filtering and runtime security for GitHub-hosted and self-hosted runners.
For self-hosted environments, Harden-Runner supports:
Learn how Harden-Runner works through the video below, which shows how it detected a supply chain attack on a Google open-source project.
1. Kubernetes runners setup using Actions Runner Controller (ARC)
2. Virtual Machine runners (e.g. on EC2) - both ephemeral and persistent runners are supported
<a href="https://youtu.be/Yz72qAOrN9s" target="_blank"><img src="images/case-study-thumbnail1.png" alt="Harden-Runner detected supply chain attack in a Google open-source project" title="This case study video shows how StepSecurity Harden-Runner detected a CI/CD supply chain attack in real-time in Google’s open-source project Flank"></a>
[![Harden Runner Demo](images/RuntimeSecurityDemo.gif)](https://youtu.be/fpdwX5hYACo)
## 3,000+ open source projects use Harden-Runner
## 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/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) | [![Mastercard](https://avatars.githubusercontent.com/u/1653148?s=60&v=4)](https://app.stepsecurity.io/github/Mastercard/flow/actions/runs/7539664931) |
| [![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/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) | **Mastercard**<br>[Explore](https://app.stepsecurity.io/github/Mastercard/flow/actions/runs/7539664931) |
## 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. | Detect anomalous traffic and 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 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 |
| 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 [XZ Utils](https://www.stepsecurity.io/blog/analysis-of-backdoored-xz-utils-build-process-with-harden-runner) and [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.
## How
### GitHub-Hosted Runners
@@ -61,7 +49,7 @@ Read this [case study](https://infosecwriteups.com/detecting-malware-packages-in
```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,18 +60,27 @@ 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/7588119198)). 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.png" alt="Insights from harden-runner" >
<img src="images/network-events1.png" alt="Insights from harden-runner" >
</p>
4. Under the process monitor view, 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.
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-policy.png" alt="Policy recommended by harden-runner" >
<img src="images/recommended-policy1.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.
@@ -116,7 +113,7 @@ Actions Runner Controller (ARC) is a Kubernetes operator that orchestrates self-
For details, check out the documentation at https://docs.stepsecurity.io
### 👀 View outbound network traffic
### 📶 View outbound network traffic
> Applies to both GitHub-hosted and self-hosted runners
@@ -126,6 +123,20 @@ Harden-Runner monitors all outbound traffic from each job at the DNS and network
- 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 the current and past job runs
### 🌐 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
@@ -135,6 +146,7 @@ Harden-Runner creates a baseline of outbound traffic for each job during the fir
- 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
@@ -146,7 +158,35 @@ 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>
### 📋 View the name and path of every file written during the build process
> Applies to both GitHub-hosted and self-hosted runners
View the name and path of every file that was written during the build process. This feature is supported with a commercial license.
- Harden-Runner tracks every file written to the GitHub Actions working directory during the build process.
- In the insights page in the `File Write Events` tab you can see a file explorer view of each file that was written to.
- Clicking on any file reveals a list of processes that wrote to it, providing complete transparency.
<p align="left">
<img src="images/file-write-events.png" alt="View the name and path of every file written during the build process" >
</p>
### 🔄 View process names and arguments
> Applies to both GitHub-hosted and self-hosted runners
View process names, PIDs, and process arguments. This feature is supported with a commercial license.
- Harden-Runner tracks every process that is run during the build process.
- Clicking on any file reveals a list of processes that wrote to it.
- You can walk up the process tree and view process arguments to understand the build process and detect suspicious activity.
<p align="left">
<img src="images/process-events-3.png" alt="View process names and arguments" >
</p>
### 📁 Detect tampering of source code during build
@@ -161,7 +201,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
+1 -1
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"
+10 -3
View File
@@ -2836,6 +2836,11 @@ __nccwpck_require__.r(__webpack_exports__);
var lib_core = __nccwpck_require__(186);
// EXTERNAL MODULE: external "fs"
var external_fs_ = __nccwpck_require__(747);
;// CONCATENATED MODULE: ./src/configs.ts
const STEPSECURITY_ENV = "agent"; // agent or int
const STEPSECURITY_API_URL = `https://${STEPSECURITY_ENV}.api.stepsecurity.io/v1`;
const configs_STEPSECURITY_WEB_URL = "https://app.stepsecurity.io";
;// CONCATENATED MODULE: ./src/common.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -2848,6 +2853,7 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
};
function printInfo(web_url) {
console.log("\x1b[32m%s\x1b[0m", "View security insights and recommended policy at:");
console.log(`${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`);
@@ -2872,10 +2878,10 @@ const processLogLine = (line, tableEntries) => {
};
function addSummary() {
return __awaiter(this, void 0, void 0, function* () {
if (process.env.STATE_monitorStatusCode !== "200") {
if (process.env.STATE_addSummary !== "true") {
return;
}
const web_url = "https://app.stepsecurity.io";
const web_url = STEPSECURITY_WEB_URL;
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
const log = "/home/agent/agent.log";
if (!fs.existsSync(log)) {
@@ -3015,6 +3021,7 @@ var src_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argu
(() => src_awaiter(void 0, void 0, void 0, function* () {
if (process.platform !== "linux") {
console.log(UBUNTU_MESSAGE);
@@ -3034,7 +3041,7 @@ var src_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argu
console.log("Telemetry will not be sent to StepSecurity API as disable-telemetry is set to true");
}
else {
var web_url = "https://app.stepsecurity.io";
var web_url = configs_STEPSECURITY_WEB_URL;
printInfo(web_url);
}
}))();
+1 -1
View File
File diff suppressed because one or more lines are too long
+17 -5
View File
@@ -139,7 +139,7 @@ const command_1 = __nccwpck_require__(351);
const file_command_1 = __nccwpck_require__(717);
const utils_1 = __nccwpck_require__(278);
const os = __importStar(__nccwpck_require__(87));
const path = __importStar(__nccwpck_require__(622));
const path = __importStar(__nccwpck_require__(277));
const oidc_utils_1 = __nccwpck_require__(41);
/**
* The code to exit an action
@@ -618,7 +618,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.toPlatformPath = exports.toWin32Path = exports.toPosixPath = void 0;
const path = __importStar(__nccwpck_require__(622));
const path = __importStar(__nccwpck_require__(277));
/**
* toPosixPath converts the given path to the posix form. On Windows, \\ will be
* replaced with /.
@@ -2752,7 +2752,7 @@ module.exports = require("os");
/***/ }),
/***/ 622:
/***/ 277:
/***/ ((module) => {
"use strict";
@@ -2838,6 +2838,11 @@ var external_fs_ = __nccwpck_require__(747);
const external_child_process_namespaceObject = require("child_process");
// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js
var core = __nccwpck_require__(186);
;// CONCATENATED MODULE: ./src/configs.ts
const STEPSECURITY_ENV = "agent"; // agent or int
const STEPSECURITY_API_URL = `https://${STEPSECURITY_ENV}.api.stepsecurity.io/v1`;
const STEPSECURITY_WEB_URL = "https://app.stepsecurity.io";
;// CONCATENATED MODULE: ./src/common.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -2850,6 +2855,7 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
};
function printInfo(web_url) {
console.log("\x1b[32m%s\x1b[0m", "View security insights and recommended policy at:");
console.log(`${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`);
@@ -2874,10 +2880,10 @@ const processLogLine = (line, tableEntries) => {
};
function addSummary() {
return __awaiter(this, void 0, void 0, function* () {
if (process.env.STATE_monitorStatusCode !== "200") {
if (process.env.STATE_addSummary !== "true") {
return;
}
const web_url = "https://app.stepsecurity.io";
const web_url = STEPSECURITY_WEB_URL;
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
const log = "/home/agent/agent.log";
if (!external_fs_.existsSync(log)) {
@@ -3109,6 +3115,12 @@ var cleanup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _
var content = external_fs_.readFileSync(log, "utf-8");
console.log(content);
}
const daemonLog = "/home/agent/daemon.log";
if (external_fs_.existsSync(daemonLog)) {
console.log("daemonLog:");
var content = external_fs_.readFileSync(daemonLog, "utf-8");
console.log(content);
}
var status = "/home/agent/agent.status";
if (external_fs_.existsSync(status)) {
console.log("status:");
+1 -1
View File
File diff suppressed because one or more lines are too long
+90 -14
View File
@@ -71246,6 +71246,11 @@ const validate = dist.validate;
const stringify = dist.stringify;
const parse = dist.parse;
;// CONCATENATED MODULE: ./src/configs.ts
const STEPSECURITY_ENV = "agent"; // agent or int
const STEPSECURITY_API_URL = `https://${STEPSECURITY_ENV}.api.stepsecurity.io/v1`;
const configs_STEPSECURITY_WEB_URL = "https://app.stepsecurity.io";
;// CONCATENATED MODULE: ./src/common.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -71258,6 +71263,7 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
};
function printInfo(web_url) {
console.log("\x1b[32m%s\x1b[0m", "View security insights and recommended policy at:");
console.log(`${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`);
@@ -71282,10 +71288,10 @@ const processLogLine = (line, tableEntries) => {
};
function addSummary() {
return __awaiter(this, void 0, void 0, function* () {
if (process.env.STATE_monitorStatusCode !== "200") {
if (process.env.STATE_addSummary !== "true") {
return;
}
const web_url = "https://app.stepsecurity.io";
const web_url = STEPSECURITY_WEB_URL;
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
const log = "/home/agent/agent.log";
if (!fs.existsSync(log)) {
@@ -71387,12 +71393,16 @@ var external_crypto_ = __nccwpck_require__(6417);
function verifyChecksum(downloadPath) {
function verifyChecksum(downloadPath, is_tls) {
const fileBuffer = external_fs_.readFileSync(downloadPath);
const checksum = external_crypto_.createHash("sha256")
.update(fileBuffer)
.digest("hex"); // checksum of downloaded file
const expectedChecksum = "ceb925c78e5c79af4f344f08f59bbdcf3376d20d15930a315f9b24b6c4d0328a"; // checksum for v0.13.5
let expectedChecksum = "ceb925c78e5c79af4f344f08f59bbdcf3376d20d15930a315f9b24b6c4d0328a"; // checksum for v0.13.5
if (is_tls) {
expectedChecksum =
"846ae66c6cfab958fe61736cec0b58bdb7651b36af04c279405c7114675d7033"; // checksum for tls_agent
}
if (checksum !== expectedChecksum) {
lib_core.setFailed(`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`);
}
@@ -71464,13 +71474,13 @@ var policy_utils_awaiter = (undefined && undefined.__awaiter) || function (thisA
});
};
const API_ENDPOINT = "https://agent.api.stepsecurity.io/v1";
function fetchPolicy(owner, policyName, idToken) {
return policy_utils_awaiter(this, void 0, void 0, function* () {
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 lib.HttpClient();
let headers = {};
headers["Authorization"] = `Bearer ${idToken}`;
@@ -71573,6 +71583,47 @@ function arcCleanUp() {
cp.execSync(`echo "cleanup" > "${getRunnerTempDir()}/step_policy_cleanup"`);
}
;// CONCATENATED MODULE: ./src/tls-inspect.ts
var tls_inspect_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
function isTLSEnabled(owner) {
return tls_inspect_awaiter(this, void 0, void 0, function* () {
let tlsStatusEndpoint = `${STEPSECURITY_API_URL}/github/${owner}/actions/tls-inspection-status`;
let httpClient = new lib.HttpClient();
httpClient.requestOptions = { socketTimeout: 3 * 1000 };
lib_core.info(`[!] Checking TLS_STATUS: ${owner}`);
let isEnabled = false;
try {
let resp = yield httpClient.get(tlsStatusEndpoint);
if (resp.message.statusCode === 200) {
isEnabled = true;
lib_core.info(`[!] TLS_ENABLED: ${owner}`);
}
else {
lib_core.info(`[!] TLS_NOT_ENABLED: ${owner}`);
}
}
catch (e) {
lib_core.info(`[!] Unable to check TLS_STATUS`);
}
return isEnabled;
});
}
function isGithubHosted() {
const runnerEnvironment = process.env.RUNNER_ENVIRONMENT || "";
return runnerEnvironment === "github-hosted";
}
;// CONCATENATED MODULE: ./src/setup.ts
var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
@@ -71601,6 +71652,8 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
(() => setup_awaiter(void 0, void 0, void 0, function* () {
var _a, _b;
try {
@@ -71613,9 +71666,8 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
return;
}
var correlation_id = v4();
var env = "agent";
var api_url = `https://${env}.api.stepsecurity.io/v1`;
var web_url = "https://app.stepsecurity.io";
var api_url = STEPSECURITY_API_URL;
var web_url = configs_STEPSECURITY_WEB_URL;
let confg = {
repo: process.env["GITHUB_REPOSITORY"],
run_id: process.env["GITHUB_RUN_ID"],
@@ -71628,6 +71680,8 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
disable_sudo: lib_core.getBooleanInput("disable-sudo"),
disable_file_monitoring: lib_core.getBooleanInput("disable-file-monitoring"),
private: ((_b = (_a = github.context === null || github.context === void 0 ? void 0 : github.context.payload) === null || _a === void 0 ? void 0 : _a.repository) === null || _b === void 0 ? void 0 : _b.private) || false,
is_github_hosted: isGithubHosted(),
is_debug: lib_core.isDebug(),
};
let policyName = lib_core.getInput("policy");
if (policyName !== "") {
@@ -71696,7 +71750,7 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
}
const runnerName = process.env.RUNNER_NAME || "";
lib_core.info(`RUNNER_NAME: ${runnerName}`);
if (!runnerName.startsWith("GitHub Actions")) {
if (!isGithubHosted()) {
external_fs_.appendFileSync(process.env.GITHUB_STATE, `selfHosted=true${external_os_.EOL}`, {
encoding: "utf8",
});
@@ -71722,16 +71776,29 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
let _http = new lib.HttpClient();
let statusCode;
_http.requestOptions = { socketTimeout: 3 * 1000 };
let addSummary = "false";
try {
const resp = yield _http.get(`${api_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}/monitor`);
statusCode = resp.message.statusCode; // adding error code to check whether agent is getting installed or not.
const monitorRequestData = {
correlation_id: correlation_id,
job: process.env["GITHUB_JOB"],
};
const resp = yield _http.postJson(`${api_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}/monitor`, monitorRequestData);
const responseData = resp.result;
statusCode = resp.statusCode; // adding error code to check whether agent is getting installed or not.
external_fs_.appendFileSync(process.env.GITHUB_STATE, `monitorStatusCode=${statusCode}${external_os_.EOL}`, {
encoding: "utf8",
});
if (statusCode === 200 && responseData) {
console.log(`Runner IP Address: ${responseData.runner_ip_address}`);
addSummary = responseData.monitoring_started ? "true" : "false";
}
}
catch (e) {
console.log(`error in connecting to ${api_url}: ${e}`);
}
external_fs_.appendFileSync(process.env.GITHUB_STATE, `addSummary=${addSummary}${external_os_.EOL}`, {
encoding: "utf8",
});
console.log(`Step Security Job Correlation ID: ${correlation_id}`);
if (String(statusCode) === STATUS_HARDEN_RUNNER_UNAVAILABLE) {
console.log(HARDEN_RUNNER_UNAVAILABLE_MESSAGE);
@@ -71743,8 +71810,15 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
// Note: to avoid github rate limiting
let token = lib_core.getInput("token");
let auth = `token ${token}`;
const downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz", undefined, auth);
verifyChecksum(downloadPath); // NOTE: verifying agent's checksum, before extracting
let downloadPath;
if (yield isTLSEnabled(github.context.repo.owner)) {
downloadPath = yield tool_cache.downloadTool("https://packages.stepsecurity.io/github-hosted/harden-runner_1.2.0_linux_amd64.tar.gz");
verifyChecksum(downloadPath, true); // NOTE: verifying tls_agent's checksum, before extracting
}
else {
downloadPath = yield tool_cache.downloadTool("https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz", undefined, auth);
verifyChecksum(downloadPath, false); // NOTE: verifying agent's checksum, before extracting
}
const extractPath = yield tool_cache.extractTar(downloadPath);
let cmd = "cp", args = [external_path_.join(extractPath, "agent"), "/home/agent/agent"];
external_child_process_.execFileSync(cmd, args);
@@ -71787,6 +71861,8 @@ var setup_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _ar
catch (error) {
lib_core.setFailed(error.message);
}
// see https://github.com/ruby/setup-ruby/issues/543
process.exit(0);
}))();
function setup_sleep(ms) {
return new Promise((resolve) => {
+1 -1
View File
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

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 99 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

+2 -2
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",
+1 -1
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": {
+7 -2
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 =
"846ae66c6cfab958fe61736cec0b58bdb7651b36af04c279405c7114675d7033"; // checksum for tls_agent
}
if (checksum !== expectedChecksum) {
core.setFailed(
`Checksum verification failed, expected ${expectedChecksum} instead got ${checksum}`
+7
View File
@@ -62,6 +62,13 @@ import { arcCleanUp, isArcRunner, removeStepPolicyFiles } from "./arc-runner";
console.log(content);
}
const daemonLog = "/home/agent/daemon.log";
if (fs.existsSync(daemonLog)) {
console.log("daemonLog:");
var content = fs.readFileSync(daemonLog, "utf-8");
console.log(content);
}
var status = "/home/agent/agent.status";
if (fs.existsSync(status)) {
console.log("status:");
+4 -3
View File
@@ -1,5 +1,6 @@
import * as core from "@actions/core";
import * as fs from "fs";
import { STEPSECURITY_WEB_URL } from "./configs";
export function printInfo(web_url) {
console.log(
@@ -47,11 +48,11 @@ export const processLogLine = (
};
export async function addSummary() {
if (process.env.STATE_monitorStatusCode !== "200") {
if (process.env.STATE_addSummary !== "true") {
return;
}
const web_url = "https://app.stepsecurity.io";
const web_url = STEPSECURITY_WEB_URL;
const insights_url = `${web_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}`;
const log = "/home/agent/agent.log";
@@ -172,4 +173,4 @@ export const HARDEN_RUNNER_UNAVAILABLE_MESSAGE =
"Sorry, we are currently experiencing issues with the Harden Runner installation process. It is currently unavailable.";
export const ARC_RUNNER_MESSAGE =
"Workflow is currently being executed in ARC based runner";
"Workflow is currently being executed in ARC based runner";
+5
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";
+2 -1
View File
@@ -1,6 +1,7 @@
import * as common from "./common";
import * as core from "@actions/core";
import isDocker from "is-docker";
import { STEPSECURITY_WEB_URL } from "./configs";
(async () => {
if (process.platform !== "linux") {
@@ -28,7 +29,7 @@ import isDocker from "is-docker";
"Telemetry will not be sent to StepSecurity API as disable-telemetry is set to true"
);
} else {
var web_url = "https://app.stepsecurity.io";
var web_url = STEPSECURITY_WEB_URL;
common.printInfo(web_url);
}
})();
+2
View File
@@ -9,7 +9,9 @@ export interface Configuration {
disable_telemetry: boolean;
disable_sudo: boolean;
disable_file_monitoring: boolean;
is_github_hosted: boolean;
private: string;
is_debug: boolean;
}
export interface PolicyResponse {
+7 -2
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,8 @@ test("merge configs", async () => {
disable_sudo: false,
disable_file_monitoring: false,
private: "true",
is_github_hosted: true,
is_debug: false,
};
let policyResponse: PolicyResponse = {
owner: "h0x0er",
@@ -60,6 +63,8 @@ test("merge configs", async () => {
disable_sudo: false,
disable_file_monitoring: false,
private: "true",
is_github_hosted: true,
is_debug: false,
};
localConfig = mergeConfigs(localConfig, policyResponse);
+11 -13
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;
}
}
+55 -13
View File
@@ -23,6 +23,13 @@ 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";
interface MonitorResponse {
runner_ip_address?: string;
monitoring_started?: boolean;
}
(async () => {
try {
@@ -36,9 +43,8 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
}
var correlation_id = uuidv4();
var env = "agent";
var api_url = `https://${env}.api.stepsecurity.io/v1`;
var web_url = "https://app.stepsecurity.io";
var api_url = STEPSECURITY_API_URL;
var web_url = STEPSECURITY_WEB_URL;
let confg: Configuration = {
repo: process.env["GITHUB_REPOSITORY"],
@@ -52,6 +58,8 @@ 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(),
is_debug: core.isDebug(),
};
let policyName = core.getInput("policy");
@@ -143,7 +151,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",
});
@@ -169,11 +177,19 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
let _http = new httpm.HttpClient();
let statusCode;
_http.requestOptions = { socketTimeout: 3 * 1000 };
let addSummary = "false";
try {
const resp: httpm.HttpClientResponse = await _http.get(
`${api_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}/monitor`
const monitorRequestData = {
correlation_id: correlation_id,
job: process.env["GITHUB_JOB"],
};
const resp = await _http.postJson<MonitorResponse>(
`${api_url}/github/${process.env["GITHUB_REPOSITORY"]}/actions/runs/${process.env["GITHUB_RUN_ID"]}/monitor`,
monitorRequestData
);
statusCode = resp.message.statusCode; // adding error code to check whether agent is getting installed or not.
const responseData = resp.result;
statusCode = resp.statusCode; // adding error code to check whether agent is getting installed or not.
fs.appendFileSync(
process.env.GITHUB_STATE,
`monitorStatusCode=${statusCode}${EOL}`,
@@ -181,9 +197,21 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
encoding: "utf8",
}
);
if (statusCode === 200 && responseData) {
console.log(`Runner IP Address: ${responseData.runner_ip_address}`);
addSummary = responseData.monitoring_started ? "true" : "false";
}
} catch (e) {
console.log(`error in connecting to ${api_url}: ${e}`);
}
fs.appendFileSync(
process.env.GITHUB_STATE,
`addSummary=${addSummary}${EOL}`,
{
encoding: "utf8",
}
);
console.log(`Step Security Job Correlation ID: ${correlation_id}`);
if (String(statusCode) === common.STATUS_HARDEN_RUNNER_UNAVAILABLE) {
@@ -199,18 +227,30 @@ import { isArcRunner, sendAllowedEndpoints } from "./arc-runner";
let token = core.getInput("token");
let auth = `token ${token}`;
const downloadPath: string = await tc.downloadTool(
"https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz",
undefined,
auth
);
let downloadPath: string;
if (await isTLSEnabled(context.repo.owner)) {
downloadPath = await tc.downloadTool(
"https://packages.stepsecurity.io/github-hosted/harden-runner_1.2.0_linux_amd64.tar.gz"
);
verifyChecksum(downloadPath, true); // NOTE: verifying tls_agent's checksum, before extracting
} else {
downloadPath = await tc.downloadTool(
"https://github.com/step-security/agent/releases/download/v0.13.5/agent_0.13.5_linux_amd64.tar.gz",
undefined,
auth
);
verifyChecksum(downloadPath, false); // NOTE: verifying agent's checksum, before extracting
}
verifyChecksum(downloadPath); // NOTE: verifying agent's checksum, before extracting
const extractPath = await tc.extractTar(downloadPath);
let cmd = "cp",
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);
@@ -252,6 +292,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
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
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 runnerEnvironment = process.env.RUNNER_ENVIRONMENT || "";
return runnerEnvironment === "github-hosted";
}