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
|
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
|
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>`,
|
(`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
|
`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,
|
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.
|
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
|
return ok
|
||||||
})
|
})
|
||||||
if e.Values["user"] != "agent-g14" || e.Values["ssh_host"] != "novox.internal" ||
|
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/" {
|
e.Values["ssh_base"] != "ssh://git@novox.internal:222/" || e.Values["https_base"] != "https://git.novox.be/" {
|
||||||
t.Fatalf("values = %v", e.Values)
|
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)
|
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) {
|
func knownHostLine(scanned, host string, port int) (string, error) {
|
||||||
for _, line := range strings.Split(scanned, "\n") {
|
for _, line := range strings.Split(scanned, "\n") {
|
||||||
f := strings.Fields(line)
|
f := strings.Fields(line)
|
||||||
@@ -348,7 +353,11 @@ func (s *Service) valuesFor(node string) (map[string]any, error) {
|
|||||||
if user == "" || known == "" {
|
if user == "" || known == "" {
|
||||||
return nil, fmt.Errorf("nothing is known to serve %s yet", node)
|
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,
|
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
|
"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()
|
r.pass()
|
||||||
e := r.bus.entry(t, "g14.ssh-client.forge-account")
|
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),
|
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/"}
|
"https_base": "https://git.novox.be/"}
|
||||||
for k, v := range want {
|
for k, v := range want {
|
||||||
if e.Values[k] != v {
|
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.
|
// 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{
|
var sampleBound = map[string]string{
|
||||||
"known_host": "[novox.internal]:222 ssh-ed25519 AAAAC3Nza",
|
"known_host": "[novox.internal]:222 ssh-ed25519 AAAAC3Nza",
|
||||||
|
"host_key": "ssh-ed25519 AAAAC3Nza",
|
||||||
"ssh_host": "novox.internal",
|
"ssh_host": "novox.internal",
|
||||||
|
"ssh_alias": "mesh-forge",
|
||||||
"ssh_port": "222",
|
"ssh_port": "222",
|
||||||
"ssh_base": "ssh://git@novox.internal:222/",
|
"ssh_base": "ssh://git@novox.internal:222/",
|
||||||
"https_base": "https://git.novox.be/",
|
"https_base": "https://git.novox.be/",
|
||||||
@@ -141,7 +143,7 @@ func TestForgeFilesRenderFromTheBoundValues(t *testing.T) {
|
|||||||
if kh["into"] != "block" {
|
if kh["into"] != "block" {
|
||||||
t.Errorf("known_hosts is %v, want a block", kh["into"])
|
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)
|
t.Errorf("known_hosts block = %q", got)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +151,7 @@ func TestForgeFilesRenderFromTheBoundValues(t *testing.T) {
|
|||||||
if forge["into"] != nil {
|
if forge["into"] != nil {
|
||||||
t.Errorf("10-forge is a block, want the whole file")
|
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 {
|
if got := renderBound(t, templateText(t, forge)); got != want {
|
||||||
t.Errorf("10-forge = %q, want %q", got, want)
|
t.Errorf("10-forge = %q, want %q", got, want)
|
||||||
}
|
}
|
||||||
@@ -159,7 +161,7 @@ func TestForgeFilesRenderFromTheBoundValues(t *testing.T) {
|
|||||||
if g["into"] != "block" {
|
if g["into"] != "block" {
|
||||||
t.Errorf("git config is %v, want a block", g["into"])
|
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 {
|
if got := renderBound(t, templateText(t, g)); got != wantGit {
|
||||||
t.Errorf("git config block = %q, want %q", 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}
|
Port ${bound:forge-account:ssh_port}
|
||||||
|
HostKeyAlias ${bound:forge-account:ssh_alias}
|
||||||
User git
|
User git
|
||||||
IdentityFile ~/.ssh/mesh_ed25519
|
IdentityFile ~/.ssh/mesh_ed25519
|
||||||
IdentitiesOnly yes
|
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}
|
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