Add more env variables
This commit is contained in:
parent
6e3859dd43
commit
6d21d10a9e
23 changed files with 336 additions and 100 deletions
19
Readme.md
19
Readme.md
|
|
@ -170,9 +170,25 @@ You can bind this to a hotkey in your desktop environment (i.e i3/sway config fi
|
||||||
|
|
||||||
### Login with device
|
### 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
|
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
|
### Building
|
||||||
|
|
||||||
To build, you will need libfido2-dev. And a go toolchain.
|
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
|
### Future Plans
|
||||||
Some things that I consider adding (depending on time and personal need):
|
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)
|
- Regular cli managment (add, delete, update, of logins / secure notes)
|
||||||
- Scripts to properly set up the policies/systemd/etc.
|
- Scripts to properly set up the policies/systemd/etc.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,10 @@ func sync(ctx context.Context, vault *vault.Vault, cfg *config.Config) bool {
|
||||||
|
|
||||||
func ensureIsNotLocked(action Action) Action {
|
func ensureIsNotLocked(action Action) Action {
|
||||||
return func(request ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, ctx sockets.CallingContext) (interface{}, error) {
|
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() {
|
if cfg.IsLocked() {
|
||||||
err := cfg.TryUnlock(vault)
|
err := cfg.TryUnlock(vault)
|
||||||
ctx1 := context.Background()
|
ctx1 := context.Background()
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleLogin(msg ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext sockets.CallingContext) (response interface{}, err error) {
|
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{
|
response, err = ipc.IPCMessageFromPayload(ipc.ActionResponse{
|
||||||
Success: false,
|
Success: false,
|
||||||
Message: "No pin set. Set a pin first!",
|
Message: "No pin set. Set a pin first!",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden"
|
"github.com/quexten/goldwarden/agent/bitwarden"
|
||||||
"github.com/quexten/goldwarden/agent/config"
|
"github.com/quexten/goldwarden/agent/config"
|
||||||
"github.com/quexten/goldwarden/agent/sockets"
|
"github.com/quexten/goldwarden/agent/sockets"
|
||||||
|
|
@ -12,9 +11,10 @@ import (
|
||||||
"github.com/quexten/goldwarden/agent/systemauth"
|
"github.com/quexten/goldwarden/agent/systemauth"
|
||||||
"github.com/quexten/goldwarden/agent/vault"
|
"github.com/quexten/goldwarden/agent/vault"
|
||||||
"github.com/quexten/goldwarden/ipc"
|
"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) {
|
func handleAddSSH(msg ipc.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext sockets.CallingContext) (response interface{}, err error) {
|
||||||
req := msg.ParsedPayload().(ipc.CreateSSHKeyRequest)
|
req := msg.ParsedPayload().(ipc.CreateSSHKeyRequest)
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,17 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/awnumar/memguard"
|
"github.com/awnumar/memguard"
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden/twofactor"
|
"github.com/quexten/goldwarden/agent/bitwarden/twofactor"
|
||||||
"github.com/quexten/goldwarden/agent/config"
|
"github.com/quexten/goldwarden/agent/config"
|
||||||
"github.com/quexten/goldwarden/agent/systemauth"
|
"github.com/quexten/goldwarden/agent/systemauth"
|
||||||
"github.com/quexten/goldwarden/agent/vault"
|
"github.com/quexten/goldwarden/agent/vault"
|
||||||
|
"github.com/quexten/goldwarden/logging"
|
||||||
"golang.org/x/crypto/pbkdf2"
|
"golang.org/x/crypto/pbkdf2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var authLog = llamalog.NewLogger("Goldwarden", "Auth")
|
var authLog = logging.GetLogger("Goldwarden", "Auth")
|
||||||
|
|
||||||
type preLoginRequest struct {
|
type preLoginRequest struct {
|
||||||
Email string `json:"email"`
|
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)
|
err = authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values)
|
||||||
errsc, ok := err.(*errStatusCode)
|
errsc, ok := err.(*errStatusCode)
|
||||||
if ok && bytes.Contains(errsc.body, []byte("TwoFactor")) {
|
if ok && bytes.Contains(errsc.body, []byte("TwoFactor")) {
|
||||||
var twoFactor twofactor.TwoFactorResponse
|
loginResponseToken, err = Perform2FA(values, errsc, cfg, ctx)
|
||||||
if err := json.Unmarshal(errsc.body, &twoFactor); err != nil {
|
if err != nil {
|
||||||
return LoginResponseToken{}, crypto.MasterKey{}, "", err
|
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.") {
|
} else if err != nil && strings.Contains(err.Error(), "Captcha required.") {
|
||||||
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("captcha required, please login via the web interface")
|
return LoginResponseToken{}, crypto.MasterKey{}, "", fmt.Errorf("captcha required, please login via the web interface")
|
||||||
|
|
||||||
|
|
@ -177,8 +165,17 @@ func LoginWithDevice(ctx context.Context, email string, cfg *config.Config, vaul
|
||||||
|
|
||||||
var loginResponseToken LoginResponseToken
|
var loginResponseToken LoginResponseToken
|
||||||
err = authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values)
|
err = authenticatedHTTPPost(ctx, cfg.ConfigFile.IdentityUrl+"/connect/token", &loginResponseToken, values)
|
||||||
if err != nil {
|
errsc, ok := err.(*errStatusCode)
|
||||||
return LoginResponseToken{}, crypto.MasterKey{}, "", err
|
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
|
return loginResponseToken, crypto.MasterKeyFromBytes(masterKey), string(masterPasswordHash), nil
|
||||||
}
|
}
|
||||||
|
|
@ -218,6 +215,26 @@ func RefreshToken(ctx context.Context, cfg *config.Config) bool {
|
||||||
return true
|
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 {
|
func urlValues(pairs ...string) url.Values {
|
||||||
if len(pairs)%2 != 0 {
|
if len(pairs)%2 != 0 {
|
||||||
panic("pairs must be of even length")
|
panic("pairs must be of even length")
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,14 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden/models"
|
"github.com/quexten/goldwarden/agent/bitwarden/models"
|
||||||
"github.com/quexten/goldwarden/agent/config"
|
"github.com/quexten/goldwarden/agent/config"
|
||||||
"github.com/quexten/goldwarden/agent/vault"
|
"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"
|
const path = "/.cache/goldwarden-vault.json"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/quexten/goldwarden/agent/config"
|
"github.com/quexten/goldwarden/agent/config"
|
||||||
"github.com/quexten/goldwarden/agent/systemauth"
|
"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) {
|
func PerformSecondFactor(resp *TwoFactorResponse, cfg *config.Config) (TwoFactorProvider, []byte, error) {
|
||||||
if resp.TwoFactorProviders2[WebAuthn] != nil {
|
if resp.TwoFactorProviders2[WebAuthn] != nil {
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,17 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/awnumar/memguard"
|
"github.com/awnumar/memguard"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden/models"
|
"github.com/quexten/goldwarden/agent/bitwarden/models"
|
||||||
"github.com/quexten/goldwarden/agent/config"
|
"github.com/quexten/goldwarden/agent/config"
|
||||||
"github.com/quexten/goldwarden/agent/systemauth"
|
"github.com/quexten/goldwarden/agent/systemauth"
|
||||||
"github.com/quexten/goldwarden/agent/vault"
|
"github.com/quexten/goldwarden/agent/vault"
|
||||||
|
"github.com/quexten/goldwarden/logging"
|
||||||
"github.com/vmihailenco/msgpack/v5"
|
"github.com/vmihailenco/msgpack/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
var websocketLog = llamalog.NewLogger("Goldwarden", "Websocket")
|
var websocketLog = logging.GetLogger("Goldwarden", "Websocket")
|
||||||
|
|
||||||
type NotificationMessageType int64
|
type NotificationMessageType int64
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,29 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
KDFIterations = 2
|
KDFIterations = 2
|
||||||
KDFMemory = 2 * 1024 * 1024
|
KDFMemory = 2 * 1024 * 1024
|
||||||
KDFThreads = 8
|
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 {
|
type ConfigFile struct {
|
||||||
IdentityUrl string
|
IdentityUrl string
|
||||||
ApiUrl string
|
ApiUrl string
|
||||||
|
|
@ -36,6 +53,7 @@ type ConfigFile struct {
|
||||||
EncryptedUserSymmetricKey string
|
EncryptedUserSymmetricKey string
|
||||||
EncryptedMasterPasswordHash string
|
EncryptedMasterPasswordHash string
|
||||||
EncryptedMasterKey string
|
EncryptedMasterKey string
|
||||||
|
RuntimeConfig RuntimeConfig `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type LoginToken struct {
|
type LoginToken struct {
|
||||||
|
|
@ -65,13 +83,14 @@ func DefaultConfig() Config {
|
||||||
EncryptedUserSymmetricKey: "",
|
EncryptedUserSymmetricKey: "",
|
||||||
EncryptedMasterPasswordHash: "",
|
EncryptedMasterPasswordHash: "",
|
||||||
EncryptedMasterKey: "",
|
EncryptedMasterKey: "",
|
||||||
|
RuntimeConfig: RuntimeConfig{},
|
||||||
},
|
},
|
||||||
sync.Mutex{},
|
sync.Mutex{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) IsLocked() bool {
|
func (c *Config) IsLocked() bool {
|
||||||
return c.key == nil
|
return c.key.EqualTo(make([]byte, 32)) && c.HasPin()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) IsLoggedIn() bool {
|
func (c *Config) IsLoggedIn() bool {
|
||||||
|
|
@ -105,8 +124,7 @@ func (c *Config) Lock() {
|
||||||
if c.IsLocked() {
|
if c.IsLocked() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.key.Destroy()
|
c.key.Wipe()
|
||||||
c.key = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Purge() {
|
func (c *Config) Purge() {
|
||||||
|
|
@ -315,6 +333,10 @@ func (c *Config) decryptString(data string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (config *Config) WriteConfig() error {
|
func (config *Config) WriteConfig() error {
|
||||||
|
if config.ConfigFile.RuntimeConfig.DoNotPersistConfig {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
config.mu.Lock()
|
config.mu.Lock()
|
||||||
defer config.mu.Unlock()
|
defer config.mu.Unlock()
|
||||||
|
|
||||||
|
|
@ -323,13 +345,9 @@ func (config *Config) WriteConfig() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
home, err := os.UserHomeDir()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// write to disk
|
// write to disk
|
||||||
os.Remove(home + ConfigPath)
|
os.Remove(config.ConfigFile.RuntimeConfig.ConfigDirectory)
|
||||||
file, err := os.OpenFile(home+ConfigPath, os.O_CREATE|os.O_WRONLY, 0600)
|
file, err := os.OpenFile(config.ConfigFile.RuntimeConfig.ConfigDirectory, os.O_CREATE|os.O_WRONLY, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -342,14 +360,13 @@ func (config *Config) WriteConfig() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ReadConfig() (Config, error) {
|
func ReadConfig(rtCfg RuntimeConfig) (Config, error) {
|
||||||
home, err := os.UserHomeDir()
|
file, err := os.Open(rtCfg.ConfigDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return Config{
|
||||||
}
|
key: memguard.NewBuffer(32),
|
||||||
file, err := os.Open(home + ConfigPath)
|
ConfigFile: ConfigFile{},
|
||||||
if err != nil {
|
}, err
|
||||||
return Config{ConfigFile: ConfigFile{}}, err
|
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
|
|
@ -357,12 +374,21 @@ func ReadConfig() (Config, error) {
|
||||||
config := ConfigFile{}
|
config := ConfigFile{}
|
||||||
err = decoder.Decode(&config)
|
err = decoder.Decode(&config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Config{ConfigFile: ConfigFile{}}, err
|
return Config{
|
||||||
|
key: memguard.NewBuffer(32),
|
||||||
|
ConfigFile: ConfigFile{},
|
||||||
|
}, err
|
||||||
}
|
}
|
||||||
if config.ConfigKeyHash == "" {
|
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 {
|
func (cfg *Config) TryUnlock(vault *vault.Vault) error {
|
||||||
|
|
|
||||||
|
|
@ -8,15 +8,15 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/quexten/goldwarden/agent/sockets"
|
"github.com/quexten/goldwarden/agent/sockets"
|
||||||
"github.com/quexten/goldwarden/agent/systemauth"
|
"github.com/quexten/goldwarden/agent/systemauth"
|
||||||
"github.com/quexten/goldwarden/agent/vault"
|
"github.com/quexten/goldwarden/agent/vault"
|
||||||
|
"github.com/quexten/goldwarden/logging"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/crypto/ssh/agent"
|
"golang.org/x/crypto/ssh/agent"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = llamalog.NewLogger("Goldwarden", "SSH")
|
var log = logging.GetLogger("Goldwarden", "SSH")
|
||||||
|
|
||||||
type vaultAgent struct {
|
type vaultAgent struct {
|
||||||
vault *vault.Vault
|
vault *vault.Vault
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,10 @@ package systemauth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/twpayne/go-pinentry"
|
"github.com/twpayne/go-pinentry"
|
||||||
)
|
)
|
||||||
|
|
||||||
var authDisabled = false
|
|
||||||
|
|
||||||
func GetPassword(title string, description string) (string, error) {
|
func GetPassword(title string, description string) (string, error) {
|
||||||
client, err := pinentry.NewClient(
|
client, err := pinentry.NewClient(
|
||||||
pinentry.WithBinaryNameFromGnuPGAgentConf(),
|
pinentry.WithBinaryNameFromGnuPGAgentConf(),
|
||||||
|
|
@ -40,8 +37,7 @@ func GetPassword(title string, description string) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetApproval(title string, description string) (bool, error) {
|
func GetApproval(title string, description string) (bool, error) {
|
||||||
if authDisabled {
|
if systemAuthDisabled {
|
||||||
log.Info("Skipping approval because system auth is disabled")
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,10 +66,3 @@ func GetApproval(title string, description string) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
envAuthDisabled := os.Getenv("GOLDWARDEN_SYSTEM_AUTH_DISABLED")
|
|
||||||
if envAuthDisabled == "true" {
|
|
||||||
authDisabled = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
package systemauth
|
package systemauth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/amenzhinsky/go-polkit"
|
"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
|
type Approval string
|
||||||
|
|
||||||
|
|
@ -75,11 +75,12 @@ func (a Approval) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckBiometrics(approvalType Approval) bool {
|
func CheckBiometrics(approvalType Approval) bool {
|
||||||
log.Info("Checking biometrics for %s", approvalType.String())
|
if systemAuthDisabled {
|
||||||
if authDisabled {
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Info("Checking biometrics for %s", approvalType.String())
|
||||||
|
|
||||||
authority, err := polkit.NewAuthority()
|
authority, err := polkit.NewAuthority()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
11
agent/systemauth/systemauth.go
Normal file
11
agent/systemauth/systemauth.go
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
package systemauth
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
var systemAuthDisabled = false
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if os.Getenv("GOLDWARDEN_SYSTEM_AUTH_DISABLED") == "true" {
|
||||||
|
systemAuthDisabled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/LlamaNite/llamalog"
|
|
||||||
"github.com/quexten/goldwarden/agent/actions"
|
"github.com/quexten/goldwarden/agent/actions"
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden"
|
"github.com/quexten/goldwarden/agent/bitwarden"
|
||||||
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
"github.com/quexten/goldwarden/agent/bitwarden/crypto"
|
||||||
|
|
@ -17,6 +16,7 @@ import (
|
||||||
"github.com/quexten/goldwarden/agent/ssh"
|
"github.com/quexten/goldwarden/agent/ssh"
|
||||||
"github.com/quexten/goldwarden/agent/vault"
|
"github.com/quexten/goldwarden/agent/vault"
|
||||||
"github.com/quexten/goldwarden/ipc"
|
"github.com/quexten/goldwarden/ipc"
|
||||||
|
"github.com/quexten/goldwarden/logging"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ const (
|
||||||
TokenRefreshInterval = 30 * time.Minute
|
TokenRefreshInterval = 30 * time.Minute
|
||||||
)
|
)
|
||||||
|
|
||||||
var log = llamalog.NewLogger("Goldwarden", "Agent")
|
var log = logging.GetLogger("Goldwarden", "Agent")
|
||||||
|
|
||||||
func writeError(c net.Conn, errMsg error) error {
|
func writeError(c net.Conn, errMsg error) error {
|
||||||
payload := ipc.ActionResponse{
|
payload := ipc.ActionResponse{
|
||||||
|
|
@ -102,17 +102,28 @@ type AgentState struct {
|
||||||
config *config.ConfigFile
|
config *config.ConfigFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func StartUnixAgent(path string, websocket bool, sshAgent bool) error {
|
func StartUnixAgent(path string, runtimeConfig config.RuntimeConfig) error {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
// check if exists
|
// check if exists
|
||||||
keyring := crypto.NewKeyring(nil)
|
keyring := crypto.NewKeyring(nil)
|
||||||
var vault = vault.NewVault(&keyring)
|
var vault = vault.NewVault(&keyring)
|
||||||
cfg, err := config.ReadConfig()
|
cfg, err := config.ReadConfig(runtimeConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var cfg = config.DefaultConfig()
|
var cfg = config.DefaultConfig()
|
||||||
cfg.WriteConfig()
|
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() {
|
if !cfg.IsLocked() {
|
||||||
log.Warn("Config is not locked. SET A PIN!!")
|
log.Warn("Config is not locked. SET A PIN!!")
|
||||||
token, err := cfg.GetToken()
|
token, err := cfg.GetToken()
|
||||||
|
|
@ -134,11 +145,11 @@ func StartUnixAgent(path string, websocket bool, sshAgent bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
disableDumpable()
|
disableDumpable()
|
||||||
if websocket {
|
if !runtimeConfig.WebsocketDisabled {
|
||||||
go bitwarden.RunWebsocketDaemon(ctx, vault, &cfg)
|
go bitwarden.RunWebsocketDaemon(ctx, vault, &cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sshAgent {
|
if !runtimeConfig.DisableSSHAgent {
|
||||||
vaultAgent := ssh.NewVaultAgent(vault)
|
vaultAgent := ssh.NewVaultAgent(vault)
|
||||||
vaultAgent.SetUnlockRequestAction(func() bool {
|
vaultAgent.SetUnlockRequestAction(func() bool {
|
||||||
err := cfg.TryUnlock(vault)
|
err := cfg.TryUnlock(vault)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
ctx := context.Background()
|
||||||
|
|
||||||
// check if exists
|
// check if exists
|
||||||
keyring := crypto.NewKeyring(nil)
|
keyring := crypto.NewKeyring(nil)
|
||||||
var vault = vault.NewVault(&keyring)
|
var vault = vault.NewVault(&keyring)
|
||||||
cfg, err := config.ReadConfig()
|
cfg, err := config.ReadConfig(runtimeConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var cfg = config.DefaultConfig()
|
var cfg = config.DefaultConfig()
|
||||||
cfg.WriteConfig()
|
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!!")
|
log.Warn("Config is not locked. SET A PIN!!")
|
||||||
token, err := cfg.GetToken()
|
token, err := cfg.GetToken()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"github.com/quexten/goldwarden/ipc"
|
"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{
|
resp, err := client.SendToAgent(ipc.GetLoginRequest{
|
||||||
UUID: uuid,
|
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{})
|
resp, err := client.SendToAgent(ipc.ListLoginsRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []ipc.DecryptedLoginCipher{}, err
|
return []ipc.DecryptedLoginCipher{}, err
|
||||||
|
|
@ -49,8 +49,8 @@ func ListLogins() ([]ipc.DecryptedLoginCipher, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Run(layout string, useCopyPaste bool) {
|
func Run(layout string, useCopyPaste bool, client client.Client) {
|
||||||
logins, err := ListLogins()
|
logins, err := ListLogins(client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -65,7 +65,7 @@ func Run(layout string, useCopyPaste bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RunAutofill(autofillEntries, func(uuid string, c chan bool) {
|
RunAutofill(autofillEntries, func(uuid string, c chan bool) {
|
||||||
login, err := GetLoginByUUID(uuid)
|
login, err := GetLoginByUUID(uuid, client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
//go:build autofill
|
//go:build !noautofill
|
||||||
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
|
|
@ -14,7 +14,7 @@ var autofillCmd = &cobra.Command{
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
layout := cmd.Flag("layout").Value.String()
|
layout := cmd.Flag("layout").Value.String()
|
||||||
useCopyPaste, _ := cmd.Flags().GetBool("use-copy-paste")
|
useCopyPaste, _ := cmd.Flags().GetBool("use-copy-paste")
|
||||||
autofill.Run(layout, useCopyPaste)
|
autofill.Run(layout, useCopyPaste, commandClient)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,13 @@ var daemonizeCmd = &cobra.Command{
|
||||||
Long: `Starts the agent as a daemon. The agent will run in the background and will
|
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 in the background until it is stopped.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
websocketDisabled := os.Getenv("GOLDWARDEN_WEBSOCKET_DISABLED") == "true"
|
websocketDisabled := runtimeConfig.WebsocketDisabled
|
||||||
|
sshDisabled := runtimeConfig.DisableSSHAgent
|
||||||
|
|
||||||
if websocketDisabled {
|
if websocketDisabled {
|
||||||
println("Websocket disabled")
|
println("Websocket disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
sshDisabled := os.Getenv("GOLDWARDEN_SSH_DISABLED") == "true"
|
|
||||||
if sshDisabled {
|
if sshDisabled {
|
||||||
println("SSH agent disabled")
|
println("SSH agent disabled")
|
||||||
}
|
}
|
||||||
|
|
@ -35,7 +36,7 @@ var daemonizeCmd = &cobra.Command{
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
err = agent.StartUnixAgent(home+"/.goldwarden.sock", websocketDisabled, sshDisabled)
|
err = agent.StartUnixAgent(home+"/.goldwarden.sock", runtimeConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
62
cmd/logins.go
Normal file
62
cmd/logins.go
Normal 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", "", "")
|
||||||
|
}
|
||||||
41
cmd/root.go
41
cmd/root.go
|
|
@ -4,11 +4,14 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/quexten/goldwarden/agent"
|
"github.com/quexten/goldwarden/agent"
|
||||||
|
"github.com/quexten/goldwarden/agent/config"
|
||||||
"github.com/quexten/goldwarden/client"
|
"github.com/quexten/goldwarden/client"
|
||||||
|
"github.com/quexten/goldwarden/ipc"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var commandClient client.Client
|
var commandClient client.Client
|
||||||
|
var runtimeConfig config.RuntimeConfig
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "goldwarden",
|
Use: "goldwarden",
|
||||||
|
|
@ -18,7 +21,17 @@ var rootCmd = &cobra.Command{
|
||||||
biometric unlock, and more.`,
|
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()
|
err := rootCmd.Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
@ -26,13 +39,23 @@ func Execute() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
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")
|
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
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ var sshAddCmd = &cobra.Command{
|
||||||
Long: `Runs a command with environment variables from your vault.
|
Long: `Runs a command with environment variables from your vault.
|
||||||
The variables are stored as a secure note. Consult the documentation for more information.`,
|
The variables are stored as a secure note. Consult the documentation for more information.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
loginIfRequired()
|
||||||
|
|
||||||
name, _ := cmd.Flags().GetString("name")
|
name, _ := cmd.Flags().GetString("name")
|
||||||
copyToClipboard, _ := cmd.Flags().GetBool("clipboard")
|
copyToClipboard, _ := cmd.Flags().GetBool("clipboard")
|
||||||
|
|
||||||
|
|
@ -60,6 +62,8 @@ var listSSHCmd = &cobra.Command{
|
||||||
Short: "Lists all SSH keys in your vault",
|
Short: "Lists all SSH keys in your vault",
|
||||||
Long: `Lists all SSH keys in your vault.`,
|
Long: `Lists all SSH keys in your vault.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
loginIfRequired()
|
||||||
|
|
||||||
result, err := commandClient.SendToAgent(ipc.GetSSHKeysRequest{})
|
result, err := commandClient.SendToAgent(ipc.GetSSHKeysRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Error: " + err.Error())
|
println("Error: " + err.Error())
|
||||||
|
|
|
||||||
22
logging/llamalogger.go
Normal file
22
logging/llamalogger.go
Normal 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
43
main.go
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/quexten/goldwarden/agent/config"
|
||||||
"github.com/quexten/goldwarden/browserbiometrics"
|
"github.com/quexten/goldwarden/browserbiometrics"
|
||||||
"github.com/quexten/goldwarden/cmd"
|
"github.com/quexten/goldwarden/cmd"
|
||||||
)
|
)
|
||||||
|
|
@ -16,10 +17,48 @@ func main() {
|
||||||
return
|
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.")
|
fmt.Println("Polkit is not setup. Run 'goldwarden setup polkit' to set it up.")
|
||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Execute()
|
cmd.Execute(runtimeConfig)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue