|
Bogdan Timofte
authored
2 weeks ago
|
1
|
# SSH Infrastructure
|
|
|
2
|
|
|
|
3
|
Source-controlled SSH routing and wrapper configuration for the Next-Gen jump
|
|
|
4
|
infrastructure.
|
|
|
5
|
|
|
|
6
|
## Runtime vs project
|
|
|
7
|
|
|
|
8
|
- Project source: `~/Documents/Workspaces/Bogdan/ssh-infrastructure`
|
|
|
9
|
- OpenSSH runtime: `~/.ssh`
|
|
|
10
|
|
|
|
11
|
Keep secrets and machine-local state out of this repository:
|
|
|
12
|
|
|
|
13
|
- private keys: `~/.ssh/keys/`
|
|
|
14
|
- `authorized_keys`
|
|
|
15
|
- `known_hosts`
|
|
|
16
|
- socket or agent state
|
|
|
17
|
|
|
|
18
|
The runtime `~/.ssh/config` is a generated single-file OpenSSH config. The
|
|
|
19
|
project is the place to edit wrappers, documentation, inventory, and generator
|
|
|
20
|
code.
|
|
|
21
|
|
|
|
22
|
Deploy the local runtime copy with:
|
|
|
23
|
|
|
|
24
|
```bash
|
|
|
25
|
tools/deploy-local.sh
|
|
|
26
|
```
|
|
|
27
|
|
|
|
28
|
The deploy script generates `generated/client.conf`, installs it as
|
|
|
29
|
`~/.ssh/config`, and installs the wrapper commands into `~/.local/bin`.
|
|
|
30
|
It does not touch keys, `authorized_keys`, or `known_hosts`.
|
|
|
31
|
|
|
|
32
|
## Version control
|
|
|
33
|
|
|
|
34
|
This directory is the git repository for source files only. Generated configs,
|
|
|
35
|
local state, keys, known hosts, and handoff notes stay out of version control.
|
|
|
36
|
|
|
|
37
|
Track source changes with:
|
|
|
38
|
|
|
|
39
|
```bash
|
|
|
40
|
git status
|
|
|
41
|
git add inventory schema scripts tools .doc README.md .gitignore
|
|
|
42
|
git commit
|
|
|
43
|
```
|
|
|
44
|
|
|
Bogdan Timofte
authored
2 weeks ago
|
45
|
## SSH Key Management
|
|
|
46
|
|
|
|
47
|
Modern key migration from legacy infrastructure:
|
|
|
48
|
|
|
|
49
|
```bash
|
|
|
50
|
# Migrate all legacy hosts to modern key (ed25519)
|
|
|
51
|
tools/migrate-modern-key.sh
|
|
|
52
|
|
|
|
53
|
# Migrate specific host
|
|
|
54
|
tools/migrate-modern-key.sh is-baobab
|
|
|
55
|
```
|
|
|
56
|
|
|
|
57
|
See [docs/KEY_MIGRATION.md](docs/KEY_MIGRATION.md) for detailed procedures.
|
|
|
58
|
|
|
Bogdan Timofte
authored
2 weeks ago
|
59
|
## Current client layout
|
|
|
60
|
|
|
|
61
|
```text
|
|
|
62
|
~/.ssh/config
|
|
|
63
|
~/.local/bin/ssh
|
|
|
64
|
~/.local/bin/scp
|
|
|
65
|
~/.local/bin/sftp
|
|
|
66
|
```
|
|
|
67
|
|
|
|
68
|
The wrapper sources stay versioned in `scripts/` inside the project; deploy
|
|
|
69
|
installs executable copies into `~/.local/bin` and removes the obsolete
|
|
|
70
|
`~/.ssh/scripts` runtime layout from older checkouts.
|
|
|
71
|
|
|
|
72
|
## Source of Truth
|
|
|
73
|
|
|
|
74
|
The structured source of truth starts in:
|
|
|
75
|
|
|
|
76
|
```text
|
|
|
77
|
inventory/hosts.yaml
|
|
|
78
|
schema/hosts.schema.json
|
|
|
79
|
tools/generate-configs.py
|
|
|
80
|
```
|
|
|
81
|
|
|
|
82
|
The `generated/*.conf` files are deploy artifacts. They are ignored by git and
|
|
|
83
|
can be recreated at any time with `tools/deploy-local.sh`.
|
|
|
84
|
|
|
|
85
|
## Sync from upstream
|
|
|
86
|
|
|
|
87
|
Pull the upstream inventory, apply this machine's local `is-jumper` key override,
|
|
|
88
|
regenerate, and deploy if the inventory changed:
|
|
|
89
|
|
|
|
90
|
```bash
|
|
|
91
|
tools/sync-hosts-from-upstream.sh
|
|
|
92
|
```
|
|
|
93
|
|
|
|
94
|
Defaults:
|
|
|
95
|
|
|
|
96
|
```text
|
|
|
97
|
UPSTREAM_SSH_TARGET=nextgen@192.168.2.103
|
|
|
98
|
UPSTREAM_HOSTS_PATH=/home/nextgen/projects/ssh-infrastructure/inventory/hosts.yaml
|
|
|
99
|
LOCAL_IS_JUMPER_IDENTITY_FILE=~/.ssh/keys/is-jumper_ed25519
|
|
|
100
|
DEPLOY_AFTER_SYNC=1
|
|
|
101
|
```
|
|
|
102
|
|
|
|
103
|
Useful overrides:
|
|
|
104
|
|
|
|
105
|
```bash
|
|
|
106
|
UPSTREAM_HOSTS_FILE=/tmp/hosts.yaml tools/sync-hosts-from-upstream.sh
|
|
|
107
|
DEPLOY_AFTER_SYNC=0 tools/sync-hosts-from-upstream.sh
|
|
|
108
|
FORCE_DEPLOY=1 tools/sync-hosts-from-upstream.sh
|
|
|
109
|
```
|
|
|
110
|
|
|
|
111
|
Known defaults captured there:
|
|
|
112
|
|
|
|
113
|
- jump hosts default to user `bogdan.timofte`;
|
|
|
114
|
- jump hosts default to port `24`, with explicit overrides such as `25904`;
|
|
|
115
|
- final hosts default to user `bogdan` because most distributions do not like
|
|
|
116
|
dotted local usernames;
|
|
|
117
|
- when imported configs disagree between `bogdan` and `root`, `bogdan` wins;
|
|
|
118
|
- final hosts default to port `22`, with explicit overrides where needed.
|
|
|
119
|
- Cisco/TACACS router entries use `auth: password_interactive`; generated SSH
|
|
|
120
|
config marks them so the wrapper does not force `BatchMode=yes`.
|
|
|
121
|
- Imported IFS devices use the canonical hostname already known on the jump
|
|
|
122
|
servers as client-side `HostName`, while IPs remain available as aliases for
|
|
|
123
|
autocomplete.
|
|
|
124
|
- J1/J2 configs inherit the company-managed global compatibility block and
|
|
|
125
|
selected `Match Host` user/port defaults from the jump servers instead of
|
|
|
126
|
duplicating them in generated output.
|
|
|
127
|
- J1/J2 configs only emit host entries when there is an effective override to
|
|
|
128
|
keep on the jump side; hosts that only use inherited defaults are omitted.
|
|
|
129
|
- J1/J2 generated configs are stripped down to functional SSH stanzas only,
|
|
|
130
|
without generated comments or group annotations.
|