Use single persistent ssh key for all machines

Changes SSH key behavior such that there is a single persisted key for all
machines across all providers. If there is no key that is located at
`.local/share/containers/podman/machine/` then it is created. The keys are
not deleted when the last machine on the host is removed.

The main motivation for this change is it leads to fewer files created on the
host as a result of vm configuration. Having `n` machines on your system doesn't
result in `2n` machine-related files in `.ssh` on your system anymore.

As a result of ssh keys being persisted by default, the `--save-keys` flag
on `podman machine rm` will no longer be supported.

Signed-off-by: Jake Correnti <jakecorrenti+github@proton.me>
This commit is contained in:
Jake Correnti
2024-01-04 13:35:36 -05:00
parent 753bdc39ba
commit b01a330d37
15 changed files with 101 additions and 88 deletions

View File

@ -3,6 +3,7 @@ package e2e_test
import (
"fmt"
"os"
"path/filepath"
"github.com/containers/podman/v4/pkg/machine/define"
. "github.com/onsi/ginkgo/v2"
@ -80,7 +81,7 @@ var _ = Describe("podman machine rm", func() {
Expect(ec).To(Equal(125))
})
It("machine rm --save-keys, --save-ignition, --save-image", func() {
It("machine rm --save-ignition --save-image", func() {
i := new(initMachine)
session, err := mb.setCmd(i.withImagePath(mb.imagePath)).run()
Expect(err).ToNot(HaveOccurred())
@ -104,7 +105,7 @@ var _ = Describe("podman machine rm", func() {
img := inspectSession.outputToString()
rm := rmMachine{}
removeSession, err := mb.setCmd(rm.withForce().withSaveIgnition().withSaveImage().withSaveKeys()).run()
removeSession, err := mb.setCmd(rm.withForce().withSaveIgnition().withSaveImage()).run()
Expect(err).ToNot(HaveOccurred())
Expect(removeSession).To(Exit(0))
@ -127,4 +128,71 @@ var _ = Describe("podman machine rm", func() {
_, err = os.Stat(img)
Expect(err).ToNot(HaveOccurred())
})
It("Remove machine sharing ssh key with another machine", func() {
expectedIdentityPathSuffix := filepath.Join(".local", "share", "containers", "podman", "machine", define.DefaultIdentityName)
fooName := "foo"
foo := new(initMachine)
session, err := mb.setName(fooName).setCmd(foo.withImagePath(mb.imagePath)).run()
Expect(err).ToNot(HaveOccurred())
Expect(session).To(Exit(0))
barName := "bar"
bar := new(initMachine)
session, err = mb.setName(barName).setCmd(bar.withImagePath(mb.imagePath).withNow()).run()
Expect(err).ToNot(HaveOccurred())
Expect(session).To(Exit(0))
inspectFoo := new(inspectMachine)
inspectFoo = inspectFoo.withFormat("{{.SSHConfig.IdentityPath}}")
inspectSession, err := mb.setName(fooName).setCmd(inspectFoo).run()
Expect(err).ToNot(HaveOccurred())
Expect(inspectSession).To(Exit(0))
Expect(inspectSession.outputToString()).To(ContainSubstring(expectedIdentityPathSuffix))
fooIdentityPath := inspectSession.outputToString()
inspectBar := new(inspectMachine)
inspectBar = inspectBar.withFormat("{{.SSHConfig.IdentityPath}}")
inspectSession, err = mb.setName(barName).setCmd(inspectBar).run()
Expect(err).ToNot(HaveOccurred())
Expect(inspectSession).To(Exit(0))
Expect(inspectSession.outputToString()).To(Equal(fooIdentityPath))
rmFoo := new(rmMachine)
stop, err := mb.setName(fooName).setCmd(rmFoo.withForce()).run()
Expect(err).ToNot(HaveOccurred())
Expect(stop).To(Exit(0))
// removal of foo should not affect the ability to ssh into the bar machine
sshBar := new(sshMachine)
sshSession, err := mb.setName(barName).setCmd(sshBar.withSSHCommand([]string{"echo", "foo"})).run()
Expect(err).ToNot(HaveOccurred())
Expect(sshSession).To(Exit(0))
})
It("Removing all machines doesn't delete ssh keys", func() {
fooName := "foo"
foo := new(initMachine)
session, err := mb.setName(fooName).setCmd(foo.withImagePath(mb.imagePath)).run()
Expect(err).ToNot(HaveOccurred())
Expect(session).To(Exit(0))
inspectFoo := new(inspectMachine)
inspectFoo = inspectFoo.withFormat("{{.SSHConfig.IdentityPath}}")
inspectSession, err := mb.setName(fooName).setCmd(inspectFoo).run()
Expect(err).ToNot(HaveOccurred())
Expect(inspectSession).To(Exit(0))
fooIdentityPath := inspectSession.outputToString()
rmFoo := new(rmMachine)
stop, err := mb.setName(fooName).setCmd(rmFoo.withForce()).run()
Expect(err).ToNot(HaveOccurred())
Expect(stop).To(Exit(0))
_, err = os.Stat(fooIdentityPath)
Expect(err).ToNot(HaveOccurred())
_, err = os.Stat(fooIdentityPath + ".pub")
Expect(err).ToNot(HaveOccurred())
})
})