Add more env variables

This commit is contained in:
Bernd Schoolmann 2023-08-21 18:37:34 +02:00
parent 6e3859dd43
commit 6d21d10a9e
No known key found for this signature in database
23 changed files with 336 additions and 100 deletions

View File

@ -170,9 +170,25 @@ You can bind this to a hotkey in your desktop environment (i.e i3/sway config fi
### Login with device
Approving other devices works out of the box and is enabled by default. If the agent is unlocked, you will be prompted
to approve the device.
to approve the device. If you want to log into goldwarden using another device, add the "--passwordless" parameter to the login command.
### Environment Variables
```
GOLDWARDEN_WEBSOCKET_DISABLED=true # disable websocket
GOLDWARDEN_PIN_REQUIREMENT_DISABLED=true # disable pin requirement
GOLDWARDEN_DO_NOT_PERSIST_CONFIG=true # do not persist config
GOLDWARDEN_API_URI=https://my.bitwarden.domain/api # set api uri
GOLDWARDEN_IDENTITY_URI=https://my.bitwarden.domain/identity # set identity uri
GOLDWARDEN_SINGLE_PROCESS=true # run in single process mode, i.e no daemon
GOLDWARDEN_DEVICE_UUID= # set device uuid
GOLDWARDEN_AUTH_METHOD= # set auth method (password/passwordless)
GOLDWARDEN_AUTH_USER= # set auth user
GOLDWARDEN_AUTH_PASSWORD= # set auth password
GOLDWARDEN_SILENT_LOGGING=true # disable logging
GOLDWARDEN_SYSTEM_AUTH_DISABLED=true # disable system auth (biometrics / approval)
```
### Building
To build, you will need libfido2-dev. And a go toolchain.
@ -204,7 +220,6 @@ When accessing a vault entry, the daemon will authenticate against a polkit poli
### Future Plans
Some things that I consider adding (depending on time and personal need):
- Paswordless sign in
- Regular cli managment (add, delete, update, of logins / secure notes)
- Scripts to properly set up the policies/systemd/etc.

View File

@ -69,6 +69,10 @@ func sync(ctx context.Context, vault *vault.Vault, cfg *config.Config) bool {
func ensureIsNotLocked(action Action) Action {
return func(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx sockets.CallingContext) (interface{}, error) {
if cfg.ConfigFile.RuntimeConfig.DisablePinRequirement {
return action(request, cfg, vault, ctx)
}
if cfg.IsLocked() {
err := cfg.TryUnlock(vault)
ctx1 := context.Background()

View File

@ -13,7 +13,7 @@ import (
)
func handleLogin(msg ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext sockets.CallingContext) (response interface{}, err error) {
if !cfg.HasPin() {
if !cfg.HasPin() && !cfg.ConfigFile.RuntimeConfig.DisablePinRequirement {
response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{
Success: false,
Message: "No pin set. Set a pin first!",

View File

@ -4,7 +4,6 @@ import (
"context"
"strings"
"github.com/LlamaNite/llamalog"
"github.com/quexten/goldwarden/agent/bitwarden"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/sockets"
@ -12,9 +11,10 @@ import (
"github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/ipc"
"github.com/quexten/goldwarden/logging"
)
var actionsLog = llamalog.NewLogger("Goldwarden", "Actions")
var actionsLog = logging.GetLogger("Goldwarden", "Actions")
func handleAddSSH(msg ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext sockets.CallingContext) (response interface{}, err error) {
req := msg.ParsedPayload().(ipc.CreateSSHKeyRequest)

View File

@ -14,17 +14,17 @@ import (
"strings"
"time"
"github.com/LlamaNite/llamalog"
"github.com/awnumar/memguard"
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
"github.com/quexten/goldwarden/agent/bitwarden/twofactor"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/logging"
"golang.org/x/crypto/pbkdf2"
)
var authLog = llamalog.NewLogger("Goldwarden", "Auth")
var authLog = logging.GetLogger("Goldwarden", "Auth")
type preLoginRequest struct {
Email string `json:"email"`
@ -103,22 +103,10 @@ func LoginWithMasterpassword(ctx context.Context, email string, cfg *config.Conf
err = authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values)
errsc, ok := err.(*errStatusCode)
if ok && bytes.Contains(errsc.body, []byte("TwoFactor")) {
var twoFactor twofactor.TwoFactorResponse
if err := json.Unmarshal(errsc.body, &twoFactor); err != nil {
loginResponseToken, err = Perform2FA(values, errsc, cfg, ctx)
if err != nil {
return LoginResponseToken{}, crypto.MasterKey{}, "", err
}
provider, token, err := twofactor.PerformSecondFactor(&twoFactor, cfg)
if err != nil {
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not obtain two-factor auth token: %v", err)
}
values.Set("twoFactorProvider", strconv.Itoa(int(provider)))
values.Set("twoFactorToken", string(token))
values.Set("twoFactorRemember", "1")
loginResponseToken = LoginResponseToken{}
if err := authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values); err != nil {
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not login via two-factor: %v", err)
}
authLog.Info("2FA login successful")
} else if err != nil && strings.Contains(err.Error(), "Captcha required.") {
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("captcha required, please login via the web interface")
@ -177,9 +165,18 @@ func LoginWithDevice(ctx context.Context, email string, cfg *config.Config, vaul
var loginResponseToken LoginResponseToken
err = authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values)
errsc, ok := err.(*errStatusCode)
if ok && bytes.Contains(errsc.body, []byte("TwoFactor")) {
loginResponseToken, err = Perform2FA(values, errsc, cfg, ctx)
if err != nil {
return LoginResponseToken{}, crypto.MasterKey{}, "", err
}
} else if err != nil && strings.Contains(err.Error(), "Captcha required.") {
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("captcha required, please login via the web interface")
} else if err != nil {
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("could not login via password: %v", err)
}
return loginResponseToken, crypto.MasterKeyFromBytes(masterKey), string(masterPasswordHash), nil
}
}
@ -218,6 +215,26 @@ func RefreshToken(ctx context.Context, cfg *config.Config) bool {
return true
}
func Perform2FA(values url.Values, errsc *errStatusCode, cfg *config.Config, ctx context.Context) (LoginResponseToken, error) {
var twoFactor twofactor.TwoFactorResponse
if err := json.Unmarshal(errsc.body, &twoFactor); err != nil {
return LoginResponseToken{}, err
}
provider, token, err := twofactor.PerformSecondFactor(&twoFactor, cfg)
if err != nil {
return LoginResponseToken{}, fmt.Errorf("could not obtain two-factor auth token: %v", err)
}
values.Set("twoFactorProvider", strconv.Itoa(int(provider)))
values.Set("twoFactorToken", string(token))
values.Set("twoFactorRemember", "1")
loginResponseToken := LoginResponseToken{}
if err := authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values); err != nil {
return LoginResponseToken{}, fmt.Errorf("could not login via two-factor: %v", err)
}
authLog.Info("2FA login successful")
return loginResponseToken, nil
}
func urlValues(pairs ...string) url.Values {
if len(pairs)%2 != 0 {
panic("pairs must be of even length")

View File

@ -6,14 +6,14 @@ import (
"fmt"
"os"
"github.com/LlamaNite/llamalog"
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
"github.com/quexten/goldwarden/agent/bitwarden/models"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/logging"
)
var log = llamalog.NewLogger("Goldwarden", "Bitwarden API")
var log = logging.GetLogger("Goldwarden", "Bitwarden API")
const path = "/.cache/goldwarden-vault.json"

View File

@ -5,12 +5,12 @@ import (
"fmt"
"strconv"
"github.com/LlamaNite/llamalog"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/logging"
)
var twofactorLog = llamalog.NewLogger("Goldwarden", "TwoFactor")
var twofactorLog = logging.GetLogger("Goldwarden", "TwoFactor")
func PerformSecondFactor(resp *TwoFactorResponse, cfg *config.Config) (TwoFactorProvider, []byte, error) {
if resp.TwoFactorProviders2[WebAuthn] != nil {

View File

@ -8,17 +8,17 @@ import (
"os/signal"
"time"
"github.com/LlamaNite/llamalog"
"github.com/awnumar/memguard"
"github.com/gorilla/websocket"
"github.com/quexten/goldwarden/agent/bitwarden/models"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/logging"
"github.com/vmihailenco/msgpack/v5"
)
var websocketLog = llamalog.NewLogger("Goldwarden", "Websocket")
var websocketLog = logging.GetLogger("Goldwarden", "Websocket")
type NotificationMessageType int64

View File

@ -24,9 +24,26 @@ const (
KDFIterations = 2
KDFMemory = 2 * 1024 * 1024
KDFThreads = 8
ConfigPath = "/.config/goldwarden.json"
DefaultConfigPath = "~/.config/goldwarden.json"
)
type RuntimeConfig struct {
DisableAuth bool
DisablePinRequirement bool
AuthMethod string
DoNotPersistConfig bool
ConfigDirectory string
DisableSSHAgent bool
WebsocketDisabled bool
ApiURI string
IdentityURI string
SingleProcess bool
DeviceUUID string
User string
Password string
Pin string
}
type ConfigFile struct {
IdentityUrl string
ApiUrl string
@ -36,6 +53,7 @@ type ConfigFile struct {
EncryptedUserSymmetricKey string
EncryptedMasterPasswordHash string
EncryptedMasterKey string
RuntimeConfig RuntimeConfig `json:"-"`
}
type LoginToken struct {
@ -65,13 +83,14 @@ func DefaultConfig() Config {
EncryptedUserSymmetricKey: "",
EncryptedMasterPasswordHash: "",
EncryptedMasterKey: "",
RuntimeConfig: RuntimeConfig{},
},
sync.Mutex{},
}
}
func (c *Config) IsLocked() bool {
return c.key == nil
return c.key.EqualTo(make([]byte, 32)) && c.HasPin()
}
func (c *Config) IsLoggedIn() bool {
@ -105,8 +124,7 @@ func (c *Config) Lock() {
if c.IsLocked() {
return
}
c.key.Destroy()
c.key = nil
c.key.Wipe()
}
func (c *Config) Purge() {
@ -315,6 +333,10 @@ func (c *Config) decryptString(data string) (string, error) {
}
func (config *Config) WriteConfig() error {
if config.ConfigFile.RuntimeConfig.DoNotPersistConfig {
return nil
}
config.mu.Lock()
defer config.mu.Unlock()
@ -323,13 +345,9 @@ func (config *Config) WriteConfig() error {
return err
}
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
// write to disk
os.Remove(home + ConfigPath)
file, err := os.OpenFile(home+ConfigPath, os.O_CREATE|os.O_WRONLY, 0600)
os.Remove(config.ConfigFile.RuntimeConfig.ConfigDirectory)
file, err := os.OpenFile(config.ConfigFile.RuntimeConfig.ConfigDirectory, os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
return err
}
@ -342,14 +360,13 @@ func (config *Config) WriteConfig() error {
return nil
}
func ReadConfig() (Config, error) {
home, err := os.UserHomeDir()
func ReadConfig(rtCfg RuntimeConfig) (Config, error) {
file, err := os.Open(rtCfg.ConfigDirectory)
if err != nil {
panic(err)
}
file, err := os.Open(home + ConfigPath)
if err != nil {
return Config{ConfigFile: ConfigFile{}}, err
return Config{
key: memguard.NewBuffer(32),
ConfigFile: ConfigFile{},
}, err
}
defer file.Close()
@ -357,12 +374,21 @@ func ReadConfig() (Config, error) {
config := ConfigFile{}
err = decoder.Decode(&config)
if err != nil {
return Config{ConfigFile: ConfigFile{}}, err
return Config{
key: memguard.NewBuffer(32),
ConfigFile: ConfigFile{},
}, err
}
if config.ConfigKeyHash == "" {
return Config{ConfigFile: config, key: memguard.NewBuffer(32)}, nil
return Config{
key: memguard.NewBuffer(32),
ConfigFile: config,
}, nil
}
return Config{ConfigFile: config}, nil
return Config{
key: memguard.NewBuffer(32),
ConfigFile: config,
}, nil
}
func (cfg *Config) TryUnlock(vault *vault.Vault) error {

View File

@ -8,15 +8,15 @@ import (
"net"
"os"
"github.com/LlamaNite/llamalog"
"github.com/quexten/goldwarden/agent/sockets"
"github.com/quexten/goldwarden/agent/systemauth"
"github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/logging"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
)
var log = llamalog.NewLogger("Goldwarden", "SSH")
var log = logging.GetLogger("Goldwarden", "SSH")
type vaultAgent struct {
vault *vault.Vault

View File

@ -2,13 +2,10 @@ package systemauth
import (
"errors"
"os"
"github.com/twpayne/go-pinentry"
)
var authDisabled = false
func GetPassword(title string, description string) (string, error) {
client, err := pinentry.NewClient(
pinentry.WithBinaryNameFromGnuPGAgentConf(),
@ -40,8 +37,7 @@ func GetPassword(title string, description string) (string, error) {
}
func GetApproval(title string, description string) (bool, error) {
if authDisabled {
log.Info("Skipping approval because system auth is disabled")
if systemAuthDisabled {
return true, nil
}
@ -70,10 +66,3 @@ func GetApproval(title string, description string) (bool, error) {
return true, nil
}
}
func init() {
envAuthDisabled := os.Getenv("GOLDWARDEN_SYSTEM_AUTH_DISABLED")
if envAuthDisabled == "true" {
authDisabled = true
}
}

View File

@ -1,11 +1,11 @@
package systemauth
import (
"github.com/LlamaNite/llamalog"
"github.com/amenzhinsky/go-polkit"
"github.com/quexten/goldwarden/logging"
)
var log = llamalog.NewLogger("Goldwarden", "Systemauth")
var log = logging.GetLogger("Goldwarden", "Systemauth")
type Approval string
@ -75,11 +75,12 @@ func (a Approval) String() string {
}
func CheckBiometrics(approvalType Approval) bool {
log.Info("Checking biometrics for %s", approvalType.String())
if authDisabled {
if systemAuthDisabled {
return true
}
log.Info("Checking biometrics for %s", approvalType.String())
authority, err := polkit.NewAuthority()
if err != nil {
return false

View File

@ -0,0 +1,11 @@
package systemauth
import "os"
var systemAuthDisabled = false
func init() {
if os.Getenv("GOLDWARDEN_SYSTEM_AUTH_DISABLED") == "true" {
systemAuthDisabled = true
}
}

View File

@ -8,7 +8,6 @@ import (
"os"
"time"
"github.com/LlamaNite/llamalog"
"github.com/quexten/goldwarden/agent/actions"
"github.com/quexten/goldwarden/agent/bitwarden"
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
@ -17,6 +16,7 @@ import (
"github.com/quexten/goldwarden/agent/ssh"
"github.com/quexten/goldwarden/agent/vault"
"github.com/quexten/goldwarden/ipc"
"github.com/quexten/goldwarden/logging"
"golang.org/x/sys/unix"
)
@ -25,7 +25,7 @@ const (
TokenRefreshInterval = 30 * time.Minute
)
var log = llamalog.NewLogger("Goldwarden", "Agent")
var log = logging.GetLogger("Goldwarden", "Agent")
func writeError(c net.Conn, errMsg error) error {
payload := ipc.ActionResponse{
@ -102,17 +102,28 @@ type AgentState struct {
config *config.ConfigFile
}
func StartUnixAgent(path string, websocket bool, sshAgent bool) error {
func StartUnixAgent(path string, runtimeConfig config.RuntimeConfig) error {
ctx := context.Background()
// check if exists
keyring := crypto.NewKeyring(nil)
var vault = vault.NewVault(&keyring)
cfg, err := config.ReadConfig()
cfg, err := config.ReadConfig(runtimeConfig)
if err != nil {
var cfg = config.DefaultConfig()
cfg.WriteConfig()
}
cfg.ConfigFile.RuntimeConfig = runtimeConfig
if cfg.ConfigFile.RuntimeConfig.ApiURI != "" {
cfg.ConfigFile.ApiUrl = cfg.ConfigFile.RuntimeConfig.ApiURI
}
if cfg.ConfigFile.RuntimeConfig.IdentityURI != "" {
cfg.ConfigFile.IdentityUrl = cfg.ConfigFile.RuntimeConfig.IdentityURI
}
if cfg.ConfigFile.RuntimeConfig.DeviceUUID != "" {
cfg.ConfigFile.DeviceUUID = cfg.ConfigFile.RuntimeConfig.DeviceUUID
}
if !cfg.IsLocked() {
log.Warn("Config is not locked. SET A PIN!!")
token, err := cfg.GetToken()
@ -134,11 +145,11 @@ func StartUnixAgent(path string, websocket bool, sshAgent bool) error {
}
disableDumpable()
if websocket {
if !runtimeConfig.WebsocketDisabled {
go bitwarden.RunWebsocketDaemon(ctx, vault, &cfg)
}
if sshAgent {
if !runtimeConfig.DisableSSHAgent {
vaultAgent := ssh.NewVaultAgent(vault)
vaultAgent.SetUnlockRequestAction(func() bool {
err := cfg.TryUnlock(vault)

View File

@ -70,18 +70,29 @@ func serveVirtualAgent(recv chan []byte, send chan []byte, ctx context.Context,
}
}
func StartVirtualAgent() (chan []byte, chan []byte) {
func StartVirtualAgent(runtimeConfig config.RuntimeConfig) (chan []byte, chan []byte) {
ctx := context.Background()
// check if exists
keyring := crypto.NewKeyring(nil)
var vault = vault.NewVault(&keyring)
cfg, err := config.ReadConfig()
cfg, err := config.ReadConfig(runtimeConfig)
if err != nil {
var cfg = config.DefaultConfig()
cfg.WriteConfig()
}
if !cfg.IsLocked() {
cfg.ConfigFile.RuntimeConfig = runtimeConfig
if cfg.ConfigFile.RuntimeConfig.ApiURI != "" {
cfg.ConfigFile.ApiUrl = cfg.ConfigFile.RuntimeConfig.ApiURI
}
if cfg.ConfigFile.RuntimeConfig.IdentityURI != "" {
cfg.ConfigFile.IdentityUrl = cfg.ConfigFile.RuntimeConfig.IdentityURI
}
if cfg.ConfigFile.RuntimeConfig.DeviceUUID != "" {
cfg.ConfigFile.DeviceUUID = cfg.ConfigFile.RuntimeConfig.DeviceUUID
}
if !cfg.IsLocked() && !cfg.ConfigFile.RuntimeConfig.DoNotPersistConfig {
log.Warn("Config is not locked. SET A PIN!!")
token, err := cfg.GetToken()
if err == nil {

View File

@ -11,7 +11,7 @@ import (
"github.com/quexten/goldwarden/ipc"
)
func GetLoginByUUID(uuid string) (ipc.DecryptedLoginCipher, error) {
func GetLoginByUUID(uuid string, client client.Client) (ipc.DecryptedLoginCipher, error) {
resp, err := client.SendToAgent(ipc.GetLoginRequest{
UUID: uuid,
})
@ -31,7 +31,7 @@ func GetLoginByUUID(uuid string) (ipc.DecryptedLoginCipher, error) {
}
}
func ListLogins() ([]ipc.DecryptedLoginCipher, error) {
func ListLogins(client client.Client) ([]ipc.DecryptedLoginCipher, error) {
resp, err := client.SendToAgent(ipc.ListLoginsRequest{})
if err != nil {
return []ipc.DecryptedLoginCipher{}, err
@ -49,8 +49,8 @@ func ListLogins() ([]ipc.DecryptedLoginCipher, error) {
}
}
func Run(layout string, useCopyPaste bool) {
logins, err := ListLogins()
func Run(layout string, useCopyPaste bool, client client.Client) {
logins, err := ListLogins(client)
if err != nil {
panic(err)
}
@ -65,7 +65,7 @@ func Run(layout string, useCopyPaste bool) {
}
RunAutofill(autofillEntries, func(uuid string, c chan bool) {
login, err := GetLoginByUUID(uuid)
login, err := GetLoginByUUID(uuid, client)
if err != nil {
panic(err)
}

View File

@ -1,4 +1,4 @@
//go:build autofill
//go:build !noautofill
package cmd
@ -14,7 +14,7 @@ var autofillCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
layout := cmd.Flag("layout").Value.String()
useCopyPaste, _ := cmd.Flags().GetBool("use-copy-paste")
autofill.Run(layout, useCopyPaste)
autofill.Run(layout, useCopyPaste, commandClient)
},
}

View File

@ -15,12 +15,13 @@ var daemonizeCmd = &cobra.Command{
Long: `Starts the agent as a daemon. The agent will run in the background and will
run in the background until it is stopped.`,
Run: func(cmd *cobra.Command, args []string) {
websocketDisabled := os.Getenv("GOLDWARDEN_WEBSOCKET_DISABLED") == "true"
websocketDisabled := runtimeConfig.WebsocketDisabled
sshDisabled := runtimeConfig.DisableSSHAgent
if websocketDisabled {
println("Websocket disabled")
}
sshDisabled := os.Getenv("GOLDWARDEN_SSH_DISABLED") == "true"
if sshDisabled {
println("SSH agent disabled")
}
@ -35,7 +36,7 @@ var daemonizeCmd = &cobra.Command{
if err != nil {
panic(err)
}
err = agent.StartUnixAgent(home+"/.goldwarden.sock", websocketDisabled, sshDisabled)
err = agent.StartUnixAgent(home+"/.goldwarden.sock", runtimeConfig)
if err != nil {
panic(err)
}

62
cmd/logins.go Normal file
View File

@ -0,0 +1,62 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"fmt"
"github.com/quexten/goldwarden/ipc"
"github.com/spf13/cobra"
)
var baseLoginCmd = &cobra.Command{
Use: "logins",
Short: "Commands for managing logins.",
Long: `Commands for managing logins.`,
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}
var getLoginCmd = &cobra.Command{
Use: "get",
Short: "Gets a login in your vault",
Long: `Gets a login in your vault.`,
Run: func(cmd *cobra.Command, args []string) {
loginIfRequired()
uuid, _ := cmd.Flags().GetString("uuid")
name, _ := cmd.Flags().GetString("name")
username, _ := cmd.Flags().GetString("username")
resp, err := commandClient.SendToAgent(ipc.GetLoginRequest{
Name: name,
Username: username,
UUID: uuid,
})
if err != nil {
println("Error: " + err.Error())
println("Is the daemon running?")
return
}
switch resp.(type) {
case ipc.GetLoginResponse:
response := resp.(ipc.GetLoginResponse)
fmt.Println(response.Result.Password)
break
case ipc.ActionResponse:
println("Error: " + resp.(ipc.ActionResponse).Message)
return
}
},
}
func init() {
rootCmd.AddCommand(baseLoginCmd)
baseLoginCmd.AddCommand(getLoginCmd)
getLoginCmd.PersistentFlags().String("name", "", "")
getLoginCmd.PersistentFlags().String("username", "", "")
getLoginCmd.PersistentFlags().String("uuid", "", "")
}

View File

@ -4,11 +4,14 @@ import (
"os"
"github.com/quexten/goldwarden/agent"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/client"
"github.com/quexten/goldwarden/ipc"
"github.com/spf13/cobra"
)
var commandClient client.Client
var runtimeConfig config.RuntimeConfig
var rootCmd = &cobra.Command{
Use: "goldwarden",
@ -18,7 +21,17 @@ var rootCmd = &cobra.Command{
biometric unlock, and more.`,
}
func Execute() {
func Execute(cfg config.RuntimeConfig) {
runtimeConfig = cfg
goldwardenSingleProcess := os.Getenv("GOLDWARDEN_SINGLE_PROCESS")
if goldwardenSingleProcess == "true" {
recv, send := agent.StartVirtualAgent(runtimeConfig)
commandClient = client.NewVirtualClient(send, recv)
} else {
commandClient = client.NewUnixSocketClient()
}
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
@ -26,13 +39,23 @@ func Execute() {
}
func init() {
goldwardenSingleProcess := os.Getenv("GOLDWARDEN_SINGLE_PROCESS")
if goldwardenSingleProcess == "true" {
recv, send := agent.StartVirtualAgent()
commandClient = client.NewVirtualClient(send, recv)
} else {
commandClient = client.NewUnixSocketClient()
}
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
func loginIfRequired() error {
var err error
if runtimeConfig.AuthMethod == "password" {
_, err = commandClient.SendToAgent(ipc.DoLoginRequest{
Email: runtimeConfig.User,
Password: runtimeConfig.Password,
})
} else if runtimeConfig.AuthMethod == "passwordless" {
_, err = commandClient.SendToAgent(ipc.DoLoginRequest{
Email: runtimeConfig.User,
Passwordless: true,
})
}
return err
}

View File

@ -27,6 +27,8 @@ var sshAddCmd = &cobra.Command{
Long: `Runs a command with environment variables from your vault.
The variables are stored as a secure note. Consult the documentation for more information.`,
Run: func(cmd *cobra.Command, args []string) {
loginIfRequired()
name, _ := cmd.Flags().GetString("name")
copyToClipboard, _ := cmd.Flags().GetBool("clipboard")
@ -60,6 +62,8 @@ var listSSHCmd = &cobra.Command{
Short: "Lists all SSH keys in your vault",
Long: `Lists all SSH keys in your vault.`,
Run: func(cmd *cobra.Command, args []string) {
loginIfRequired()
result, err := commandClient.SendToAgent(ipc.GetSSHKeysRequest{})
if err != nil {
println("Error: " + err.Error())

22
logging/llamalogger.go Normal file
View File

@ -0,0 +1,22 @@
package logging
import (
"os"
"github.com/LlamaNite/llamalog"
)
type SilentWriter struct {
}
func (w SilentWriter) Write(p []byte) (n int, err error) {
return len(p), nil
}
func GetLogger(packageDir ...string) *llamalog.Logger {
if os.Getenv("GOLDWARDEN_SILENT_LOGGING") == "true" {
return llamalog.NewLoggerFromWriter(SilentWriter{}, packageDir...)
} else {
return llamalog.NewLogger(packageDir...)
}
}

43
main.go
View File

@ -6,6 +6,7 @@ import (
"strings"
"time"
"github.com/quexten/goldwarden/agent/config"
"github.com/quexten/goldwarden/browserbiometrics"
"github.com/quexten/goldwarden/cmd"
)
@ -16,10 +17,48 @@ func main() {
return
}
if !cmd.IsPolkitSetup() {
var configPath string
if path, found := os.LookupEnv("GOLDWARDEN_CONFIG_DIRECTORY"); found {
configPath = path
} else {
configPath = config.DefaultConfigPath
}
userHome, _ := os.UserHomeDir()
configPath = strings.ReplaceAll(configPath, "~", userHome)
runtimeConfig := config.RuntimeConfig{
DisableAuth: os.Getenv("GOLDWARDEN_WEBSOCKET_DISABLED") == "true",
DisablePinRequirement: os.Getenv("GOLDWARDEN_PIN_REQUIREMENT_DISABLED") == "true",
DoNotPersistConfig: os.Getenv("GOLDWARDEN_DO_NOT_PERSIST_CONFIG") == "true",
ApiURI: os.Getenv("GOLDWARDEN_API_URI"),
IdentityURI: os.Getenv("GOLDWARDEN_IDENTITY_URI"),
SingleProcess: os.Getenv("GOLDWARDEN_SINGLE_PROCESS") == "true",
DeviceUUID: os.Getenv("GOLDWARDEN_DEVICE_UUID"),
AuthMethod: os.Getenv("GOLDWARDEN_AUTH_METHOD"),
User: os.Getenv("GOLDWARDEN_AUTH_USER"),
Password: os.Getenv("GOLDWARDEN_AUTH_PASSWORD"),
Pin: os.Getenv("GOLDWARDEN_PIN"),
ConfigDirectory: configPath,
}
if runtimeConfig.SingleProcess {
runtimeConfig.DisablePinRequirement = true
runtimeConfig.DisableAuth = true
}
if runtimeConfig.DisablePinRequirement {
runtimeConfig.DoNotPersistConfig = true
}
if runtimeConfig.DisableAuth {
os.Setenv("GOLDWARDEN_SYSTEM_AUTH_DISABLED", "true")
}
if !cmd.IsPolkitSetup() && !runtimeConfig.DisableAuth {
fmt.Println("Polkit is not setup. Run 'goldwarden setup polkit' to set it up.")
time.Sleep(3 * time.Second)
}
cmd.Execute()
cmd.Execute(runtimeConfig)
}