// LoadClientKeys loads the client SSH keys from the // specified directory, and caches them as a process-wide // global. If the directory does not exist, it is created; // if the directory did not exist, or contains no keys, it // is populated with a new key pair. // // If the directory exists, then all pairs of files where one // has the same name as the other + ".pub" will be loaded as // private/public key pairs. // // Calls to LoadClientKeys will clear the previously loaded // keys, and recompute the keys. func LoadClientKeys(dir string) error { clientKeysMutex.Lock() defer clientKeysMutex.Unlock() dir, err := utils.NormalizePath(dir) if err != nil { return err } if _, err := os.Stat(dir); err == nil { keys, err := loadClientKeys(dir) if err != nil { return err } else if len(keys) > 0 { clientKeys = keys return nil } // Directory exists but contains no keys; // fall through and create one. } if err := os.MkdirAll(dir, 0700); err != nil { return err } keyfile, key, err := generateClientKey(dir) if err != nil { os.RemoveAll(dir) return err } clientKeys = map[string]ssh.Signer{keyfile: key} return nil }
// Read returns the contents of the file. func (f *FileVar) Read(ctx *Context) ([]byte, error) { if f.Path == "" { return nil, ErrNoPath } path, err := utils.NormalizePath(f.Path) if err != nil { return nil, err } return ioutil.ReadFile(ctx.AbsPath(path)) }
func (s *ConfigSuite) TestPrepareWithDefaultKeyFile(c *gc.C) { ctx := coretesting.Context(c) // By default "private-key-path isn't set until after validateConfig has been called. attrs := validAttrs().Delete("private-key-path", "private-key") keyFilePath, err := utils.NormalizePath(jp.DefaultPrivateKey) c.Assert(err, gc.IsNil) err = ioutil.WriteFile(keyFilePath, []byte(testPrivateKey), 400) c.Assert(err, gc.IsNil) defer os.Remove(keyFilePath) testConfig := newConfig(c, attrs) preparedConfig, err := jp.Provider.Prepare(ctx, testConfig) c.Assert(err, gc.IsNil) attrs = preparedConfig.Config().AllAttrs() c.Check(attrs["private-key-path"], gc.Equals, jp.DefaultPrivateKey) c.Check(attrs["private-key"], gc.Equals, testPrivateKey) }
func opensshOptions(options *Options, commandKind opensshCommandKind) []string { args := append([]string{}, opensshCommonOptions...) if options == nil { options = &Options{} } if len(options.proxyCommand) > 0 { args = append(args, "-o", "ProxyCommand "+utils.CommandString(options.proxyCommand...)) } if !options.passwordAuthAllowed { args = append(args, "-o", "PasswordAuthentication no") } if options.allocatePTY { args = append(args, "-t", "-t") // twice to force } identities := append([]string{}, options.identities...) if pk := PrivateKeyFiles(); len(pk) > 0 { // Add client keys as implicit identities identities = append(identities, pk...) } // If any identities are specified, the // default ones must be explicitly specified. if len(identities) > 0 { for _, identity := range defaultIdentities { path, err := utils.NormalizePath(identity) if err != nil { logger.Warningf("failed to normalize path %q: %v", identity, err) continue } if _, err := os.Stat(path); err == nil { identities = append(identities, path) } } } for _, identity := range identities { args = append(args, "-i", identity) } if options.port != 0 { port := fmt.Sprint(options.port) if commandKind == scpKind { // scp uses -P instead of -p (-p means preserve). args = append(args, "-P", port) } else { args = append(args, "-p", port) } } return args }
// ReadAuthorizedKeys implements the standard juju behaviour for finding // authorized_keys. It returns a set of keys in in authorized_keys format // (see sshd(8) for a description). If path is non-empty, it names the // file to use; otherwise the user's .ssh directory will be searched. // Home directory expansion will be performed on the path if it starts with // a ~; if the expanded path is relative, it will be interpreted relative // to $HOME/.ssh. // // The result of utils/ssh.PublicKeyFiles will always be prepended to the // result. In practice, this means ReadAuthorizedKeys never returns an // error when the call originates in the CLI. func ReadAuthorizedKeys(path string) (string, error) { files := ssh.PublicKeyFiles() if path == "" { files = append(files, "id_dsa.pub", "id_rsa.pub", "identity.pub") } else { files = append(files, path) } var firstError error var keyData []byte for _, f := range files { f, err := utils.NormalizePath(f) if err != nil { if firstError == nil { firstError = err } continue } if !filepath.IsAbs(f) { f = filepath.Join(utils.Home(), ".ssh", f) } data, err := ioutil.ReadFile(f) if err != nil { if firstError == nil && !os.IsNotExist(err) { firstError = err } continue } keyData = append(keyData, bytes.Trim(data, "\n")...) keyData = append(keyData, '\n') } if len(keyData) == 0 { if firstError == nil { firstError = fmt.Errorf("no public ssh keys found") } return "", firstError } return string(keyData), nil }