func (s *ClientKeysSuite) TestPrivateKeyFiles(c *gc.C) { // Create/load client keys. They will be cached in memory: // any files added to the directory will not be considered // unless LoadClientKeys is called again. err := ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, gc.IsNil) checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa") priv, pub, err := ssh.GenerateKey("whatever") c.Assert(err, gc.IsNil) err = ioutil.WriteFile(testing.HomePath(".juju", "ssh", "whatever"), []byte(priv), 0600) c.Assert(err, gc.IsNil) err = ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, gc.IsNil) // The new private key won't be observed until the // corresponding public key exists. checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa") err = ioutil.WriteFile(testing.HomePath(".juju", "ssh", "whatever.pub"), []byte(pub), 0600) c.Assert(err, gc.IsNil) // new keys won't be reported until we call LoadClientKeys again checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub") checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa") err = ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, gc.IsNil) checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub", "~/.juju/ssh/whatever.pub") checkPrivateKeyFiles(c, "~/.juju/ssh/juju_id_rsa", "~/.juju/ssh/whatever") }
func (s *SSHGoCryptoCommandSuite) TestProxyCommand(c *gc.C) { realNetcat, err := exec.LookPath("nc") if err != nil { c.Skip("skipping test, couldn't find netcat: %v") return } netcat := filepath.Join(c.MkDir(), "nc") err = ioutil.WriteFile(netcat, []byte("#!/bin/sh\necho $0 \"$@\" > $0.args && exec "+realNetcat+" \"$@\""), 0755) c.Assert(err, gc.IsNil) private, _, err := ssh.GenerateKey("test-server") c.Assert(err, gc.IsNil) key, err := cryptossh.ParsePrivateKey([]byte(private)) client, err := ssh.NewGoCryptoClient(key) c.Assert(err, gc.IsNil) server := newServer(c) var opts ssh.Options port := server.Addr().(*net.TCPAddr).Port opts.SetProxyCommand(netcat, "-q0", "%h", "%p") opts.SetPort(port) cmd := client.Command("127.0.0.1", testCommand, &opts) server.cfg.PublicKeyCallback = func(conn *cryptossh.ServerConn, user, algo string, pubkey []byte) bool { return true } go server.run(c) out, err := cmd.Output() c.Assert(err, gc.ErrorMatches, "ssh: could not execute command.*") // TODO(axw) when gosshnew is ready, expect reply from server. c.Assert(out, gc.IsNil) // Ensure the proxy command was executed with the appropriate arguments. data, err := ioutil.ReadFile(netcat + ".args") c.Assert(err, gc.IsNil) c.Assert(string(data), gc.Equals, fmt.Sprintf("%s -q0 127.0.0.1 %v\n", netcat, port)) }
func ensureSystemSSHKey(context Context) error { identityFile := context.AgentConfig().SystemIdentityPath() // Don't generate a key unless we have to. keyExists, err := systemKeyExists(identityFile) if err != nil { return fmt.Errorf("failed to check system key exists: %v", err) } if keyExists { return nil } privateKey, publicKey, err := ssh.GenerateKey(config.JujuSystemKey) if err != nil { return fmt.Errorf("failed to create system key: %v", err) } // Write new authorised key. keyManager := keymanager.NewClient(context.APIState()) errResults, err := keyManager.AddKeys(config.JujuSystemKey, publicKey) apiErr := err if apiErr == nil { apiErr = errResults[0].Error } if err != nil || errResults[0].Error != nil { return fmt.Errorf("failed to update authoised keys with new system key: %v", apiErr) } return ioutil.WriteFile(identityFile, []byte(privateKey), 0600) }
func (s *SSHGoCryptoCommandSuite) TestNewGoCryptoClient(c *gc.C) { _, err := ssh.NewGoCryptoClient() c.Assert(err, gc.IsNil) private, _, err := ssh.GenerateKey("test-client") c.Assert(err, gc.IsNil) key, err := cryptossh.ParsePrivateKey([]byte(private)) c.Assert(err, gc.IsNil) _, err = ssh.NewGoCryptoClient(key) c.Assert(err, gc.IsNil) }
func (s *GenerateSuite) TestGenerate(c *gc.C) { defer overrideGenerateKey(c).Restore() private, public, err := ssh.GenerateKey("some-comment") c.Check(err, gc.IsNil) c.Check(private, jc.HasPrefix, "-----BEGIN RSA PRIVATE KEY-----\n") c.Check(private, jc.HasSuffix, "-----END RSA PRIVATE KEY-----\n") c.Check(public, jc.HasPrefix, "ssh-rsa ") c.Check(public, jc.HasSuffix, " some-comment\n") }
func newServer(c *gc.C) *sshServer { private, _, err := ssh.GenerateKey("test-server") c.Assert(err, gc.IsNil) key, err := cryptossh.ParsePrivateKey([]byte(private)) c.Assert(err, gc.IsNil) server := &sshServer{ cfg: &cryptossh.ServerConfig{}, } server.cfg.AddHostKey(key) server.Listener, err = cryptossh.Listen("tcp", "127.0.0.1:0", server.cfg) c.Assert(err, gc.IsNil) return server }
// GenerateSystemSSHKey creates a new key for the system identity. The // authorized_keys in the environment config is updated to include the public // key for the generated key. func GenerateSystemSSHKey(env environs.Environ) (privateKey string, err error) { logger.Debugf("generate a system ssh key") // Create a new system ssh key and add that to the authorized keys. privateKey, publicKey, err := ssh.GenerateKey(config.JujuSystemKey) if err != nil { return "", fmt.Errorf("failed to create system key: %v", err) } authorized_keys := config.ConcatAuthKeys(env.Config().AuthorizedKeys(), publicKey) newConfig, err := env.Config().Apply(map[string]interface{}{ config.AuthKeysConfig: authorized_keys, }) if err != nil { return "", fmt.Errorf("failed to create new config: %v", err) } if err = env.SetConfig(newConfig); err != nil { return "", fmt.Errorf("failed to set new config: %v", err) } return privateKey, nil }
func (s *ClientKeysSuite) TestPublicKeyFiles(c *gc.C) { // LoadClientKeys will create the specified directory // and populate it with a key pair. err := ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, gc.IsNil) checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub") // All files ending with .pub in the client key dir get picked up. priv, pub, err := ssh.GenerateKey("whatever") c.Assert(err, gc.IsNil) err = ioutil.WriteFile(testing.HomePath(".juju", "ssh", "whatever.pub"), []byte(pub), 0600) c.Assert(err, gc.IsNil) err = ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, gc.IsNil) // The new public key won't be observed until the // corresponding private key exists. checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub") err = ioutil.WriteFile(testing.HomePath(".juju", "ssh", "whatever"), []byte(priv), 0600) c.Assert(err, gc.IsNil) err = ssh.LoadClientKeys("~/.juju/ssh") c.Assert(err, gc.IsNil) checkPublicKeyFiles(c, "~/.juju/ssh/juju_id_rsa.pub", "~/.juju/ssh/whatever.pub") }
func (s *SSHGoCryptoCommandSuite) TestCommand(c *gc.C) { private, _, err := ssh.GenerateKey("test-server") c.Assert(err, gc.IsNil) key, err := cryptossh.ParsePrivateKey([]byte(private)) client, err := ssh.NewGoCryptoClient(key) c.Assert(err, gc.IsNil) server := newServer(c) var opts ssh.Options opts.SetPort(server.Addr().(*net.TCPAddr).Port) cmd := client.Command("127.0.0.1", testCommand, &opts) checkedKey := false server.cfg.PublicKeyCallback = func(conn *cryptossh.ServerConn, user, algo string, pubkey []byte) bool { c.Check(pubkey, gc.DeepEquals, cryptossh.MarshalPublicKey(key.PublicKey())) checkedKey = true return true } go server.run(c) out, err := cmd.Output() c.Assert(err, gc.ErrorMatches, "ssh: could not execute command.*") // TODO(axw) when gosshnew is ready, expect reply from server. c.Assert(out, gc.IsNil) c.Assert(checkedKey, jc.IsTrue) }