func (cc *Client) AuthorizedKeysWithMetadata() (*Keys, error) {
	s, err := cc.sshSession()
	if err != nil {
		return nil, err
	}
	defer s.Close()
	b, err := s.Output("api-keys")
	if err != nil {
		return nil, err
	}
	var k Keys
	err = json.Unmarshal(b, &k)
	return &k, err
}
AuthorizedKeysWithMetadata fetches keys linked to a user's account, with metadata.
package charm
import (
	"crypto/rsa"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"path/filepath"
	"regexp"
	"sync"
	"time"
	"github.com/meowgorithm/babyenv"
	"github.com/mitchellh/go-homedir"
	gap "github.com/muesli/go-app-paths"
	"github.com/muesli/sasquatch"
	"golang.org/x/crypto/ssh"
	"golang.org/x/crypto/ssh/agent"
)
var nameValidator = regexp.MustCompile("^[a-zA-Z0-9]{1,50}$")
var ErrMissingSSHAuth = errors.New("missing ssh auth")
var ErrNameTaken = errors.New("name already taken")
var ErrNameInvalid = errors.New("invalid name")
var ErrCouldNotUnlinkKey = errors.New("could not unlink key")
type ErrAuthFailed struct {
	Err error
}
func (e ErrAuthFailed) Error() string { return e.Err.Error() }
func (e ErrAuthFailed) Unwrap() error { return e.Err }
type Config struct {
	IDHost   string `env:"CHARM_ID_HOST" default:"id.charm.sh"`
	IDPort   int    `env:"CHARM_ID_PORT" default:"22"`
	BioHost  string `env:"CHARM_BIO_HOST" default:"https://bio.charm.sh"`
	BioPort  int    `env:"CHARM_BIO_PORT" default:"443"`
	GlowHost string `env:"CHARM_GLOW_HOST" default:"https://glow.charm.sh"`
	GlowPort int    `env:"CHARM_GLOW_PORT" default:"443"`
	JWTKey   string `env:"CHARM_JWT_KEY" default:""`
	Debug    bool   `env:"CHARM_DEBUG" default:"false"`
	Logfile  string `env:"CHARM_LOGFILE" default:""`
}
type Client struct {
	config               *Config
	auth                 *Auth
	authLock             *sync.Mutex
	sshConfig            *ssh.ClientConfig
	jwtPublicKey         *rsa.PublicKey
	plainTextEncryptKeys []*EncryptKey
	authKeyPaths         []string
	encryptKeyLock       *sync.Mutex
}
type User struct {
	CharmID   string    `json:"charm_id"`
	Name      string    `json:"name"`
	Email     string    `json:"email"`
	Bio       string    `json:"bio"`
	CreatedAt time.Time `json:"created_at"`
}
type Keys struct {
	ActiveKey int   `json:"active_key"`
	Keys      []Key `json:"keys"`
}
func DataPath() (string, error) {
	scope := gap.NewScope(gap.User, "charm")
	dataPath, err := scope.DataPath("")
	if err != nil {
		return "", err
	}
	return dataPath, nil
}
func ConfigFromEnv() (*Config, error) {
	var cfg Config
	if err := babyenv.Parse(&cfg); err != nil {
		return nil, err
	}
	return &cfg, nil
}
func NewClient(cfg *Config) (*Client, error) {
	cc := &Client{
		config:         cfg,
		auth:           &Auth{},
		authLock:       &sync.Mutex{},
		encryptKeyLock: &sync.Mutex{},
	}
	jk, err := jwtKey(cfg.JWTKey)
	if err != nil {
		return nil, err
	}
	cc.jwtPublicKey = jk
	sshKeys, err := findAuthKeys()
	if err != nil {
		return nil, err
	}
	if len(sshKeys) == 0 {  
		return nil, ErrMissingSSHAuth
	}
	var pkam ssh.AuthMethod
	for i := 0; i < len(sshKeys); i++ {
		pkam, err = publicKeyAuthMethod(sshKeys[i])
		if err != nil && i == len(sshKeys)-1 {
			return nil, ErrMissingSSHAuth
		}
	}
	cc.authKeyPaths = sshKeys
	cc.sshConfig = &ssh.ClientConfig{
		User:            "charm",
		Auth:            []ssh.AuthMethod{pkam},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}
	return cc, nil
}
func (cc *Client) JWT() (string, error) {
	s, err := cc.sshSession()
	if err != nil {
		return "", err
	}
	defer s.Close()
	jwt, err := s.Output("jwt")
	if err != nil {
		return "", err
	}
	return string(jwt), nil
}
func (cc *Client) ID() (string, error) {
	s, err := cc.sshSession()
	if err != nil {
		return "", err
	}
	defer s.Close()
	id, err := s.Output("id")
	if err != nil {
		return "", err
	}
	return string(id), nil
}
func (cc *Client) AuthorizedKeys() (string, error) {
	s, err := cc.sshSession()
	if err != nil {
		return "", err
	}
	defer s.Close()
	keys, err := s.Output("keys")
	if err != nil {
		return "", err
	}
	return string(keys), nil
}