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")
+}
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
}
// 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 {