// ListKeys connects to the local SSH Agent and lists all the public keys // loaded into it. It returns user friendly error message when it has trouble. func ListKeys() ([]*agent.Key, error) { sshAuthSock := os.Getenv("SSH_AUTH_SOCK") if sshAuthSock == "" { return nil, fmt.Errorf( "The SSH_AUTH_SOCK environment variable is not set, which normally\n" + "means that no SSH Agent is running.") } conn, err := net.Dial("unix", sshAuthSock) if err != nil { return nil, fmt.Errorf( "Error connecting to agent: %s\n\n"+ "The agent address is detected using the SSH_AUTH_SOCK environment\n"+ "variable. Please verify this variable is correct and the SSH agent\n"+ "is properly set up.", err) } defer conn.Close() agent := agent.NewClient(conn) loadedKeys, err := agent.List() if err != nil { return nil, fmt.Errorf("Error listing keys: %s", err) } return loadedKeys, err }
func getAgentSSHKey() string { // Check to see if we have an SSH agent running. sshAuthSock := os.Getenv("SSH_AUTH_SOCK") d, err := net.Dial("unix", sshAuthSock) if err != nil { return "" } agent := agent.NewClient(d) keys, _ := agent.List() if len(keys) == 0 { return "" } return base64.StdEncoding.EncodeToString(keys[0].Marshal()) }
// ListKeys connects to the local SSH Agent and lists all the public keys // loaded into it. It returns user friendly error message when it has trouble. func ListKeys() ([]*agent.Key, error) { sshAuthSock := os.Getenv("SSH_AUTH_SOCK") if sshAuthSock == "" { return nil, fmt.Errorf( "The SSH_AUTH_SOCK environment variable is not set, which normally\n" + "means that no SSH Agent is running.") } conn, err := net.Dial("unix", sshAuthSock) if err != nil { return nil, fmt.Errorf("Error connecting to agent: %s", err) } defer conn.Close() agent := agent.NewClient(conn) loadedKeys, err := agent.List() if err != nil { return nil, fmt.Errorf("Error listing keys: %s", err) } return loadedKeys, err }
func TestLDAPUserCache(t *testing.T) { Convey("Given an LDAP user cache connected to our server", t, func() { // The SSH agent stuff was moved up here so that we can use it to // dynamically create the LDAP result object. sshSock := os.Getenv("SSH_AUTH_SOCK") if sshSock == "" { t.Skip() } c, err := net.Dial("unix", sshSock) if err != nil { t.Fatal(err) } agent := agent.NewClient(c) keys, err := agent.List() if err != nil { t.Fatal(err) } keyValue := base64.StdEncoding.EncodeToString(keys[0].Blob) // Load in an additional key from the test data. privateKey, _ := ssh.ParsePrivateKey(testKey) testPublicKey := base64.StdEncoding.EncodeToString(privateKey.PublicKey().Marshal()) s := &StubLDAPServer{ Keys: []string{keyValue, testPublicKey}, } lc, err := server.NewLDAPUserCache(s, g2s.Noop(), "cn", "dc=testdn,dc=com") So(err, ShouldBeNil) So(lc, ShouldNotBeNil) Convey("It should retrieve users from LDAP", func() { So(lc.Users(), ShouldNotBeEmpty) }) Convey("It should verify the current user positively.", func() { success := false for i := 0; i < len(keys); i++ { challenge := randomBytes(64) sig, err := agent.Sign(keys[i], challenge) if err != nil { t.Fatal(err) } verifiedUser, err := lc.Authenticate("ericallen", challenge, sig) success = success || (verifiedUser != nil) } So(success, ShouldEqual, true) }) Convey("When a user is requested that cannot be found in the cache", func() { // Use an SSH key we're guaranteed to not have. oldKey := s.Keys[0] s.Keys[0] = testPublicKey lc.Update() // Swap the key back and try verifying. // We should still get a result back. s.Keys[0] = oldKey success := false for i := 0; i < len(keys); i++ { challenge := randomBytes(64) sig, err := agent.Sign(keys[i], challenge) if err != nil { t.Fatal(err) } verifiedUser, err := lc.Authenticate("ericallen", challenge, sig) success = success || (verifiedUser != nil) } Convey("Then it should update LDAP again and find the user.", func() { So(success, ShouldEqual, true) }) }) Convey("When a user with multiple SSH keys assigned tries to use Hologram", func() { Convey("The system should allow them to use any key.", func() { success := false for i := 0; i < len(keys); i++ { challenge := randomBytes(64) sig, err := privateKey.Sign(cryptrand.Reader, challenge) if err != nil { t.Fatal(err) } verifiedUser, err := lc.Authenticate("ericallen", challenge, sig) success = success || (verifiedUser != nil) } So(success, ShouldEqual, true) }) }) testAuthorizedKey := string(ssh.MarshalAuthorizedKey(privateKey.PublicKey())) s = &StubLDAPServer{ Keys: []string{testAuthorizedKey}, } lc, err = server.NewLDAPUserCache(s, g2s.Noop(), "cn", "dc=testdn,dc=com") So(err, ShouldBeNil) So(lc, ShouldNotBeNil) Convey("The usercache should understand the SSH authorized_keys format", func() { challenge := randomBytes(64) sig, err := privateKey.Sign(cryptrand.Reader, challenge) if err != nil { t.Fatal(err) } verifiedUser, err := lc.Authenticate("ericallen", challenge, sig) So(verifiedUser, ShouldNotBeNil) So(err, ShouldBeNil) }) }) }