Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/check-version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Check Script Version

on:
pull_request:
branches:
- main

jobs:
check-version:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Extract SCRIPT_VERSION from sync-ssh-keys.sh
id: get_version
run: |
VERSION=$(awk -F'"' '/SCRIPT_VERSION/ {print $2; exit}' sync-ssh-keys.sh)
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Fetch tags
run: git fetch --tags

- name: Check if version tag exists
run: |
TAG="v${{ steps.get_version.outputs.version }}"
if git tag --list | grep -q "^$TAG$"; then
echo "Error: Tag $TAG already exists. Please bump SCRIPT_VERSION."
exit 1
else
echo "Tag $TAG does not exist. Good to merge."
fi
46 changes: 46 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Create Release

on:
push:
branches:
- main

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Extract version from script
id: get_version
run: |
VERSION=$(awk -F'"' '/SCRIPT_VERSION/ {print $2; exit}' sync-ssh-keys.sh)
if [[ ! $VERSION =~ ^[0-9]+(\.[0-9]+)*$ ]]; then
echo "Error: Invalid version format: $VERSION" >&2
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT

- name: Create tag if needed
run: |
TAG="v${{ steps.get_version.outputs.version }}"
if git rev-parse "$TAG" >/dev/null 2>&1; then
echo "Tag $TAG already exists."
else
git config user.name "github-actions"
git config user.email "[email protected]"
git tag "$TAG"
git push origin "$TAG"
fi

- name: Create release zip
run: |
zip ssh-key-sync.zip sync-ssh-keys.sh users.conf

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.get_version.outputs.version }}
generate_release_notes: true
files: ssh-key-sync.zip
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ This Bash script pulls `authorized_keys` files from remote URLs and updates SSH

## ⚙️ Configuration

Edit the `USER_KEYS` associative array in `sync-ssh-keys.sh` to define users and their key sources.
User configuration is stored in a separate `users.conf` file in the same directory as the script.
Edit `users.conf` to define users and their key sources.
Each entry uses the format:
`["username"]="method:url"`

- **raw:** Fetches directly from a public URL.
- **api:** Fetches from a private GitHub repo using the GitHub API (requires `GITHUB_TOKEN` environment variable).

**Example:**
**Example `users.conf`:**
```bash
declare -A USER_KEYS=(
["ubuntu"]="raw:https://example.com/ssh-keys/ubuntu.authorized_keys"
Expand All @@ -31,19 +32,24 @@ declare -A USER_KEYS=(

## Usage

1. Edit the `USER_KEYS` array in `sync-ssh-keys.sh` to define users and their key URLs.
1. Edit the `users.conf` file to define users and their key URLs.
2. If using the `api` method, export your GitHub token:
```bash
export GITHUB_TOKEN=your_token_here
```
3. Add to root's crontab:
3. Make sure the script is executable:
```bash
chmod +x sync-ssh-keys.sh
```
4. Add to root's crontab:

```cron
*/15 * * * * /usr/local/bin/sync-ssh-keys.sh >> /var/log/ssh-key-sync.log 2>&1
```

## Implementation Notes

- The script uses a helper function `fetch_key_file` to fetch keys using the appropriate method.
- The script sources `users.conf` for configuration.
- Uses a helper function `fetch_key_file` to fetch keys using the appropriate method.
- Only updates a user's `authorized_keys` if the remote file has changed.
- Logs all actions with timestamps.
18 changes: 12 additions & 6 deletions sync-ssh-keys.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
#!/bin/bash
set -euo pipefail

# === Configuration: user -> remote key file URL ===
declare -A USER_KEYS=(
["ubuntu"]="raw:https://example.com/ssh-keys/ubuntu.authorized_keys"
["devuser"]="api:https://api.github.com/repos/yourorg/ssh-keys/contents/keys/devuser.authorized_keys?ref=main"
["admin"]="api:https://api.github.com/repos/yourorg/ssh-keys/contents/keys/admin.authorized_keys?ref=main"
)
SCRIPT_VERSION="0.0.3"

# === Load user configuration ===
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ ! -f "$SCRIPT_DIR/users.conf" ]; then
echo "Error: Configuration file 'users.conf' not found in $SCRIPT_DIR. Halting execution." >&2
exit 1
fi
if ! source "$SCRIPT_DIR/users.conf"; then
echo "Error: Failed to load configuration file 'users.conf'. Please check the file for syntax errors. Halting execution." >&2
exit 1
fi

log_message() {
local TIMESTAMP
Expand Down
5 changes: 5 additions & 0 deletions users.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare -A USER_KEYS=(
["ubuntu"]="raw:https://example.com/ssh-keys/ubuntu.authorized_keys"
["devuser"]="api:https://api.github.com/repos/yourorg/ssh-keys/contents/keys/devuser.authorized_keys?ref=main"
["admin"]="api:https://api.github.com/repos/yourorg/ssh-keys/contents/keys/admin.authorized_keys?ref=main"
)