Fix authorized_key key handling

This commit is contained in:
Virgil 2026-04-01 22:24:33 +00:00
parent 11bb1b6a7f
commit c3aa73e065
3 changed files with 33 additions and 9 deletions

View file

@ -1318,9 +1318,9 @@ func moduleAuthorizedKeyWithClient(_ *Executor, client sshRunner, args map[strin
authKeysPath := joinPath(home, ".ssh", "authorized_keys")
if state == "absent" {
// Remove key
escapedKey := replaceAll(key, "/", "\\/")
cmd := sprintf("sed -i '/%s/d' %q 2>/dev/null || true", escapedKey[:40], authKeysPath)
// Remove the exact key line when present.
cmd := sprintf("if [ -f %q ]; then sed -i '\\|^%s$|d' %q; fi",
authKeysPath, sedExactLinePattern(key), authKeysPath)
_, _, _, _ = client.Run(context.Background(), cmd)
return &TaskResult{Changed: true}, nil
}
@ -1331,7 +1331,7 @@ func moduleAuthorizedKeyWithClient(_ *Executor, client sshRunner, args map[strin
// Add key if not present
cmd := sprintf("grep -qF %q %q 2>/dev/null || echo %q >> %q",
key[:40], authKeysPath, key, authKeysPath)
key, authKeysPath, key, authKeysPath)
stdout, stderr, rc, err := client.Run(context.Background(), cmd)
if err != nil || rc != 0 {
return &TaskResult{Failed: true, Msg: stderr, Stdout: stdout, RC: rc}, nil

View file

@ -2585,9 +2585,9 @@ func (e *Executor) moduleAuthorizedKey(ctx context.Context, client sshExecutorCl
authKeysPath := joinPath(home, ".ssh", "authorized_keys")
if state == "absent" {
// Remove key
escapedKey := replaceAll(key, "/", "\\/")
cmd := sprintf("sed -i '/%s/d' %q 2>/dev/null || true", escapedKey[:40], authKeysPath)
// Remove the exact key line when present.
cmd := sprintf("if [ -f %q ]; then sed -i '\\|^%s$|d' %q; fi",
authKeysPath, sedExactLinePattern(key), authKeysPath)
_, _, _, _ = client.Run(ctx, cmd)
return &TaskResult{Changed: true}, nil
}
@ -2596,9 +2596,9 @@ func (e *Executor) moduleAuthorizedKey(ctx context.Context, client sshExecutorCl
_, _, _, _ = client.Run(ctx, sprintf("mkdir -p %q && chmod 700 %q && chown %s:%s %q",
pathDir(authKeysPath), pathDir(authKeysPath), user, user, pathDir(authKeysPath)))
// Add key if not present
// Add the key if it is not already present.
cmd := sprintf("grep -qF %q %q 2>/dev/null || echo %q >> %q",
key[:40], authKeysPath, key, authKeysPath)
key, authKeysPath, key, authKeysPath)
stdout, stderr, rc, err := client.Run(ctx, cmd)
if err != nil || rc != 0 {
return &TaskResult{Failed: true, Msg: stderr, Stdout: stdout, RC: rc}, nil
@ -2611,6 +2611,11 @@ func (e *Executor) moduleAuthorizedKey(ctx context.Context, client sshExecutorCl
return &TaskResult{Changed: true}, nil
}
func sedExactLinePattern(value string) string {
pattern := regexp.QuoteMeta(value)
return replaceAll(pattern, "|", "\\|")
}
func (e *Executor) moduleDockerCompose(ctx context.Context, client sshExecutorClient, args map[string]any) (*TaskResult, error) {
projectSrc := getStringArg(args, "project_src", "")
state := getStringArg(args, "state", "present")

View file

@ -354,6 +354,25 @@ func TestModulesAdv_ModuleAuthorizedKey_Good_AddKey(t *testing.T) {
assert.True(t, mock.containsSubstring("authorized_keys"))
}
func TestModulesAdv_ModuleAuthorizedKey_Good_ShortKeyDoesNotPanic(t *testing.T) {
e, mock := newTestExecutorWithMock("host1")
testKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA short@host"
mock.expectCommand(`getent passwd deploy`, "/home/deploy", "", 0)
mock.expectCommand(`mkdir -p`, "", "", 0)
mock.expectCommand(`grep -qF.*echo`, "", "", 0)
mock.expectCommand(`chmod 600`, "", "", 0)
result, err := moduleAuthorizedKeyWithClient(e, mock, map[string]any{
"user": "deploy",
"key": testKey,
})
require.NoError(t, err)
assert.True(t, result.Changed)
assert.False(t, result.Failed)
assert.True(t, mock.hasExecuted(`grep -qF`))
}
func TestModulesAdv_ModuleAuthorizedKey_Good_RemoveKey(t *testing.T) {
e, mock := newTestExecutorWithMock("host1")
testKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDcT... user@host"