github.com/stackdocker/rkt@v0.10.1-0.20151109095037-1aa827478248/stage0/kvm.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package stage0 16 17 import ( 18 "fmt" 19 "io" 20 "os" 21 "os/exec" 22 "path/filepath" 23 ) 24 25 const ( 26 kvmSettingsDir = "/kvm" 27 kvmPrivateKeyFilename = "/ssh_kvm_key" 28 ) 29 30 // fileAccessible checks if the given path exists and is a regular file 31 func fileAccessible(path string) bool { 32 if info, err := os.Stat(path); err == nil { 33 return info.Mode().IsRegular() 34 } 35 return false 36 } 37 38 func kvmSettingsDirPath(dataDir string) string { 39 return filepath.Join(dataDir, kvmSettingsDir) 40 } 41 42 func sshPrivateKeyPath(dataDir string) string { 43 return filepath.Join(kvmSettingsDirPath(dataDir), kvmPrivateKeyFilename) 44 } 45 46 func sshPublicKeyPath(dataDir string) string { 47 return filepath.Join(kvmSettingsDirPath(dataDir), kvmPrivateKeyFilename+".pub") 48 } 49 50 // generateKeyPair calls ssh-keygen with private key location for key generation purpose 51 func generateKeyPair(private string) error { 52 out, err := exec.Command( 53 "ssh-keygen", 54 "-q", // silence 55 "-t", "dsa", // type 56 "-b", "1024", // length in bits 57 "-f", private, // output file 58 "-N", "", // no passphrase 59 ).Output() 60 if err != nil { 61 // out is in form of bytes buffer and we have to turn it into slice ending on first \0 occurence 62 return fmt.Errorf("error in keygen time. ret_val: %v, output: %v", err, string(out[:])) 63 } 64 return nil 65 } 66 67 func ensureKeysExistOnHost(dataDir string) error { 68 private, public := sshPrivateKeyPath(dataDir), sshPublicKeyPath(dataDir) 69 if !fileAccessible(private) || !fileAccessible(public) { 70 if err := os.MkdirAll(kvmSettingsDirPath(dataDir), 0700); err != nil { 71 return err 72 } 73 74 if err := generateKeyPair(private); err != nil { 75 return err 76 } 77 } 78 return nil 79 } 80 81 func ensureAuthorizedKeysExist(keyDirPath, dataDir string) error { 82 fout, err := os.OpenFile( 83 filepath.Join(keyDirPath, "/authorized_keys"), 84 os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 85 0600, 86 ) 87 if err != nil { 88 return err 89 } 90 defer fout.Close() 91 92 fin, err := os.Open(sshPublicKeyPath(dataDir)) 93 if err != nil { 94 return err 95 } 96 defer fin.Close() 97 98 if _, err := io.Copy(fout, fin); err != nil { 99 return err 100 } 101 return fout.Sync() 102 } 103 104 func ensureKeysExistInPod(podRootfsPath, dataDir string) error { 105 keyDirPath := filepath.Join(podRootfsPath, "/root", "/.ssh") 106 if err := os.MkdirAll(keyDirPath, 0700); err != nil { 107 return err 108 } 109 return ensureAuthorizedKeysExist(keyDirPath, dataDir) 110 } 111 112 func kvmCheckSSHSetup(rootfsPath, dataDir string) error { 113 if err := ensureKeysExistOnHost(dataDir); err != nil { 114 return err 115 } 116 return ensureKeysExistInPod(rootfsPath, dataDir) 117 }