streamline package naming
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
# ssh-authorize
|
||||
|
||||
**Authorize SSH public key for a user**
|
||||
|
||||
## Purpose
|
||||
|
||||
This cube adds a specific SSH public key to a user's `authorized_keys` file on the remote server, allowing them to log in via SSH using the corresponding private key.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Parameters
|
||||
|
||||
- **USER** (string, default: `'vagrant'`)
|
||||
- The username on the remote server to authorize.
|
||||
- If the user does not exist, `pyinfra` will attempt to create it (though a full user creation with shell/groups is better handled by `user-add`).
|
||||
|
||||
- **PUBKEY** (string, required)
|
||||
- The actual content of the public key (e.g., `ssh-ed25519 AAAA...`).
|
||||
|
||||
## Use Cases
|
||||
|
||||
Grant access to a developer:
|
||||
```javascript
|
||||
exec('ssh-authorize', {
|
||||
USER: 'developer',
|
||||
PUBKEY: 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA...'
|
||||
})
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
None.
|
||||
@@ -0,0 +1,13 @@
|
||||
from pyinfra import host
|
||||
from pyinfra.operations import server
|
||||
|
||||
USER = host.data.USER
|
||||
PUBKEY = host.data.PUBKEY
|
||||
|
||||
server.user(
|
||||
name=f"Authorize public key for {USER}",
|
||||
user=USER,
|
||||
public_keys=[PUBKEY],
|
||||
present=True,
|
||||
_sudo=True
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default Manifest({
|
||||
id: 'ssh:authorize',
|
||||
name: 'Authorize SSH public key for a user',
|
||||
dependencies: () => [],
|
||||
schema: z.object({
|
||||
USER: z.string().describe('Username to authorize').default('vagrant'),
|
||||
PUBKEY: z.string().describe('SSH public key string').default(''),
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,93 @@
|
||||
# ssh-keygen
|
||||
|
||||
**Generate SSH key for a given user**
|
||||
|
||||
## Purpose
|
||||
|
||||
This cube generates a new SSH key pair for a specified user, which can be used for secure, passwordless authentication to remote servers and services like GitHub, GitLab, or other SSH-accessible systems.
|
||||
|
||||
## What are SSH Keys?
|
||||
|
||||
SSH keys provide a more secure and convenient way to authenticate compared to passwords:
|
||||
|
||||
- **Public key**: Shared with servers/services you want to access (like GitHub)
|
||||
- **Private key**: Kept secret on your local machine, never shared
|
||||
- **Passphrase-free**: This cube generates keys without a passphrase for automation
|
||||
- **Algorithm support**: RSA (traditional) or Ed25519 (modern, recommended)
|
||||
|
||||
## What This Cube Does
|
||||
|
||||
1. Creates the `.ssh` directory with proper permissions (700)
|
||||
2. Generates an SSH key pair using the specified algorithm
|
||||
3. Saves the keys as `id_{SUFFIX}` and `id_{SUFFIX}.pub`
|
||||
4. Logs the public key to the console for easy copying
|
||||
|
||||
## Configuration
|
||||
|
||||
### Parameters
|
||||
|
||||
- **SUFFIX** (string, default: `'ed25519'`)
|
||||
- Suffix for keyname (e.g., `github` → `id_github.pub`)
|
||||
- Helps identify the purpose of the key
|
||||
|
||||
- **EMAIL** (string, default: `'undefined@bitsquare.dev'`)
|
||||
- Email address to associate with the SSH key
|
||||
- Used as a comment in the public key
|
||||
|
||||
- **ALGORITHM** (enum: `'rsa'` | `'ed25519'`, default: `'ed25519'`)
|
||||
- SSH key algorithm type
|
||||
- **Ed25519**: Modern, faster, more secure (recommended)
|
||||
- **RSA**: Traditional, widely supported
|
||||
|
||||
- **USER** (string, default: `'vagrant'`)
|
||||
- Username for which to generate the SSH key
|
||||
- Inherited from `user-add` dependency
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **user-add** - Creates the user account first
|
||||
|
||||
## Post-Installation
|
||||
|
||||
After the key is generated:
|
||||
|
||||
1. The public key will be logged to the console
|
||||
2. Copy the public key and add it to the target service:
|
||||
- **GitHub**: Settings → SSH and GPG keys → New SSH key
|
||||
- **GitLab**: Preferences → SSH Keys
|
||||
- **Remote server**: Add to `~/.ssh/authorized_keys`
|
||||
|
||||
3. SSH config is automatically set up for the key
|
||||
|
||||
## Key Locations
|
||||
|
||||
- Private key: `/home/{USER}/.ssh/id_{SUFFIX}`
|
||||
- Public key: `/home/{USER}/.ssh/id_{SUFFIX}.pub`
|
||||
|
||||
## Algorithm Comparison
|
||||
|
||||
**Ed25519** (Recommended):
|
||||
- Smaller keys (256-bit)
|
||||
- Faster generation and verification
|
||||
- More secure against certain attacks
|
||||
- Not supported on very old systems
|
||||
|
||||
**RSA**:
|
||||
- Larger keys (2048-4096 bit)
|
||||
- Universally supported
|
||||
- Slower than Ed25519
|
||||
- Well-tested and trusted
|
||||
|
||||
## Example Usage
|
||||
|
||||
Generate a key for GitHub access:
|
||||
```javascript
|
||||
exec('ssh-keygen', {
|
||||
SUFFIX: 'github',
|
||||
EMAIL: 'myemail@example.com',
|
||||
ALGORITHM: 'ed25519',
|
||||
USER: 'myuser'
|
||||
})
|
||||
```
|
||||
|
||||
This creates `id_github` and `id_github.pub` in `/home/myuser/.ssh/`.
|
||||
@@ -0,0 +1,46 @@
|
||||
from pyinfra.operations import files, server, python
|
||||
from pyinfra import host, logger
|
||||
import logging
|
||||
|
||||
|
||||
NAME=host.data.SUFFIX
|
||||
EMAIL=host.data.EMAIL
|
||||
ALGORITHM=host.data.ALGORITHM
|
||||
USER=host.data.USER
|
||||
|
||||
# Ensure the .ssh directory exists
|
||||
files.directory(
|
||||
name="Ensure .ssh directory exists",
|
||||
path=f"/home/{USER}/.ssh",
|
||||
present=True,
|
||||
mode=700,
|
||||
user=USER,
|
||||
group=USER,
|
||||
)
|
||||
|
||||
# Generate the SSH keypair
|
||||
server.shell(
|
||||
name=f"Generate SSH key id_{NAME}",
|
||||
commands=[
|
||||
f"ssh-keygen -t {ALGORITHM} -f /home/{USER}/.ssh/id_{NAME} -C '{EMAIL}' -N ''"
|
||||
]
|
||||
)
|
||||
|
||||
# Print the public key
|
||||
result = server.shell(
|
||||
name="Print public key",
|
||||
commands=[f"cat /home/{USER}/.ssh/id_{NAME}.pub"],
|
||||
)
|
||||
|
||||
def callback():
|
||||
# 🔹 Extract and log the key output
|
||||
if result.stdout:
|
||||
logger.info(f"Public Key for {USER}: {result.stdout.strip()}")
|
||||
else:
|
||||
logger.warning(f"No public key found for {USER} at /home/{USER}/.ssh/id_{NAME}.pub")
|
||||
|
||||
python.call(
|
||||
name="Log public key",
|
||||
function=callback,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default Manifest({
|
||||
id: 'ssh:keygen',
|
||||
name: 'Generate SSH key for a given $USER',
|
||||
dependencies: () => ['user:add'],
|
||||
schema: z.object({
|
||||
SUFFIX: z
|
||||
.string()
|
||||
.describe('Suffix for keyname, e.g. github => id_github.pub')
|
||||
.default('ed25519'),
|
||||
EMAIL: z
|
||||
.string()
|
||||
.describe('Email address to associate with the SSH key')
|
||||
.default('undefined@bitsquare.dev'),
|
||||
ALGORITHM: z.enum(['rsa', 'ed25519']).describe('SSH key algorithm type').default('ed25519'),
|
||||
USER: z.string().describe('Username for which to generate the SSH key').default('vagrant'),
|
||||
}),
|
||||
});
|
||||
@@ -0,0 +1,110 @@
|
||||
# ssh-keyman
|
||||
|
||||
**Deploy existing SSH keys to host**
|
||||
|
||||
## Purpose
|
||||
|
||||
This cube deploys pre-existing SSH key pairs from your local machine to a remote server, configuring them for automatic use with specified hosts (like GitHub, GitLab, etc.).
|
||||
|
||||
## What This Cube Does
|
||||
|
||||
1. **Copies SSH keys to the server**
|
||||
- Transfers both private and public keys from local directory to remote `.ssh` folder
|
||||
- Sets correct file permissions (600 for private, 644 for public)
|
||||
|
||||
2. **Configures SSH client**
|
||||
- Creates/updates `.ssh/config` to use the deployed key for specified hosts
|
||||
- Disables strict host key checking for easier automation
|
||||
- Maps each host to use the correct identity file
|
||||
|
||||
3. **Ensures security**
|
||||
- Sets proper directory permissions (700 for `.ssh`)
|
||||
- Ensures keys are owned by the specified user
|
||||
|
||||
## Configuration
|
||||
|
||||
### Parameters
|
||||
|
||||
- **KEY_NAME** (string, default: `'id_ed25519'`)
|
||||
- Name of the SSH key file (without extension)
|
||||
- Must exist in the KEY_DIR directory locally
|
||||
|
||||
- **USER** (string, default: `'vagrant'`)
|
||||
- Username for which to deploy the SSH key
|
||||
- Inherited from `user-add` dependency
|
||||
|
||||
- **HOSTS** (string, default: `'github.com'`)
|
||||
- Space-separated list of hosts to add to known_hosts
|
||||
- Example: `'github.com gitlab.com bitbucket.org'`
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **user-add** - Creates the user account first
|
||||
|
||||
## Use Cases
|
||||
|
||||
Deploy GitHub SSH key:
|
||||
|
||||
```javascript
|
||||
exec('ssh-keyman', {
|
||||
KEY_NAME: 'id_github',
|
||||
HOSTS: 'github.com'
|
||||
})
|
||||
```
|
||||
|
||||
Deploy key for multiple Git services:
|
||||
|
||||
```javascript
|
||||
exec('ssh-keyman', {
|
||||
KEY_NAME: 'id_git',
|
||||
HOSTS: 'github.com gitlab.com bitbucket.org'
|
||||
})
|
||||
```
|
||||
|
||||
## What Gets Configured
|
||||
|
||||
After deployment, the `.ssh/config` file will contain entries like:
|
||||
|
||||
```
|
||||
Host github.com
|
||||
IdentityFile /home/{USER}/.ssh/id_github
|
||||
StrictHostKeyChecking no
|
||||
```
|
||||
|
||||
This means when you run `git clone git@github.com:user/repo.git`, it will automatically use the deployed key.
|
||||
|
||||
## Key File Requirements
|
||||
|
||||
The local KEY_DIR must contain:
|
||||
|
||||
- `{KEY_NAME}` - Private key file
|
||||
- `{KEY_NAME}.pub` - Public key file
|
||||
|
||||
For example, if `KEY_NAME=id_github`, you need:
|
||||
|
||||
- `./vault/tmp/id_github`
|
||||
- `./vault/tmp/id_github.pub`
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **Private keys are sensitive**: Ensure your local KEY_DIR is secure
|
||||
- **StrictHostKeyChecking disabled**: Convenient but less secure
|
||||
- Consider enabling it for production: Edit `/home/{USER}/.ssh/config`
|
||||
- **Backup your keys**: Keep secure copies of private keys
|
||||
- **Use different keys**: Consider separate keys for different services
|
||||
|
||||
## Post-Installation
|
||||
|
||||
Test SSH connection:
|
||||
|
||||
```bash
|
||||
ssh -T git@github.com
|
||||
# Should show: "Hi username! You've successfully authenticated..."
|
||||
```
|
||||
|
||||
Clone a repository:
|
||||
|
||||
```bash
|
||||
git clone git@github.com:user/repo.git
|
||||
# Should work without prompting for credentials
|
||||
```
|
||||
@@ -0,0 +1,96 @@
|
||||
from pyinfra.operations import server, files, apt, systemd
|
||||
from pyinfra import host
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
|
||||
def get_keyman_config():
|
||||
"""Get keyman configuration by calling keyman --print-config"""
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['keyman', '--print-config'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=True
|
||||
)
|
||||
return json.loads(result.stdout)
|
||||
except (subprocess.CalledProcessError, json.JSONDecodeError, FileNotFoundError):
|
||||
return None
|
||||
|
||||
|
||||
# Load keyman config for defaults
|
||||
keyman_config = get_keyman_config()
|
||||
|
||||
USER = host.data.USER
|
||||
KEY = host.data.KEY_NAME
|
||||
|
||||
# Use KEY_DIR from host data, or fall back to keyman config tmpDir
|
||||
DIR = host.data.get('KEY_DIR')
|
||||
if not DIR and keyman_config:
|
||||
DIR = keyman_config.get('tmpDir')
|
||||
if not DIR:
|
||||
DIR = '../../vault/tmp' # Final fallback
|
||||
|
||||
# Support multiple hosts separated by space
|
||||
HOSTS = map(str.lstrip, str(host.data.HOSTS).split(' '))
|
||||
|
||||
# 🔹 Define remote paths
|
||||
SSH_DIR = f"/home/{USER}/.ssh" if USER != "root" else "/root/.ssh"
|
||||
PRIVATE_KEY_PATH = f"{SSH_DIR}/{KEY}"
|
||||
PUBLIC_KEY_PATH = f"{SSH_DIR}/{KEY}.pub"
|
||||
|
||||
# Ensure the .ssh directory exists
|
||||
files.directory(
|
||||
name="Ensure .ssh directory exists",
|
||||
path=SSH_DIR,
|
||||
present=True,
|
||||
mode=700,
|
||||
user=USER,
|
||||
group=USER,
|
||||
_sudo=True
|
||||
)
|
||||
# Copy private key to the remote server
|
||||
files.put(
|
||||
name="Copy private key",
|
||||
src=f"{DIR}/{KEY}",
|
||||
dest=PRIVATE_KEY_PATH,
|
||||
mode="600",
|
||||
user=USER,
|
||||
group=USER,
|
||||
_sudo=True,
|
||||
)
|
||||
|
||||
# Copy public key to the remote server
|
||||
files.put(
|
||||
name="Copy public key",
|
||||
src=f"{DIR}/{KEY}.pub",
|
||||
dest=PUBLIC_KEY_PATH,
|
||||
mode="644",
|
||||
user=USER,
|
||||
group=USER,
|
||||
_sudo=True,
|
||||
)
|
||||
|
||||
# Ensure correct permissions for the private key
|
||||
server.shell(
|
||||
name="Set correct permissions for private key",
|
||||
commands=[f"chmod 600 {PRIVATE_KEY_PATH}"],
|
||||
_sudo=True,
|
||||
)
|
||||
|
||||
files.file(
|
||||
name="Ensure .ssh/config directory exists",
|
||||
path=f"/home/{USER}/.ssh/config",
|
||||
present=True,
|
||||
user=USER,
|
||||
group=USER,
|
||||
_sudo=True
|
||||
)
|
||||
|
||||
for host in HOSTS:
|
||||
files.line(
|
||||
name=f"Configure SSH key for {host}",
|
||||
path=f"{SSH_DIR}/config",
|
||||
line=f"Host {host}\n IdentityFile {SSH_DIR}/{KEY}\n StrictHostKeyChecking no",
|
||||
_sudo=True
|
||||
)
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Manifest } from '@bitsquare/nopy-cubes';
|
||||
import { z } from 'zod';
|
||||
|
||||
export default Manifest({
|
||||
id: 'ssh:keyman',
|
||||
name: 'Deploy an ssh key managed by keyman',
|
||||
dependencies: () => [],
|
||||
schema: z.object({
|
||||
KEY_NAME: z
|
||||
.string()
|
||||
.describe('Name of the SSH key file (without extension)')
|
||||
.default('id_ed25519'),
|
||||
USER: z.string().describe('Username for which to deploy the SSH key').default('vagrant'),
|
||||
HOSTS: z
|
||||
.string()
|
||||
.describe('Space-separated list of hosts to add to known_hosts')
|
||||
.default('github.com'),
|
||||
}),
|
||||
});
|
||||
Reference in New Issue
Block a user