Compare commits
No commits in common. "91f3272fc5907f4699dcf59761eb622a07342f5a" and "3ca8a7c5359ac6ad91aa47f1946ece1c3b025004" have entirely different histories.
91f3272fc5
...
3ca8a7c535
|
|
@ -1,51 +0,0 @@
|
||||||
name: Trivy Security Scan
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
trivy-scan:
|
|
||||||
name: Trivy Security Scan
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
security-events: write
|
|
||||||
actions: read
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner in repo mode
|
|
||||||
uses: aquasecurity/trivy-action@0.33.1
|
|
||||||
with:
|
|
||||||
scan-type: 'fs'
|
|
||||||
scan-ref: '.'
|
|
||||||
scanners: 'vuln,secret,misconfig'
|
|
||||||
format: 'sarif'
|
|
||||||
output: 'trivy-results.sarif'
|
|
||||||
severity: 'CRITICAL,HIGH,MEDIUM'
|
|
||||||
|
|
||||||
- name: Upload Trivy results to GitHub Security tab
|
|
||||||
uses: github/codeql-action/upload-sarif@v3
|
|
||||||
if: always()
|
|
||||||
with:
|
|
||||||
sarif_file: 'trivy-results.sarif'
|
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner (table format)
|
|
||||||
uses: aquasecurity/trivy-action@0.33.1
|
|
||||||
with:
|
|
||||||
scan-type: 'fs'
|
|
||||||
scan-ref: '.'
|
|
||||||
scanners: 'vuln,secret,misconfig'
|
|
||||||
format: 'table'
|
|
||||||
severity: 'CRITICAL,HIGH,MEDIUM'
|
|
||||||
exit-code: '1'
|
|
||||||
176
CLAUDE.md
176
CLAUDE.md
|
|
@ -1,176 +0,0 @@
|
||||||
# CLAUDE.md
|
|
||||||
|
|
||||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
||||||
|
|
||||||
## Project Overview
|
|
||||||
|
|
||||||
This is a GitHub Action for executing remote SSH commands. Built using a composite action pattern, it downloads and runs the [drone-ssh](https://github.com/appleboy/drone-ssh) binary (written in Go) to execute SSH commands on remote hosts.
|
|
||||||
|
|
||||||
**Key characteristics:**
|
|
||||||
|
|
||||||
- No local compilation required - downloads pre-built binaries from drone-ssh releases
|
|
||||||
- Shell-based composite action using `entrypoint.sh`
|
|
||||||
- Supports password and SSH key authentication, proxies, multiple hosts, and environment variable passing
|
|
||||||
- All input parameters are passed via `INPUT_*` environment variables
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
### Execution Flow
|
|
||||||
|
|
||||||
1. **action.yml** - GitHub Actions composite action definition
|
|
||||||
- Defines all input parameters and their descriptions
|
|
||||||
- Sets up environment variables with `INPUT_*` prefix
|
|
||||||
- Calls `entrypoint.sh`
|
|
||||||
|
|
||||||
2. **entrypoint.sh** - Main entry point
|
|
||||||
- Detects platform (Linux/Darwin/Windows) and architecture (amd64/arm64)
|
|
||||||
- Downloads appropriate `drone-ssh` binary from GitHub releases
|
|
||||||
- Executes the binary with all environment variables
|
|
||||||
- Handles `capture_stdout` for output capture
|
|
||||||
|
|
||||||
3. **drone-ssh binary** - The actual SSH client (separate Go project)
|
|
||||||
- Performs SSH connection and command execution
|
|
||||||
- Not part of this repository
|
|
||||||
|
|
||||||
### Key Files
|
|
||||||
|
|
||||||
- `action.yml` - Action metadata and input/output definitions
|
|
||||||
- `entrypoint.sh` - Platform detection, binary download, and execution
|
|
||||||
- `testdata/` - Test scripts and SSH keys for CI workflows
|
|
||||||
- `.github/workflows/main.yml` - Comprehensive test suite using Docker containers
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
|
|
||||||
### Running Tests
|
|
||||||
|
|
||||||
Tests run automatically via GitHub Actions workflows. The test suite uses Docker containers running OpenSSH servers:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Tests run automatically on push via .github/workflows/main.yml
|
|
||||||
# Tests create Docker containers with openssh-server and test various scenarios
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Categories (from main.yml)
|
|
||||||
|
|
||||||
The test workflow covers:
|
|
||||||
|
|
||||||
- **default-user-name-password**: Basic password authentication
|
|
||||||
- **check-ssh-key**: RSA key authentication, key priority over password
|
|
||||||
- **support-key-passphrase**: Encrypted SSH keys
|
|
||||||
- **multiple-server**: Multiple hosts with different ports
|
|
||||||
- **support-ed25519-key**: ED25519 key format
|
|
||||||
- **testing-with-env**: Environment variable passing, `allenvs`, custom formats
|
|
||||||
- **testing06**: IPv6 connectivity
|
|
||||||
- **testing07**: Special characters in passwords
|
|
||||||
- **testing-capturing-output**: Output capture functionality
|
|
||||||
- **testing-script-stop**: Script error handling with `set -e`
|
|
||||||
- **testing-script-error**: Error propagation
|
|
||||||
|
|
||||||
### Testing Locally
|
|
||||||
|
|
||||||
Since this action downloads binaries, local testing should:
|
|
||||||
|
|
||||||
1. Create a test SSH server (Docker or VM)
|
|
||||||
2. Test `entrypoint.sh` directly with appropriate `INPUT_*` environment variables
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export INPUT_HOST="192.168.1.100"
|
|
||||||
export INPUT_USERNAME="testuser"
|
|
||||||
export INPUT_PASSWORD="testpass"
|
|
||||||
export INPUT_PORT="22"
|
|
||||||
export INPUT_SCRIPT="whoami"
|
|
||||||
export GITHUB_ACTION_PATH="$(pwd)"
|
|
||||||
./entrypoint.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## Important Patterns
|
|
||||||
|
|
||||||
### Script Execution
|
|
||||||
|
|
||||||
Users can provide scripts in two ways:
|
|
||||||
|
|
||||||
- `script`: Inline commands (via `INPUT_SCRIPT`)
|
|
||||||
- `script_path`: Path to a file in the repository (via `INPUT_SCRIPT_FILE`)
|
|
||||||
|
|
||||||
### Error Handling
|
|
||||||
|
|
||||||
To stop execution on first error (mimics removed `script_stop` option), users should add `set -e` to their scripts:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
script: |
|
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -e
|
|
||||||
command1
|
|
||||||
command2
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
|
|
||||||
The action passes GitHub Action inputs as environment variables with `INPUT_*` prefix. The drone-ssh binary reads these to configure SSH behavior.
|
|
||||||
|
|
||||||
Special handling:
|
|
||||||
|
|
||||||
- `envs`: Comma-separated list of environment variables to pass to remote script
|
|
||||||
- `allenvs`: Pass all `GITHUB_*` and `INPUT_*` variables
|
|
||||||
- `envs_format`: Custom format for environment variable export (e.g., `export TEST_{NAME}={VALUE}`)
|
|
||||||
|
|
||||||
### Multiple Hosts
|
|
||||||
|
|
||||||
- Comma-separated hosts: `"host1,host2"` (executes in parallel by default)
|
|
||||||
- With custom ports: `"host1:2222,host2:5678"`
|
|
||||||
- Synchronous execution: Set `sync: true`
|
|
||||||
|
|
||||||
## Common Issues
|
|
||||||
|
|
||||||
### Command Not Found
|
|
||||||
|
|
||||||
Non-interactive shells may skip `.bashrc`/`.bash_profile`. See README section "Command not found" for details. Solutions:
|
|
||||||
|
|
||||||
- Use absolute paths in commands
|
|
||||||
- Comment out early return in `/etc/bash.bashrc`
|
|
||||||
|
|
||||||
### OpenSSH Compatibility
|
|
||||||
|
|
||||||
Ubuntu 20.04+ may require enabling `ssh-rsa` algorithm in sshd_config:
|
|
||||||
|
|
||||||
```txt
|
|
||||||
CASignatureAlgorithms +ssh-rsa
|
|
||||||
```
|
|
||||||
|
|
||||||
Or use ED25519 keys instead (preferred).
|
|
||||||
|
|
||||||
## Development Guidelines
|
|
||||||
|
|
||||||
### Adding New Parameters
|
|
||||||
|
|
||||||
1. Add input definition to `action.yml` with description
|
|
||||||
2. Add corresponding `INPUT_*` environment variable mapping in `action.yml` runs.steps
|
|
||||||
3. Update README.md parameter tables
|
|
||||||
4. The drone-ssh binary handles the actual parameter logic (separate repo)
|
|
||||||
|
|
||||||
### Documentation
|
|
||||||
|
|
||||||
- Keep parameter tables in README.md synchronized with `action.yml`
|
|
||||||
- Maintain Chinese translations (README.zh-cn.md, README.zh-tw.md)
|
|
||||||
- Use clear examples for each feature
|
|
||||||
|
|
||||||
### Version Management
|
|
||||||
|
|
||||||
The action pins to specific drone-ssh versions via:
|
|
||||||
|
|
||||||
- Default: `DRONE_SSH_VERSION="1.8.1"` in `entrypoint.sh`
|
|
||||||
- Override: Users can specify `version` input parameter
|
|
||||||
|
|
||||||
Update the default version when new drone-ssh releases are available.
|
|
||||||
|
|
||||||
## Release Process
|
|
||||||
|
|
||||||
This action uses semantic versioning with major version tags:
|
|
||||||
|
|
||||||
- Tags: `v1.0.0`, `v1.0.1`, etc.
|
|
||||||
- Major version tag: `v1` (points to latest v1.x.x)
|
|
||||||
- Users reference: `uses: appleboy/ssh-action@v1`
|
|
||||||
|
|
||||||
GoReleaser config (`.goreleaser.yaml`) is present but set to `skip: true` since this action doesn't build Go code - it downloads pre-built binaries.
|
|
||||||
|
|
@ -46,7 +46,6 @@ Built with [Golang](https://go.dev) and [drone-ssh](https://github.com/appleboy/
|
||||||

|

|
||||||
|
|
||||||
[](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
|
[](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
|
||||||
[](https://github.com/appleboy/ssh-action/actions/workflows/trivy-scan.yml)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@
|
||||||

|

|
||||||
|
|
||||||
[](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
|
[](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
|
||||||
[](https://github.com/appleboy/ssh-action/actions/workflows/trivy-scan.yml)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@
|
||||||

|

|
||||||
|
|
||||||
[](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
|
[](https://github.com/appleboy/ssh-action/actions/workflows/main.yml)
|
||||||
[](https://github.com/appleboy/ssh-action/actions/workflows/trivy-scan.yml)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,6 @@ GITHUB_ACTION_PATH="${GITHUB_ACTION_PATH%/}"
|
||||||
DRONE_SSH_RELEASE_URL="${DRONE_SSH_RELEASE_URL:-https://github.com/appleboy/drone-ssh/releases/download}"
|
DRONE_SSH_RELEASE_URL="${DRONE_SSH_RELEASE_URL:-https://github.com/appleboy/drone-ssh/releases/download}"
|
||||||
DRONE_SSH_VERSION="${DRONE_SSH_VERSION:-1.8.1}"
|
DRONE_SSH_VERSION="${DRONE_SSH_VERSION:-1.8.1}"
|
||||||
|
|
||||||
# Error codes
|
|
||||||
readonly ERR_UNKNOWN_PLATFORM=2
|
|
||||||
readonly ERR_UNKNOWN_ARCH=3
|
|
||||||
readonly ERR_DOWNLOAD_FAILED=4
|
|
||||||
readonly ERR_INVALID_BINARY=5
|
|
||||||
readonly ERR_VERSION_CHECK_FAILED=6
|
|
||||||
|
|
||||||
function log_error() {
|
function log_error() {
|
||||||
echo "$1" >&2
|
echo "$1" >&2
|
||||||
exit "$2"
|
exit "$2"
|
||||||
|
|
@ -26,13 +19,13 @@ function detect_client_info() {
|
||||||
|
|
||||||
case "${CLIENT_PLATFORM}" in
|
case "${CLIENT_PLATFORM}" in
|
||||||
darwin | linux | windows) ;;
|
darwin | linux | windows) ;;
|
||||||
*) log_error "Unknown or unsupported platform: ${CLIENT_PLATFORM}. Supported platforms are Linux, Darwin, and Windows." "${ERR_UNKNOWN_PLATFORM}" ;;
|
*) log_error "Unknown or unsupported platform: ${CLIENT_PLATFORM}. Supported platforms are Linux, Darwin, and Windows." 2 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "${CLIENT_ARCH}" in
|
case "${CLIENT_ARCH}" in
|
||||||
x86_64* | i?86_64* | amd64*) CLIENT_ARCH="amd64" ;;
|
x86_64* | i?86_64* | amd64*) CLIENT_ARCH="amd64" ;;
|
||||||
aarch64* | arm64*) CLIENT_ARCH="arm64" ;;
|
aarch64* | arm64*) CLIENT_ARCH="arm64" ;;
|
||||||
*) log_error "Unknown or unsupported architecture: ${CLIENT_ARCH}. Supported architectures are x86_64, i686, and arm64." "${ERR_UNKNOWN_ARCH}" ;;
|
*) log_error "Unknown or unsupported architecture: ${CLIENT_ARCH}. Supported architectures are x86_64, i686, and arm64." 3 ;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -40,35 +33,17 @@ detect_client_info
|
||||||
DOWNLOAD_URL_PREFIX="${DRONE_SSH_RELEASE_URL}/v${DRONE_SSH_VERSION}"
|
DOWNLOAD_URL_PREFIX="${DRONE_SSH_RELEASE_URL}/v${DRONE_SSH_VERSION}"
|
||||||
CLIENT_BINARY="drone-ssh-${DRONE_SSH_VERSION}-${CLIENT_PLATFORM}-${CLIENT_ARCH}"
|
CLIENT_BINARY="drone-ssh-${DRONE_SSH_VERSION}-${CLIENT_PLATFORM}-${CLIENT_ARCH}"
|
||||||
TARGET="${GITHUB_ACTION_PATH}/${CLIENT_BINARY}"
|
TARGET="${GITHUB_ACTION_PATH}/${CLIENT_BINARY}"
|
||||||
|
|
||||||
# Check if binary already exists and is executable (caching)
|
|
||||||
if [[ -f "${TARGET}" ]] && [[ -x "${TARGET}" ]]; then
|
|
||||||
echo "Binary ${CLIENT_BINARY} already exists, skipping download"
|
|
||||||
else
|
|
||||||
echo "Downloading ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}"
|
echo "Downloading ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}"
|
||||||
INSECURE_OPTION=""
|
INSECURE_OPTION=""
|
||||||
if [[ "${INPUT_CURL_INSECURE}" == 'true' ]]; then
|
if [[ "${INPUT_CURL_INSECURE}" == 'true' ]]; then
|
||||||
INSECURE_OPTION="--insecure"
|
INSECURE_OPTION="--insecure"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Download with better error handling
|
curl -fsSL --retry 5 --keepalive-time 2 ${INSECURE_OPTION} "${DOWNLOAD_URL_PREFIX}/${CLIENT_BINARY}" -o "${TARGET}"
|
||||||
if ! curl -fsSL --retry 5 --keepalive-time 2 --location ${INSECURE_OPTION} \
|
|
||||||
"${DOWNLOAD_URL_PREFIX}/${CLIENT_BINARY}" -o "${TARGET}"; then
|
|
||||||
log_error "Failed to download ${CLIENT_BINARY} from ${DOWNLOAD_URL_PREFIX}. Please check the URL and your network connection." "${ERR_DOWNLOAD_FAILED}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Validate downloaded file
|
|
||||||
if [[ ! -f "${TARGET}" ]] || [[ ! -s "${TARGET}" ]]; then
|
|
||||||
log_error "Downloaded file is missing or empty: ${TARGET}" "${ERR_INVALID_BINARY}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
chmod +x "${TARGET}"
|
chmod +x "${TARGET}"
|
||||||
fi
|
|
||||||
|
|
||||||
echo "======= CLI Version Information ======="
|
echo "======= CLI Version Information ======="
|
||||||
if ! "${TARGET}" --version; then
|
"${TARGET}" --version
|
||||||
log_error "Failed to execute ${TARGET} --version. The binary may be corrupted." "${ERR_VERSION_CHECK_FAILED}"
|
|
||||||
fi
|
|
||||||
echo "======================================="
|
echo "======================================="
|
||||||
if [[ "${INPUT_CAPTURE_STDOUT}" == 'true' ]]; then
|
if [[ "${INPUT_CAPTURE_STDOUT}" == 'true' ]]; then
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue