From e3dc6df1694586eca13f2f20eb064b8b16d115e5 Mon Sep 17 00:00:00 2001 From: Peter Amstutz Date: Fri, 31 Aug 2018 15:55:43 -0400 Subject: [PATCH] 13964: ssh key checking Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- lib/dispatchcloud/azure.go | 52 +++++++++++++++++++++++++++++++++ lib/dispatchcloud/azure_test.go | 13 +-------- lib/dispatchcloud/provider.go | 7 +++++ 3 files changed, 60 insertions(+), 12 deletions(-) diff --git a/lib/dispatchcloud/azure.go b/lib/dispatchcloud/azure.go index 563246eceb..378e8bea39 100644 --- a/lib/dispatchcloud/azure.go +++ b/lib/dispatchcloud/azure.go @@ -588,3 +588,55 @@ func (ai *AzureInstance) Destroy(ctx context.Context) error { func (ai *AzureInstance) Address() string { return *(*ai.nic.IPConfigurations)[0].PrivateIPAddress } + +func (ai *AzureInstance) VerifyPublicKey(ctx context.Context, receivedKey ssh.PublicKey, client *ssh.Client) error { + remoteFingerprint := ssh.FingerprintSHA256(receivedKey) + + tags, _ := ai.Tags(ctx) + + tg := tags["ssh-pubkey-fingerprint"] + if tg != "" { + if remoteFingerprint == tg { + return nil + } else { + return fmt.Errorf("Key fingerprint did not match") + } + } + + sess, err := client.NewSession() + if err != nil { + return err + } + + nodetoken, err := sess.Output("cat /home/crunch/node-token") + if err != nil { + return err + } + + expectedToken := fmt.Sprintf("%s-%s", *ai.vm.Name, tags["node-token"]) + log.Printf("%q %q", string(nodetoken), expectedToken) + + if string(nodetoken) == expectedToken { + sess, err := client.NewSession() + if err != nil { + return err + } + + keyfingerprintbytes, err := sess.Output("ssh-keygen -E sha256 -l -f /etc/ssh/ssh_host_rsa_key.pub") + if err != nil { + return err + } + + sp := strings.Split(string(keyfingerprintbytes), " ") + + log.Printf("%q %q", remoteFingerprint, sp[1]) + + if remoteFingerprint == sp[1] { + tags["ssh-pubkey-fingerprint"] = sp[1] + ai.SetTags(ctx, tags) + return nil + } + } + + return fmt.Errorf("Key fingerprint did not match") +} diff --git a/lib/dispatchcloud/azure_test.go b/lib/dispatchcloud/azure_test.go index 29356f1f7e..568a403a51 100644 --- a/lib/dispatchcloud/azure_test.go +++ b/lib/dispatchcloud/azure_test.go @@ -316,19 +316,8 @@ func SetupSSHClient(c *check.C, inst Instance) (*ssh.Client, error) { return nil, errors.New("BUG: key was never provided to HostKeyCallback") } - log.Printf("receivedKey %v", receivedKey) - log.Printf("fingerprint %v", ssh.FingerprintSHA256(receivedKey)) - tags, err := inst.Tags(context.Background()) + err = inst.VerifyPublicKey(context.Background(), receivedKey, client) c.Assert(err, check.IsNil) - log.Printf("ssh-pubkey %q", tags["ssh-pubkey"]) - - /*if wkr.publicKey == nil || !bytes.Equal(wkr.publicKey.Marshal(), receivedKey.Marshal()) { - err = wkr.instance.VerifyPublicKey(receivedKey, client) - if err != nil { - return nil, err - } - wkr.publicKey = receivedKey - }*/ return client, nil } diff --git a/lib/dispatchcloud/provider.go b/lib/dispatchcloud/provider.go index ed5eb8fe2e..9e3af07676 100644 --- a/lib/dispatchcloud/provider.go +++ b/lib/dispatchcloud/provider.go @@ -57,6 +57,13 @@ type Instance interface { // SSH server hostname or IP address, or empty string if unknown pending creation. Address() string + + // Return nil if the given public key matches the instance's + // SSH server key. If the provided ssh client is not nil, + // VerifyPublicKey can use it to make outgoing network + // connections from the instance -- e.g., to use the cloud's + // "this instance's metadata" API. + VerifyPublicKey(context.Context, ssh.PublicKey, *ssh.Client) error } type InstanceProvider interface { -- 2.30.2