Merge branch '15026-cloudtest'
[arvados.git] / lib / dispatchcloud / worker / verify.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package worker
6
7 import (
8         "bytes"
9         "errors"
10         "fmt"
11
12         "git.curoverse.com/arvados.git/lib/cloud"
13         "golang.org/x/crypto/ssh"
14 )
15
16 var (
17         errBadInstanceSecret = errors.New("bad instance secret")
18
19         // filename on instance, as given to shell (quoted accordingly)
20         instanceSecretFilename = "/var/run/arvados-instance-secret"
21         instanceSecretLength   = 40 // hex digits
22 )
23
24 type TagVerifier struct {
25         cloud.Instance
26         Secret string
27 }
28
29 func (tv TagVerifier) InitCommand() cloud.InitCommand {
30         return cloud.InitCommand(fmt.Sprintf("umask 0177 && echo -n %q >%s", tv.Secret, instanceSecretFilename))
31 }
32
33 func (tv TagVerifier) VerifyHostKey(pubKey ssh.PublicKey, client *ssh.Client) error {
34         if err := tv.Instance.VerifyHostKey(pubKey, client); err != cloud.ErrNotImplemented || tv.Secret == "" {
35                 // If the wrapped instance indicates it has a way to
36                 // verify the key, return that decision.
37                 return err
38         }
39         session, err := client.NewSession()
40         if err != nil {
41                 return err
42         }
43         defer session.Close()
44         var stdout, stderr bytes.Buffer
45         session.Stdin = bytes.NewBuffer(nil)
46         session.Stdout = &stdout
47         session.Stderr = &stderr
48         cmd := fmt.Sprintf("cat %s", instanceSecretFilename)
49         if u := tv.RemoteUser(); u != "root" {
50                 cmd = "sudo " + cmd
51         }
52         err = session.Run(cmd)
53         if err != nil {
54                 return err
55         }
56         if stdout.String() != tv.Secret {
57                 return errBadInstanceSecret
58         }
59         return nil
60 }