Merge pull request 'Give the forge an ssh name of its own, so it no longer merges with the operator's entry for its machine (issue 955, ADR 0409)' (#343) from fix/955-forge-ssh-name into main
This commit was merged in pull request #343.
This commit is contained in:
@@ -228,7 +228,7 @@ Gitea provides `forge-account`, and `cmd/forge-account-provider` answers its con
|
||||
machine). The provision has no credential: a public key is no secret. For a machine whose ssh-client has reported its
|
||||
key in the state `keys` (read, `ssh-client.keys`), the provider makes the account `agent-<node>` in the agents team
|
||||
(`internal/forgeaccount`, the code `cmd/agent-token` shares), registers the key under the title `mesh:<node>.<account>`,
|
||||
and serves the entry values `user`, `ssh_host` (the forge machine's mesh name, from the fact `forge-host`), `ssh_port`,
|
||||
and serves the entry values `user`, `ssh_host` (the forge machine's mesh name, from the fact `forge-host`), `ssh_port`, `ssh_alias` (`mesh-forge`, the forge's own name in ssh's configuration, ADR 0409),
|
||||
`known_host` (read from the forge's own sshd with `ssh-keyscan`), `ssh_base` and `https_base`. A machine that has
|
||||
reported no key gets no entry, and its client says it waits. Keys titled `mesh:` that are no longer wanted are removed,
|
||||
a key added by hand never is. Every consumer is made again every ten minutes and at once when a key changes.
|
||||
|
||||
@@ -315,7 +315,7 @@ func TestTheProviderWholeAnswersAMachineThatReportedItsKey(t *testing.T) {
|
||||
return ok
|
||||
})
|
||||
if e.Values["user"] != "agent-g14" || e.Values["ssh_host"] != "novox.internal" ||
|
||||
e.Values["known_host"] != "[novox.internal]:222 ssh-ed25519 AAAAC3HOSTKEY" ||
|
||||
e.Values["known_host"] != "[novox.internal]:222 ssh-ed25519 AAAAC3HOSTKEY" || e.Values["host_key"] != "ssh-ed25519 AAAAC3HOSTKEY" || e.Values["ssh_alias"] != "mesh-forge" ||
|
||||
e.Values["ssh_base"] != "ssh://git@novox.internal:222/" || e.Values["https_base"] != "https://git.novox.be/" {
|
||||
t.Fatalf("values = %v", e.Values)
|
||||
}
|
||||
|
||||
@@ -320,7 +320,12 @@ func (s *Service) scan(ctx context.Context) (string, error) {
|
||||
return knownHostLine(string(out), host, s.cfg.Port)
|
||||
}
|
||||
|
||||
// knownHostLine is the ed25519 line of ssh-keyscan's output with its host written as the mesh name and port.
|
||||
// sshAlias is the forge's own name in ssh's configuration (issue 955, ADR 0409): the machines' ssh-client writes a
|
||||
// Host of this name, so no other Host (the operator's own entry for the forge machine) is merged with it.
|
||||
const sshAlias = "mesh-forge"
|
||||
|
||||
// knownHostLine is the ed25519 line of ssh-keyscan's output with its host written as the mesh name and port. It is
|
||||
// the old value of `known_host`, kept for machines whose ssh-client has not moved to ssh_alias and host_key yet.
|
||||
func knownHostLine(scanned, host string, port int) (string, error) {
|
||||
for _, line := range strings.Split(scanned, "\n") {
|
||||
f := strings.Fields(line)
|
||||
@@ -348,7 +353,11 @@ func (s *Service) valuesFor(node string) (map[string]any, error) {
|
||||
if user == "" || known == "" {
|
||||
return nil, fmt.Errorf("nothing is known to serve %s yet", node)
|
||||
}
|
||||
hostKey := strings.Join(strings.Fields(known)[1:], " ")
|
||||
return map[string]any{"user": user, "ssh_host": host, "ssh_port": s.cfg.Port, "known_host": known,
|
||||
"ssh_alias": sshAlias, "host_key": hostKey,
|
||||
// known_host and ssh_base keep their old values: a machine whose ssh-client has not moved yet renders its old
|
||||
// templates from them. They are dropped in a later change once every machine uses ssh_alias and host_key (ADR 0409).
|
||||
"ssh_base": fmt.Sprintf("ssh://git@%s:%d/", host, s.cfg.Port), "https_base": https}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -240,7 +240,8 @@ func TestAConsumerWithAKeyGetsItsEntryAndItsKeyIsRegistered(t *testing.T) {
|
||||
r.pass()
|
||||
e := r.bus.entry(t, "g14.ssh-client.forge-account")
|
||||
want := map[string]any{"user": "agent-g14", "ssh_host": "novox.internal", "ssh_port": float64(222),
|
||||
"known_host": "[novox.internal]:222 ssh-ed25519 AAAAC3HOSTKEY", "ssh_base": "ssh://git@novox.internal:222/",
|
||||
"known_host": "[novox.internal]:222 ssh-ed25519 AAAAC3HOSTKEY", "ssh_alias": "mesh-forge",
|
||||
"host_key": "ssh-ed25519 AAAAC3HOSTKEY", "ssh_base": "ssh://git@novox.internal:222/",
|
||||
"https_base": "https://git.novox.be/"}
|
||||
for k, v := range want {
|
||||
if e.Values[k] != v {
|
||||
|
||||
@@ -93,7 +93,9 @@ func TestManifestKeepsKeysAndRequiresForgeAccount(t *testing.T) {
|
||||
// Issue 955, area S3: the three files the forge account fills in — known_hosts, the forge's Host, git's rewrite.
|
||||
var sampleBound = map[string]string{
|
||||
"known_host": "[novox.internal]:222 ssh-ed25519 AAAAC3Nza",
|
||||
"host_key": "ssh-ed25519 AAAAC3Nza",
|
||||
"ssh_host": "novox.internal",
|
||||
"ssh_alias": "mesh-forge",
|
||||
"ssh_port": "222",
|
||||
"ssh_base": "ssh://git@novox.internal:222/",
|
||||
"https_base": "https://git.novox.be/",
|
||||
@@ -141,7 +143,7 @@ func TestForgeFilesRenderFromTheBoundValues(t *testing.T) {
|
||||
if kh["into"] != "block" {
|
||||
t.Errorf("known_hosts is %v, want a block", kh["into"])
|
||||
}
|
||||
if got := strings.TrimSpace(renderBound(t, templateText(t, kh))); got != "[novox.internal]:222 ssh-ed25519 AAAAC3Nza" {
|
||||
if got := strings.TrimSpace(renderBound(t, templateText(t, kh))); got != "mesh-forge ssh-ed25519 AAAAC3Nza" {
|
||||
t.Errorf("known_hosts block = %q", got)
|
||||
}
|
||||
|
||||
@@ -149,7 +151,7 @@ func TestForgeFilesRenderFromTheBoundValues(t *testing.T) {
|
||||
if forge["into"] != nil {
|
||||
t.Errorf("10-forge is a block, want the whole file")
|
||||
}
|
||||
want := "Host novox.internal\n Port 222\n User git\n IdentityFile ~/.ssh/mesh_ed25519\n IdentitiesOnly yes\n"
|
||||
want := "Host mesh-forge\n HostName novox.internal\n Port 222\n HostKeyAlias mesh-forge\n User git\n IdentityFile ~/.ssh/mesh_ed25519\n IdentitiesOnly yes\n"
|
||||
if got := renderBound(t, templateText(t, forge)); got != want {
|
||||
t.Errorf("10-forge = %q, want %q", got, want)
|
||||
}
|
||||
@@ -159,7 +161,7 @@ func TestForgeFilesRenderFromTheBoundValues(t *testing.T) {
|
||||
if g["into"] != "block" {
|
||||
t.Errorf("git config is %v, want a block", g["into"])
|
||||
}
|
||||
wantGit := "[url \"ssh://git@novox.internal:222/\"]\n\tinsteadOf = https://git.novox.be/\n"
|
||||
wantGit := "[url \"ssh://mesh-forge/\"]\n\tinsteadOf = https://git.novox.be/\n"
|
||||
if got := renderBound(t, templateText(t, g)); got != wantGit {
|
||||
t.Errorf("git config block = %q, want %q", got, wantGit)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
Host ${bound:forge-account:ssh_host}
|
||||
Host ${bound:forge-account:ssh_alias}
|
||||
HostName ${bound:forge-account:ssh_host}
|
||||
Port ${bound:forge-account:ssh_port}
|
||||
HostKeyAlias ${bound:forge-account:ssh_alias}
|
||||
User git
|
||||
IdentityFile ~/.ssh/mesh_ed25519
|
||||
IdentitiesOnly yes
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[url "${bound:forge-account:ssh_base}"]
|
||||
[url "ssh://${bound:forge-account:ssh_alias}/"]
|
||||
insteadOf = ${bound:forge-account:https_base}
|
||||
|
||||
@@ -1 +1 @@
|
||||
${bound:forge-account:known_host}
|
||||
${bound:forge-account:ssh_alias} ${bound:forge-account:host_key}
|
||||
|
||||
Reference in New Issue
Block a user