示例#1
0
文件: test_cli.go 项目: NeilW/flynn
func (s *CLISuite) TestKey(t *c.C) {
	app := s.newGitRepo(t, "empty")
	t.Assert(app.flynn("create"), Succeeds)

	t.Assert(app.flynn("key", "add", s.sshKeys(t).Pub), Succeeds)

	// calculate fingerprint
	data, err := ioutil.ReadFile(s.sshKeys(t).Pub)
	t.Assert(err, c.IsNil)
	pubKey, _, _, _, err := ssh.ParseAuthorizedKey(data)
	t.Assert(err, c.IsNil)
	digest := md5.Sum(pubKey.Marshal())
	fingerprint := formatKeyID(hex.EncodeToString(digest[:]))

	t.Assert(app.flynn("key"), SuccessfulOutputContains, fingerprint)

	t.Assert(app.git("commit", "--allow-empty", "-m", "should succeed"), Succeeds)
	t.Assert(app.git("push", "flynn", "master"), Succeeds)

	t.Assert(app.flynn("key", "remove", fingerprint), Succeeds)
	t.Assert(app.flynn("key"), c.Not(SuccessfulOutputContains), fingerprint)

	t.Assert(app.git("commit", "--allow-empty", "-m", "should fail"), Succeeds)
	t.Assert(app.git("push", "flynn", "master"), c.Not(Succeeds))

	t.Assert(app.flynn("delete", "--yes"), Succeeds)
}
示例#2
0
func TestAgentForward(t *testing.T) {
	server := newServer(t)
	defer server.Shutdown()
	conn := server.Dial(clientConfig())
	defer conn.Close()

	keyring := agent.NewKeyring()
	keyring.Add(testPrivateKeys["dsa"], nil, "")
	pub := testPublicKeys["dsa"]

	sess, err := conn.NewSession()
	if err != nil {
		t.Fatalf("NewSession: %v", err)
	}
	if err := agent.RequestAgentForwarding(sess); err != nil {
		t.Fatalf("RequestAgentForwarding: %v", err)
	}

	if err := agent.ForwardToAgent(conn, keyring); err != nil {
		t.Fatalf("SetupForwardKeyring: %v", err)
	}
	out, err := sess.CombinedOutput("ssh-add -L")
	if err != nil {
		t.Fatalf("running ssh-add: %v, out %s", err, out)
	}
	key, _, _, _, err := ssh.ParseAuthorizedKey(out)
	if err != nil {
		t.Fatalf("ParseAuthorizedKey(%q): %v", out, err)
	}

	if !bytes.Equal(key.Marshal(), pub.Marshal()) {
		t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub))
	}
}
示例#3
0
func (c *SSHCluster) findSSHKeySigners() (signers []privateKeySigner) {
	keyDir := filepath.Join(c.sshDir())
	if stat, err := os.Stat(keyDir); err != nil || !stat.IsDir() {
		return
	}
	walkFunc := func(path string, info os.FileInfo, err error) error {
		if info.IsDir() {
			return nil
		}
		if strings.HasSuffix(path, ".pub") {
			return nil
		}
		data, err := ioutil.ReadFile(path)
		if err != nil {
			return nil
		}
		b, _ := pem.Decode(data)
		if b == nil {
			return nil
		}
		s := privateKeySigner{
			base:      c.base,
			path:      path,
			pem:       b,
			Encrypted: x509.IsEncryptedPEMBlock(b),
		}
		if s.Encrypted {
			publicKeyPath := fmt.Sprintf("%s.pub", path)
			if stat, err := os.Stat(publicKeyPath); err == nil && !stat.IsDir() {
				if data, err := ioutil.ReadFile(publicKeyPath); err == nil {
					pk, _, _, _, err := ssh.ParseAuthorizedKey(data)
					if err == nil {
						s.publicKey = pk
					}
				}
			}
			signers = append(signers, s)
			return nil
		}
		privateKey, err := x509.ParsePKCS1PrivateKey(b.Bytes)
		if err != nil {
			return nil
		}
		s.key = privateKey
		signers = append(signers, s)
		return nil
	}
	filepath.Walk(keyDir, walkFunc)
	sort.Sort(decryptedFirst(signers))
	return
}
示例#4
0
文件: discovery.go 项目: devick/flynn
func RegisterInstance(info Info) (string, error) {
	data := struct {
		Data Instance `json:"data"`
	}{Instance{
		Name:          info.Name,
		URL:           info.InstanceURL,
		SSHPublicKeys: make([]SSHPublicKey, 0, 4),
		FlynnVersion:  version.String(),
	}}

	for _, t := range []string{"dsa", "rsa", "ecdsa", "ed25519"} {
		keyData, err := ioutil.ReadFile(fmt.Sprintf("/etc/ssh/ssh_host_%s_key.pub", t))
		if err != nil {
			// TODO(titanous): log this?
			continue
		}
		k, _, _, _, err := ssh.ParseAuthorizedKey(keyData)
		if err != nil {
			// TODO(titanous): log this?
			continue
		}
		data.Data.SSHPublicKeys = append(data.Data.SSHPublicKeys, SSHPublicKey{Type: t, Data: k.Marshal()})
	}

	jsonData, err := json.Marshal(&data)
	if err != nil {
		return "", err
	}
	// TODO(titanous): retry
	uri := info.ClusterURL + "/instances"
	res, err := http.Post(uri, "application/json", bytes.NewReader(jsonData))
	if err != nil {
		return "", err
	}
	if res.StatusCode != http.StatusCreated && res.StatusCode != http.StatusConflict {
		return "", urlError("POST", uri, res.StatusCode)
	}
	if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
		return "", err
	}
	return data.Data.ID, nil
}
示例#5
0
func (S) TestMixedKeyTypes(c *C) {
	const sep = " "
	var input bytes.Buffer

	ipAddress := "192.0.2.203"

	// ECDSA
	ecdsaKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte("ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAN1At7ODzOADlqMknviOG5GRHjVy53PPC1DVhun2pMhzCjNgHMt/XvRaeMKhRvUUaUVaNLmCBi75B/2KJH289g="))
	c.Assert(err, IsNil)
	c.Assert(ecdsaKey, NotNil)
	input.WriteString("|1|apo1+O3sutQ2AxrFoUgiucqL2vs=|fQljlEPB/ICE1TT7VMBYqQhiq+w= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAN1At7ODzOADlqMknviOG5GRHjVy53PPC1DVhun2pMhzCjNgHMt/XvRaeMKhRvUUaUVaNLmCBi75B/2KJH289g=") // hashed entry for 192.0.2.203:22

	// RSA
	rsaKey := genPublicKey(c)

	k, err := Unmarshal(&input)
	c.Assert(err, IsNil)

	c.Assert(k.HostKeyCallback(net.JoinHostPort(ipAddress, "22"), &net.TCPAddr{Port: 22}, ecdsaKey), IsNil)
	c.Assert(k.HostKeyCallback(net.JoinHostPort(ipAddress, "22"), &net.TCPAddr{Port: 22}, rsaKey), Equals, HostNotFoundError) // wrong key type
}
示例#6
0
文件: key.go 项目: suifing/flynn
func (r *KeyRepo) Add(data interface{}) error {
	key := data.(*ct.Key)

	if key.Key == "" {
		return errors.New("controller: key must not be blank")
	}

	pubKey, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(key.Key))
	if err != nil {
		return err
	}

	key.ID = fingerprintKey(pubKey.Marshal())
	key.Key = string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(pubKey)))
	key.Comment = comment

	tx, err := r.db.Begin()
	if err != nil {
		return err
	}

	err = tx.QueryRow("INSERT INTO keys (fingerprint, key, comment) VALUES ($1, $2, $3) RETURNING created_at", key.ID, key.Key, key.Comment).Scan(&key.CreatedAt)
	if postgres.IsUniquenessError(err, "") {
		tx.Rollback()
		return nil
	}
	if err != nil {
		tx.Rollback()
		return err
	}
	if err := createEvent(tx.Exec, &ct.Event{
		ObjectID:   key.ID,
		ObjectType: ct.EventTypeKey,
	}, key); err != nil {
		tx.Rollback()
		return err
	}
	return tx.Commit()
}
示例#7
0
func (r *KeyRepo) Add(data interface{}) error {
	key := data.(*ct.Key)

	if key.Key == "" {
		return errors.New("controller: key must not be blank")
	}

	pubKey, comment, _, _, err := ssh.ParseAuthorizedKey([]byte(key.Key))
	if err != nil {
		return err
	}

	key.ID = fingerprintKey(pubKey.Marshal())
	key.Key = string(bytes.TrimSpace(ssh.MarshalAuthorizedKey(pubKey)))
	key.Comment = comment

	err = r.db.QueryRow("INSERT INTO keys (fingerprint, key, comment) VALUES ($1, $2, $3) RETURNING created_at", key.ID, key.Key, key.Comment).Scan(&key.CreatedAt)
	if e, ok := err.(*pq.Error); ok && e.Code.Name() == "unique_violation" {
		return nil
	}
	return err
}
示例#8
0
func parseHosts(line string) (*Line, error) {
	const whitespace = "\t "

	l := &Line{
		Revoked:       false,
		CertAuthority: false,
	}

	line = strings.TrimLeft(line, whitespace)
	line = strings.TrimRight(line, whitespace)

	nextPart := func(line string) (string, string, error) {
		i := strings.IndexAny(line, whitespace)
		if i < 0 {
			return "", "", fmt.Errorf("knownhosts: Invalid line: %s", line)
		}
		return line[0:i], strings.TrimLeft(line[i:], whitespace), nil
	}

	// ignore empty lines and comments
	if line == "" || line[0] == '#' {
		return nil, nil
	}

	// parse flags
	if line[0] == '@' {
		var flag string
		var err error
		flag, line, err = nextPart(line)
		if err != nil {
			return nil, err
		}
		flag = flag[1:] // trim @

		switch flag {
		case "revoked":
			l.Revoked = true
		case "cert-authority":
			l.CertAuthority = true
		default:
			return nil, fmt.Errorf("knownhosts: Unknown flag @%s", flag)
		}
	}

	// parse hosts
	{
		var part string
		var err error
		part, line, err = nextPart(line)
		if err != nil {
			return nil, err
		}
		if part != "" && part[0] == '|' {
			hash, err := parseHostHash(part)
			if err != nil {
				return nil, fmt.Errorf("knownhosts: Error parsing hashed host: %#v: %s", part, err)
			}
			l.Hosts = append(l.Hosts, &Host{
				Hash: hash,
				Port: "22",
				line: l,
			})
		} else {
			for _, h := range strings.Split(part, ",") {
				host, err := parseHost(h)
				if err != nil {
					return nil, fmt.Errorf("knownhosts: Error parsing host: %#v: %s", h, err)
				} else {
					host.line = l
					l.Hosts = append(l.Hosts, host)
				}
			}
		}
	}

	// the remainder is the key
	key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(line))
	if err != nil {
		return nil, err
	}
	l.PublicKey = key

	return l, nil
}