예제 #1
0
func TestCertLogin(t *testing.T) {
	s := newServer(t)
	defer s.Shutdown()

	// Use a key different from the default.
	clientKey := testSigners["dsa"]
	caAuthKey := testSigners["ecdsa"]
	cert := &ssh.Certificate{
		Key:             clientKey.PublicKey(),
		ValidPrincipals: []string{username()},
		CertType:        ssh.UserCert,
		ValidBefore:     ssh.CertTimeInfinity,
	}
	if err := cert.SignCert(rand.Reader, caAuthKey); err != nil {
		t.Fatalf("SetSignature: %v", err)
	}

	certSigner, err := ssh.NewCertSigner(cert, clientKey)
	if err != nil {
		t.Fatalf("NewCertSigner: %v", err)
	}

	conf := &ssh.ClientConfig{
		User: username(),
	}
	conf.Auth = append(conf.Auth, ssh.PublicKeys(certSigner))
	client, err := s.TryDial(conf)
	if err != nil {
		t.Fatalf("TryDial: %v", err)
	}
	client.Close()
}
예제 #2
0
func clientConfig() *ssh.ClientConfig {
	config := &ssh.ClientConfig{
		User: username(),
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(testSigners["user"]),
		},
		HostKeyCallback: hostKeyDB().Check,
	}
	return config
}
예제 #3
0
func (c *BaseCluster) sshConfig() (*ssh.ClientConfig, error) {
	signer, err := ssh.NewSignerFromKey(c.SSHKey.PrivateKey)
	if err != nil {
		return nil, err
	}
	sshConfig := &ssh.ClientConfig{
		User: c.SSHUsername,
		Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
	}
	return sshConfig, nil
}
예제 #4
0
func (c *SSHCluster) importSSHKeyPair(t *TargetServer) error {
	var buf bytes.Buffer
	_, file, readFileErrChan := c.base.PromptFileInput(fmt.Sprintf("Please provide your private key for %s@%s", t.User, t.IP))
	if _, err := io.Copy(&buf, file); err != nil {
		readFileErrChan <- err
		return err
	}
	readFileErrChan <- nil // no error reading file
	b, _ := pem.Decode(buf.Bytes())
	if b == nil {
		return fmt.Errorf("Invalid private key")
	}
	var pemBytes []byte
	if x509.IsEncryptedPEMBlock(b) {
		passphrase := c.base.PromptProtectedInput("Please enter the passphrase for the key")
		var err error
		pemBytes, err = x509.DecryptPEMBlock(b, []byte(passphrase))
		if err != nil {
			return err
		}
	} else {
		pemBytes = b.Bytes
	}
	privateKey, err := x509.ParsePKCS1PrivateKey(pemBytes)
	if err != nil {
		return err
	}

	signer, err := ssh.NewSignerFromKey(privateKey)
	if err != nil {
		return err
	}
	auth := []ssh.AuthMethod{ssh.PublicKeys(signer)}

	sshConfig := c.sshConfigForAuth(t, auth)

	c.base.SendLog(fmt.Sprintf("Testing provided key for %s@%s", t.User, t.IP))
	if !c.testAndAddAuthentication(t, sshConfig) {
		return fmt.Errorf("Provided key for %s@%s failed to authenticate", t.User, t.IP)
	}
	c.base.SendLog(fmt.Sprintf("Key verified for %s@%s", t.User, t.IP))
	return nil
}
예제 #5
0
파일: ssh_cluster.go 프로젝트: devick/flynn
func (c *SSHCluster) findSSHAuth() error {
	c.base.SendLog("Detecting authentication")

	testAndAddAuthMethod := func(t *TargetServer, a ssh.AuthMethod) bool {
		sshConfig := c.sshConfigForAuth(t, []ssh.AuthMethod{a})
		if c.testAndAddAuthentication(t, sshConfig) {
			c.base.SendLog(fmt.Sprintf("Verified authentication for %s@%s", t.User, t.IP))
			return true
		}
		return false
	}

	testAndAddSigner := func(t *TargetServer, s ssh.Signer) bool {
		return testAndAddAuthMethod(t, ssh.PublicKeys(s))
	}

	testAllAuthenticated := func(targets []*TargetServer) bool {
		for _, t := range targets {
			if t.SSHConfig == nil {
				return false
			}
		}
		return true
	}

	sshAgent := c.sshAgent()
	sshAgentAuth := ssh.PublicKeysCallback(sshAgent.Signers)
	for _, t := range c.Targets {
		testAndAddAuthMethod(t, sshAgentAuth)
	}

	if testAllAuthenticated(c.Targets) {
		return nil
	}

	var agentKeys [][]byte
	if keys, err := sshAgent.List(); err == nil {
		agentKeys = make([][]byte, len(keys))
		for i, k := range keys {
			agentKeys[i] = k.Marshal()
		}
	}

	var signers []privateKeySigner

signerloop:
	for _, s := range c.findSSHKeySigners() {
		if s.publicKey != nil {
			for _, k := range agentKeys {
				if bytes.Equal(k, s.publicKey.Marshal()) {
					continue signerloop
				}
			}
		}
		signers = append(signers, s)
	}

outer:
	for _, t := range c.Targets {
		if t.SSHConfig != nil {
			continue
		}
		for _, s := range signers {
			if s.Encrypted {
				if s.publicKey == nil {
					signer, err := s.Decrypt()
					if err != nil {
						continue
					}
					if testAndAddSigner(t, signer) {
						continue outer
					}
				} else {
					if testAndAddSigner(t, s) {
						continue outer
					}
				}
			} else {
				signer, err := ssh.NewSignerFromKey(s.key)
				if err != nil {
					continue
				}
				if testAndAddSigner(t, signer) {
					continue outer
				}
			}
		}
	}

	for _, t := range c.Targets {
		if t.SSHConfig != nil {
			continue
		}
		answer, err := c.base.ChoicePrompt(Choice{
			Message: "No working authentication found.\nPlease choose one of the following options:",
			Options: []ChoiceOption{
				{
					Type:  1,
					Name:  "Private key",
					Value: "1",
				},
				{
					Name:  "Password",
					Value: "2",
				},
				{
					Name:  "Abort",
					Value: "3",
				},
			},
		})
		if err != nil {
			return err
		}
		switch answer {
		case "1":
			if err := c.importSSHKeyPair(t); err != nil {
				return err
			} else {
				continue
			}
		case "2":
			password := c.base.PromptProtectedInput(fmt.Sprintf("Please enter your password for %s@%s", t.User, t.IP))
			if testAndAddAuthMethod(t, ssh.Password(password)) {
				continue
			}
		}
		return fmt.Errorf("No working authentication found")
	}
	return nil
}