13964: ssh key checking
authorPeter Amstutz <pamstutz@veritasgenetics.com>
Fri, 31 Aug 2018 19:55:43 +0000 (15:55 -0400)
committerPeter Amstutz <pamstutz@veritasgenetics.com>
Wed, 9 Jan 2019 21:28:16 +0000 (16:28 -0500)
Arvados-DCO-1.1-Signed-off-by: Peter Amstutz <pamstutz@veritasgenetics.com>

lib/dispatchcloud/azure.go
lib/dispatchcloud/azure_test.go
lib/dispatchcloud/provider.go

index 563246eceb45149e8f975fb71a590c4a76cc998c..378e8bea3985e29b383e15970171096d5b132fe9 100644 (file)
@@ -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")
+}
index 29356f1f7e7574baeb89e215bd9ae0f6a357cd22..568a403a510c554a091f3ffa2791a76e662a7743 100644 (file)
@@ -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
 }
index ed5eb8fe2e318ff9d12656df71c1d5d90e1e771d..9e3af07676595c9ffc3b03cc9064704c586d7b56 100644 (file)
@@ -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 {