@@ -6,85 +6,157 @@ This document provides comprehensive guidance for AI coding agents and contribut
66
77` ssh-key-sync ` is a Bash script-based utility for synchronizing SSH ` authorized_keys ` files for multiple users. It supports fetching keys from various sources, including public URLs, private GitHub repositories, and GitHub user profiles. The configuration is externalized in a ` users.conf ` file.
88
9- ## Key Components
10-
11- ### Scripts
12- - ** ` sync-ssh-keys.sh ` ** : The main script that performs the synchronization. It includes:
13- - Support for multiple fetch methods (` raw ` , ` api ` , ` ghuser ` ).
14- - Logging and error handling.
15- - Configuration loading from ` users.conf ` .
16- - A helper function ` fetch_key_file ` to handle key retrieval logic with retries for failed operations.
17- - A ` --self-update ` option to fetch and replace the script with the latest version from the GitHub repository.
18-
19- ### Configuration
20- - ** ` users.conf ` ** : Defines users and their key sources. Example structure:
21- ``` bash
22- CONF_GITHUB_TOKEN=" your_github_token_here"
23-
24- declare -A USER_KEYS=(
25- [" ubuntu" ]=" raw:https://example.com/ssh-keys/ubuntu.authorized_keys"
26- [" devuser" ]=" api:https://api.github.com/repos/yourorg/ssh-keys/contents/keys/devuser.authorized_keys?ref=main"
27- [" alice" ]=" ghuser:alice-github-username"
28- )
29- ```
30-
31- ## Developer Workflows
32-
33- ### Running the Script
34- 1 . Ensure ` sync-ssh-keys.sh ` is executable:
35- ``` bash
36- chmod +x sync-ssh-keys.sh
37- ```
38- 2 . Run the script manually:
39- ``` bash
40- ./sync-ssh-keys.sh
41- ```
42- 3 . To update the script to the latest version, run:
43- ``` bash
44- ./sync-ssh-keys.sh --self-update
45- ```
46-
47- ### Configuration
48- - Edit ` users.conf ` to define users and their key sources.
49- - If using the ` api ` method, ensure ` CONF_GITHUB_TOKEN ` is set in ` users.conf ` or export ` GITHUB_TOKEN ` in the environment.
50-
51- ### Automating with Cron
52- - Add the script to root's crontab:
53- ``` cron
54- */15 * * * * /path/to/sync-ssh-keys.sh >> /var/log/ssh-key-sync.log 2>&1
55- ```
56-
57- ### Logging
58- - Logs are printed to the console with timestamps.
59- - Example log message:
60- ```
61- 2025-07-20 12:00:00: Fetching key file for user 'ubuntu' from https://example.com/ssh-keys/ubuntu.authorized_keys (method: raw)
62- ```
63-
64- ## Coding Conventions
65-
66- - Use meaningful variable and function names.
67- - Follow the existing code style in ` sync-ssh-keys.sh ` .
68- - Add comments for complex logic.
69- - Use environment variables for sensitive data (e.g., ` GITHUB_TOKEN ` ).
70- - Ensure temporary files are cleaned up using ` trap ` .
9+ ## Key Architecture Components
10+
11+ ### Core Script Structure (` sync-ssh-keys.sh ` )
12+ The main script follows a modular architecture with distinct functional layers:
13+
14+ - ** Utility Functions** (lines 24-41): Timestamped logging functions (` log_message ` , ` log_error ` , ` log_warning ` , ` log_info ` )
15+ - ** Configuration Management** (lines 43-74): Configuration loading and validation with error handling
16+ - ** Fetch Methods** (lines 76-174): Three distinct key fetching strategies with unified retry logic
17+ - ** Self-Update System** (lines 176-272): Download, validate, and replace script functionality
18+ - ** User Management** (lines 274-443): User validation, SSH directory creation, file permission management
19+ - ** Main Execution** (lines 445-614): Command-line parsing, configuration sourcing, and orchestration
20+
21+ ### Configuration Architecture (` users.conf ` )
22+ Configuration uses Bash associative arrays for user-to-source mapping:
23+ ``` bash
24+ CONF_GITHUB_TOKEN=" token_here" # Optional GitHub token
25+ declare -A USER_KEYS=(
26+ [" username" ]=" method:target" # method:target pattern
27+ )
28+ ```
29+
30+ ### Three Key Fetch Methods
31+ 1 . ** ` raw ` ** : Direct HTTP(S) URL fetching (public endpoints)
32+ 2 . ** ` api ` ** : GitHub API with authentication (private repositories)
33+ 3 . ** ` ghuser ` ** : GitHub user public keys endpoint (` github.com/username.keys ` )
34+
35+ ## Critical Developer Workflows
36+
37+ ### Testing Commands (Essential for Changes)
38+ ``` bash
39+ # Quick validation - Run before commits
40+ ./test.sh
41+
42+ # Manual syntax check
43+ bash -n sync-ssh-keys.sh
44+
45+ # ShellCheck validation (if available)
46+ shellcheck sync-ssh-keys.sh
47+
48+ # Test with actual users (requires root)
49+ sudo ./sync-ssh-keys.sh
50+ ```
51+
52+ ### CI/CD Pipeline Structure
53+ The project uses a sophisticated multi-workflow CI system:
54+ - ** ` ci.yml ` ** : Orchestrates all checks (lint, test, version validation)
55+ - ** ` test.yml ` ** : Creates real users, tests all fetch methods, validates error handling
56+ - ** ` lint.yml ` ** : ShellCheck static analysis
57+ - ** ` check-version.yml ` ** : Ensures version bumps in PRs
58+
59+ ### Configuration Testing Pattern
60+ Always test configuration changes with temporary configs:
61+ ``` bash
62+ cp users.conf users.conf.backup
63+ # Edit users.conf with test values
64+ sudo ./sync-ssh-keys.sh
65+ mv users.conf.backup users.conf
66+ ```
67+
68+ ### Error Handling Architecture
69+ The script uses a ** defensive programming** approach:
70+ - Every function validates parameters and returns meaningful exit codes
71+ - Network operations include retry logic (3 attempts, 2-second delays)
72+ - Temporary file cleanup using ` trap ` statements
73+ - File comparison before updates to avoid unnecessary writes
74+
75+ ### Self-Update Mechanism
76+ The ` --self-update ` feature demonstrates key patterns:
77+ - GitHub API integration for release information
78+ - Temporary file management with cleanup
79+ - Script validation before replacement
80+ - Atomic replacement to prevent corruption
81+
82+ ## Project-Specific Conventions
83+
84+ ### Function Organization Pattern
85+ Functions are grouped by responsibility with clear boundaries:
86+ - ** Utilities** : Pure functions for logging (prefix: ` log_ ` )
87+ - ** Configuration** : Loading and validation (prefix: ` load_ ` , ` validate_ ` )
88+ - ** Fetching** : Key retrieval methods (prefix: ` fetch_ ` )
89+ - ** User Management** : System operations (prefix: ` create_ ` , ` update_ ` , ` process_ ` )
90+
91+ ### Error Handling Style
92+ - Use meaningful exit codes: ` return 1 ` for failures, ` return 0 ` for success
93+ - Log errors before returning: ` log_error "message"; return 1 `
94+ - Validate parameters at function start: ` [[ -z "$param" ]] && { log_error "message"; return 1; } `
95+
96+ ### Bash Patterns Used
97+ - ` set -euo pipefail ` for strict error handling
98+ - Associative arrays for configuration: ` declare -A USER_KEYS `
99+ - Here documents for multi-line content in tests
100+ - Parameter expansion for parsing: ` ${entry%%:*} ` and ` ${entry#*:} `
101+
102+ ### File Permission Management
103+ Critical pattern - always set correct permissions:
104+ ``` bash
105+ chown " $username :$username " " $file " # User ownership
106+ chmod 700 " $ssh_dir " # SSH directory
107+ chmod 600 " $auth_keys_file " # authorized_keys file
108+ ```
71109
72110## Integration Points
73111
74- ### GitHub API
75- - Used for fetching keys from private repositories (` api ` method).
76- - Requires a GitHub token (` GITHUB_TOKEN ` or ` CONF_GITHUB_TOKEN ` ).
77-
78- ### System Integration
79- - The script ensures the ` .ssh ` directory and ` authorized_keys ` file exist for each user.
80- - Updates file permissions and ownership as needed.
112+ ### GitHub API Integration
113+ - ** Authentication** : Uses ` GITHUB_TOKEN ` or ` CONF_GITHUB_TOKEN `
114+ - ** Headers** : ` Authorization: token $GITHUB_TOKEN ` and ` Accept: application/vnd.github.v3.raw `
115+ - ** Rate Limiting** : Automatic retry logic helps with transient failures
116+ - ** Private Repos** : Full API endpoint format required: ` https://api.github.com/repos/org/repo/contents/path?ref=branch `
117+
118+ ### System Dependencies
119+ - ** ` curl ` ** : All HTTP operations with ` -fsSL ` flags (fail silently, show errors, follow redirects, location headers)
120+ - ** ` getent ` ** : User information retrieval - more reliable than parsing ` /etc/passwd `
121+ - ** ` mktemp ` ** : Secure temporary file creation with automatic cleanup
122+ - ** File comparison tools** : ` cmp ` > ` diff ` > checksum fallback hierarchy
123+
124+ ### File System Integration
125+ The script manages SSH infrastructure with specific patterns:
126+ - Creates ` .ssh ` directories with ` 700 ` permissions if missing
127+ - Compares files before updating to avoid unnecessary writes
128+ - Uses atomic operations (temp file → move) for updates
129+ - Maintains proper ownership chain: directory → file → permissions
81130
82131## Contribution Guidelines
83132
84- - Include a clear description of changes in pull requests.
85- - Reference related issues.
86- - Ensure the script passes linting (e.g., using ` shellcheck ` ).
87- - Test changes locally before submission.
133+ ### Pre-Commit Validation
134+ ``` bash
135+ # Required: Syntax check
136+ bash -n sync-ssh-keys.sh
137+
138+ # Required: Run test suite
139+ ./test.sh
140+
141+ # Recommended: Static analysis (if available)
142+ shellcheck sync-ssh-keys.sh
143+ ```
144+
145+ ### Version Management
146+ - Bump ` SCRIPT_VERSION ` in PRs (enforced by CI)
147+ - Follow semantic versioning (major.minor.patch)
148+ - Version check workflow prevents duplicate releases
149+
150+ ### Code Quality Standards
151+ - All functions must validate input parameters
152+ - Use ` log_error ` before ` return 1 ` in error conditions
153+ - Maintain consistent indentation (2 spaces)
154+ - Group related functions with clear section comments
155+
156+ ### Testing Requirements
157+ - New fetch methods need integration tests in ` test.yml `
158+ - Configuration changes require validation tests
159+ - Error conditions must be tested with invalid inputs
88160
89161## Examples
90162
0 commit comments