charm

package module
v0.8.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 6, 2020 License: MIT Imports: 27 Imported by: 7

README

Charm

Manage your Charm account and access The Charm Cloud.

Charm Tool Header Treatment
Latest Release GoDoc Build Status

Charm UI Trailer

Installation

macOS and Linux users can use Homebrew:

brew tap charmbracelet/tap && brew install charmbracelet/tap/charm

Or you can download a binary from the releases page. macOS, Linux, FreeBSD binaries are available, as well as Debian and RPM packages. ARM builds are also available for Linux and FreeBSD.

Or just use go get:

go get github.com/charmbracelet/charm/cmd/charm

Bash/Zsh/Fish completion is also available. See charm help completion.

Usage

Run without arguments for the TUI. Or, for shortcuts and additional functionality see the CLI usage at charm help.

Encryption and Decryption

The Charm Tool (and Charm library) includes a simple, powerful encryption interface. Data encrypted with Charm is decryptable only by machines linked to your Charm account. Even we couldn’t decrypt your data if we somehow got our hands on it.

# Encryption is easy
echo "Secret message" | charm encrypt

# Save an encrypted message to disk
echo "Secret message" | charm encrypt > secret_message.json

# Decryption is easy too
cat secret_message.json | charm decrypt

# You can encrypt any kind of data
charm encrypt < my_secret_photo.jpg > encrypted_photo.json

# Encrypt and compress
charm encrypt < secret_document.md | gzip > encrypted_document.json.gz

# Decompress, decrypt, and read wth Glow
gunzip encrypted_document.json.gz | charm decrypt | glow -p -
How It Works

Encryption works by issuing symmetric keys (basically a generated password) and encrypting it with the local SSH public key generated by this library. That encrypted key is then sent up to our server. We can’t read it since we don’t have your private key. When you want to decrypt something or view your stash, that key is downloaded from our server and decrypted locally using the SSH private key. When you link accounts, the symmetric key is encrypted for each new public key. This happens on your machine and not our server, so we never see any unencrypted data.

The Library

The Charm library is a simple API to the Charm Cloud for doing things like:

  • Frictionless user identification
  • User accounts linking
  • Encrypt and decrypt data
  • Simple SSH key generation
  • Programatically read, write and delete from a user’s Glow markdown stash

For more details and the full feature set check out the Go docs.

Charming Projects

Check out these projects, which use the charm library:

  • Glow, a markdown reader for the CLI

License

MIT


A Charm project.

the Charm logo

Charm热爱开源! / Charm loves open source!

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrCouldNotUnlinkKey = errors.New("could not unlink key")

ErrCouldNotUnlinkKey is used when a key can't be deleted.

View Source
var ErrMalformedKey = errors.New("malformed key; is it missing the algorithm type at the beginning?")

ErrMalformedKey parsing error for bad ssh key.

View Source
var ErrMissingSSHAuth = errors.New("missing ssh auth")

ErrMissingSSHAuth is used when the user is missing SSH credentials.

View Source
var ErrNameInvalid = errors.New("invalid name")

ErrNameInvalid is used when a username is invalid.

View Source
var ErrNameTaken = errors.New("name already taken")

ErrNameTaken is used when a user attempts to set a username and that username is already taken.

View Source
var ErrorPageOutOfBounds = errors.New("page must be a value of 1 or greater")

ErrorPageOutOfBounds is an error for an invalid page number.

Functions

func DataPath

func DataPath() (string, error)

DataPath returns the Charm data path for the current user. This is where Charm keys are stored.

func ValidateName

func ValidateName(name string) bool

ValidateName validates a given name.

Types

type Auth

type Auth struct {
	CharmID     string        `json:"charm_id"`
	JWT         string        `json:"jwt"`
	PublicKey   string        `json:"public_key"`
	EncryptKeys []*EncryptKey `json:"encrypt_keys"`
	// contains filtered or unexported fields
}

Auth is the authenticated user's charm id and jwt returned from the ssh server.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is the Charm client.

func NewClient

func NewClient(cfg *Config) (*Client, error)

NewClient creates a new Charm client.

func (*Client) Auth

func (cc *Client) Auth() (*Auth, error)

Auth returns the Auth struct for a client session. It will renew and cache the Charm ID JWT.

func (*Client) AuthKeyPaths

func (cc *Client) AuthKeyPaths() []string

AuthKeyPaths returns the full file path of the Charm auth SSH keys.

func (*Client) AuthedRequest

func (cc *Client) AuthedRequest(method string, host string, port int, path string, reqBody interface{}, respBody interface{}) error

AuthedRequest sends an authorized request to the Charm and Glow HTTP servers.

func (*Client) AuthorizedKeys

func (cc *Client) AuthorizedKeys() (string, error)

AuthorizedKeys returns the keys linked to a user's account.

func (*Client) AuthorizedKeysWithMetadata

func (cc *Client) AuthorizedKeysWithMetadata() (*Keys, error)

AuthorizedKeysWithMetadata fetches keys linked to a user's account, with metadata.

func (*Client) Bio

func (cc *Client) Bio() (*User, error)

Bio returns the user's profile.

func (*Client) Decrypt

func (cc *Client) Decrypt(gid string, content []byte) ([]byte, error)

Decrypt decrypts bytes with a given encrypt key ID.

func (*Client) DeleteMarkdown

func (cc *Client) DeleteMarkdown(markdownID int) error

DeleteMarkdown deletes the stash markdown for the given ID.

func (*Client) Encrypt

func (cc *Client) Encrypt(content []byte) ([]byte, string, error)

Encrypt encrypts bytes with the default encrypt key, returning the encrypted bytes, encrypt key ID and error.

func (*Client) EncryptWithKey

func (cc *Client) EncryptWithKey(id string, content []byte) ([]byte, string, error)

EncryptWithKey encrypts bytes with a given encrypt key ID, returning the encrypted bytes, encrypt key ID and error.

func (*Client) GetNews

func (cc *Client) GetNews(page int) ([]*Markdown, error)

GetNews returns the Glow paginated news results.

func (*Client) GetNewsMarkdown

func (cc *Client) GetNewsMarkdown(markdownID int) (*Markdown, error)

GetNewsMarkdown returns the Markdown struct for the given news markdown ID.

func (*Client) GetStash

func (cc *Client) GetStash(page int) ([]*Markdown, error)

GetStash returns the paginated user stash for the authenticated Charm user.

func (*Client) GetStashMarkdown

func (cc *Client) GetStashMarkdown(markdownID int) (*Markdown, error)

GetStashMarkdown returns the Markdown struct for the given stash markdown ID.

func (*Client) ID

func (cc *Client) ID() (string, error)

ID returns the user's ID.

func (*Client) InvalidateAuth

func (cc *Client) InvalidateAuth()

InvalidateAuth clears the JWT auth cache, forcing subsequent Auth() to fetch a new JWT from the server.

func (*Client) JWT

func (cc *Client) JWT() (string, error)

JWT returns a JSON web token for the user.

func (cc *Client) Link(lh LinkHandler, code string) error

Link joins in on a linking session initiated by LinkGen.

func (*Client) LinkGen

func (cc *Client) LinkGen(lh LinkHandler) error

LinkGen initiates a linking session.

func (*Client) SetMarkdownNote

func (cc *Client) SetMarkdownNote(markdownID int, note string) error

SetMarkdownNote updates the note for a given stash markdown ID.

func (*Client) SetName

func (cc *Client) SetName(name string) (*User, error)

SetName sets the account's username.

func (*Client) StashMarkdown

func (cc *Client) StashMarkdown(note string, body string) (*Markdown, error)

StashMarkdown encrypts and stashes a new markdown file with note.

func (*Client) SyncEncryptKeys

func (cc *Client) SyncEncryptKeys() error

SyncEncryptKeys re-encodes all of the encrypt keys associated for this public key with all other linked publick keys.

func (*Client) UnlinkAuthorizedKey

func (cc *Client) UnlinkAuthorizedKey(key string) error

UnlinkAuthorizedKey removes an authorized key from the user's Charm account.

type Config

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:""`
}

Config contains the Charm client configuration.

func ConfigFromEnv

func ConfigFromEnv() (*Config, error)

ConfigFromEnv loads the configuration from the environment.

type EncryptKey

type EncryptKey struct {
	GlobalID  string `json:"global_id"`
	Key       string `json:"key"`
	PublicKey string `json:"public_key,omitempty"`
}

EncryptKey is the symmetric key used to encrypt data for a Charm user. An encrypt key will be encoded for every public key associated with a user's Charm account.

type ErrAuthFailed

type ErrAuthFailed struct {
	Err error
}

ErrAuthFailed indicates an authentication failure. The underlying error is wrapped.

func (ErrAuthFailed) Error

func (e ErrAuthFailed) Error() string

Error returns the boxed error string.

func (ErrAuthFailed) Unwrap

func (e ErrAuthFailed) Unwrap() error

Unwrap returns the boxed error.

type Fingerprint

type Fingerprint struct {
	Algorithm string
	Type      string
	Value     string
}

Fingerprint is the fingerprint of an SSH key.

func (Fingerprint) String

func (f Fingerprint) String() string

String outputs a string representation of the fingerprint.

type Key

type Key struct {
	Key       string     `json:"key"`
	CreatedAt *time.Time `json:"created_at,omitempty"`
}

Key contains data and metadata for an SSH key.

func (Key) FingerprintSHA256

func (k Key) FingerprintSHA256() (Fingerprint, error)

FingerprintSHA256 returns the algorithm and SHA256 fingerprint for the given key.

func (Key) RandomArt

func (k Key) RandomArt() (string, error)

RandomArt returns the randomart for the given key.

type Keys

type Keys struct {
	ActiveKey int   `json:"active_key"`
	Keys      []Key `json:"keys"`
}

Keys is a server response returned when the user queries for the keys linked to her account.

type Link struct {
	Token         string     `json:"token"`
	RequestPubKey string     `json:"request_pub_key"`
	RequestAddr   string     `json:"request_addr"`
	Host          string     `json:"host"`
	Port          int        `json:"port"`
	Status        LinkStatus `json:"status"`
}

Link is the struct used to communicate state during the account linking process.

type LinkHandler

type LinkHandler interface {
	TokenCreated(*Link)
	TokenSent(*Link)
	ValidToken(*Link)
	InvalidToken(*Link)
	Request(*Link) bool
	RequestDenied(*Link)
	SameUser(*Link)
	Success(*Link)
	Timeout(*Link)
	Error(*Link)
}

LinkHandler handles linking operations.

type LinkStatus

type LinkStatus int

LinkStatus represents a state in the linking process.

const (
	LinkStatusInit LinkStatus = iota
	LinkStatusTokenCreated
	LinkStatusTokenSent
	LinkStatusRequested
	LinkStatusRequestDenied
	LinkStatusSameUser
	LinkStatusDifferentUser
	LinkStatusSuccess
	LinkStatusTimedOut
	LinkStatusError
	LinkStatusValidTokenRequest
	LinkStatusInvalidTokenRequest
)

type LinkerMessage

type LinkerMessage struct {
	Message string `json:"message"`
}

LinkerMessage is used for communicating errors and data in the linking process.

type Markdown

type Markdown struct {
	ID           int       `json:"id"`
	EncryptKeyID string    `json:"encrypt_key_id"`
	Note         string    `json:"note"`
	Body         string    `json:"body,omitempty"`
	CreatedAt    time.Time `json:"created_at"`
}

Markdown is the struct that contains the markdown and note data. If EncryptKeyID is not blank, the content should be assumed to be encrypted. Once decrypted, that field will be blanked.

type MarkdownsByCreatedAtDesc

type MarkdownsByCreatedAtDesc []*Markdown

MarkdownsByCreatedAtDesc sorts markdown documents by date in descending order. It implements sort.Interface for []Markdown based on the CreatedAt field.

func (MarkdownsByCreatedAtDesc) Len

func (m MarkdownsByCreatedAtDesc) Len() int

Sort implementation for MarkdownByCreatedAt.

func (MarkdownsByCreatedAtDesc) Less

func (m MarkdownsByCreatedAtDesc) Less(i, j int) bool

func (MarkdownsByCreatedAtDesc) Swap

func (m MarkdownsByCreatedAtDesc) Swap(i, j int)

type User

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"`
}

User represents a Charm user.

Directories

Path Synopsis
cmd
ui

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL