mirror of
https://github.com/quexten/goldwarden.git
synced 2024-08-17 15:10:26 +03:00
This commit is contained in:
commit
e617ba367d
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -114,7 +114,7 @@ jobs:
|
|||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
build_macos_x86_64:
|
build_macos_x86_64:
|
||||||
runs-on: macos-latest
|
runs-on: macos-13
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v1
|
||||||
|
@ -16,12 +16,24 @@ import (
|
|||||||
func handleAddSSH(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext *sockets.CallingContext) (response messages.IPCMessage, err error) {
|
func handleAddSSH(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext *sockets.CallingContext) (response messages.IPCMessage, err error) {
|
||||||
req := messages.ParsePayload(msg).(messages.CreateSSHKeyRequest)
|
req := messages.ParsePayload(msg).(messages.CreateSSHKeyRequest)
|
||||||
|
|
||||||
cipher, publicKey := ssh.NewSSHKeyCipher(req.Name, vault.Keyring)
|
cipher, publicKey, err := ssh.NewSSHKeyCipher(req.Name, vault.Keyring)
|
||||||
|
if err != nil {
|
||||||
|
response, err = messages.IPCMessageFromPayload(messages.ActionResponse{
|
||||||
|
Success: false,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
_, err = messages.IPCMessageFromPayload(messages.ActionResponse{
|
_, err = messages.IPCMessageFromPayload(messages.ActionResponse{
|
||||||
Success: true,
|
Success: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
response, err = messages.IPCMessageFromPayload(messages.ActionResponse{
|
||||||
|
Success: false,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := cfg.GetToken()
|
token, err := cfg.GetToken()
|
||||||
@ -56,7 +68,49 @@ func handleListSSH(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vau
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleImportSSH(msg messages.IPCMessage, cfg *config.Config, vault *vault.Vault, callingContext *sockets.CallingContext) (response messages.IPCMessage, err error) {
|
||||||
|
req := messages.ParsePayload(msg).(messages.ImportSSHKeyRequest)
|
||||||
|
|
||||||
|
cipher, _, err := ssh.SSHKeyCipherFromKey(req.Name, req.Key, vault.Keyring)
|
||||||
|
if err != nil {
|
||||||
|
response, err = messages.IPCMessageFromPayload(messages.ActionResponse{
|
||||||
|
Success: false,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = messages.IPCMessageFromPayload(messages.ActionResponse{
|
||||||
|
Success: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
response, err = messages.IPCMessageFromPayload(messages.ActionResponse{
|
||||||
|
Success: false,
|
||||||
|
Message: err.Error(),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := cfg.GetToken()
|
||||||
|
if err != nil {
|
||||||
|
actionsLog.Warn(err.Error())
|
||||||
|
}
|
||||||
|
ctx := context.WithValue(context.TODO(), bitwarden.AuthToken{}, token.AccessToken)
|
||||||
|
postedCipher, err := bitwarden.PostCipher(ctx, cipher, cfg)
|
||||||
|
if err == nil {
|
||||||
|
vault.AddOrUpdateSecureNote(postedCipher)
|
||||||
|
} else {
|
||||||
|
actionsLog.Warn("Error posting ssh key cipher: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err = messages.IPCMessageFromPayload(messages.ImportSSHKeyResponse{
|
||||||
|
Success: true,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.CreateSSHKeyRequest{}), ensureEverything(systemauth.SSHKey, handleAddSSH))
|
AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.CreateSSHKeyRequest{}), ensureEverything(systemauth.SSHKey, handleAddSSH))
|
||||||
AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.GetSSHKeysRequest{}), ensureIsNotLocked(ensureIsLoggedIn(handleListSSH)))
|
AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.GetSSHKeysRequest{}), ensureIsNotLocked(ensureIsLoggedIn(handleListSSH)))
|
||||||
|
AgentActionsRegistry.Register(messages.MessageTypeForEmptyPayload(messages.ImportSSHKeyRequest{}), ensureEverything(systemauth.SSHKey, handleImportSSH))
|
||||||
}
|
}
|
||||||
|
@ -255,12 +255,11 @@ func parseMessageTypeFromMessagePack(messagePack []byte) (int8, string, bool) {
|
|||||||
return 0, "", false
|
return 0, "", false
|
||||||
}
|
}
|
||||||
if len(value) < 5 {
|
if len(value) < 5 {
|
||||||
websocketLog.Warn("Invalid message received, length too short")
|
|
||||||
return 0, "", false
|
return 0, "", false
|
||||||
}
|
}
|
||||||
value, success := value[4].([]interface{})
|
value, success := value[4].([]interface{})
|
||||||
if len(value) < 1 || !success {
|
if len(value) < 1 || !success {
|
||||||
websocketLog.Warn("Invalid message received, length too short")
|
websocketLog.Warn("Invalid message received, value length less than 1")
|
||||||
return 0, "", false
|
return 0, "", false
|
||||||
}
|
}
|
||||||
value1, success := value[0].(map[string]interface{})
|
value1, success := value[0].(map[string]interface{})
|
||||||
|
@ -12,8 +12,55 @@ import (
|
|||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewSSHKeyCipher(name string, keyring *crypto.Keyring) (models.Cipher, string) {
|
// todo refactor to share code
|
||||||
|
func SSHKeyCipherFromKey(name string, privateKey string, keyring *crypto.Keyring) (models.Cipher, string, error) {
|
||||||
|
signer, err := ssh.ParsePrivateKey([]byte(privateKey))
|
||||||
|
if err != nil {
|
||||||
|
return models.Cipher{}, "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
pubKey := signer.PublicKey()
|
||||||
|
encryptedName, _ := crypto.EncryptWith([]byte(name), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey())
|
||||||
|
encryptedPublicKeyKey, _ := crypto.EncryptWith([]byte("public-key"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey())
|
||||||
|
encryptedPublicKeyValue, _ := crypto.EncryptWith([]byte(string(ssh.MarshalAuthorizedKey(pubKey))), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey())
|
||||||
|
encryptedCustomTypeKey, _ := crypto.EncryptWith([]byte("custom-type"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey())
|
||||||
|
encryptedCustomTypeValue, _ := crypto.EncryptWith([]byte("ssh-key"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey())
|
||||||
|
encryptedPrivateKeyKey, _ := crypto.EncryptWith([]byte("private-key"), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey())
|
||||||
|
encryptedPrivateKeyValue, _ := crypto.EncryptWith([]byte(privateKey), crypto.AesCbc256_HmacSha256_B64, keyring.GetAccountKey())
|
||||||
|
|
||||||
|
cipher := models.Cipher{
|
||||||
|
Type: models.CipherNote,
|
||||||
|
Name: encryptedName,
|
||||||
|
Notes: &encryptedPublicKeyValue,
|
||||||
|
ID: nil,
|
||||||
|
Favorite: false,
|
||||||
|
OrganizationID: nil,
|
||||||
|
SecureNote: &models.SecureNoteCipher{
|
||||||
|
Type: 0,
|
||||||
|
},
|
||||||
|
Fields: []models.Field{
|
||||||
|
{
|
||||||
|
Type: 0,
|
||||||
|
Name: encryptedCustomTypeKey,
|
||||||
|
Value: encryptedCustomTypeValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: 0,
|
||||||
|
Name: encryptedPublicKeyKey,
|
||||||
|
Value: encryptedPublicKeyValue,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Type: 1,
|
||||||
|
Name: encryptedPrivateKeyKey,
|
||||||
|
Value: encryptedPrivateKeyValue,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return cipher, string(ssh.MarshalAuthorizedKey(pubKey)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSSHKeyCipher(name string, keyring *crypto.Keyring) (models.Cipher, string, error) {
|
||||||
var reader io.Reader = rand.Reader
|
var reader io.Reader = rand.Reader
|
||||||
pub, priv, err := ed25519.GenerateKey(reader)
|
pub, priv, err := ed25519.GenerateKey(reader)
|
||||||
|
|
||||||
@ -72,5 +119,5 @@ func NewSSHKeyCipher(name string, keyring *crypto.Keyring) (models.Cipher, strin
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return cipher, string(ssh.MarshalAuthorizedKey(publicKey))
|
return cipher, string(ssh.MarshalAuthorizedKey(publicKey)), nil
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,22 @@
|
|||||||
//go:build freebsd || linux
|
//go:build freebsd || linux || darwin
|
||||||
|
|
||||||
package pinentry
|
package pinentry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
"github.com/twpayne/go-pinentry"
|
"github.com/twpayne/go-pinentry"
|
||||||
)
|
)
|
||||||
|
|
||||||
func getPassword(title string, description string) (string, error) {
|
func getPassword(title string, description string) (string, error) {
|
||||||
|
binaryClientOption := pinentry.WithBinaryNameFromGnuPGAgentConf()
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
binaryClientOption = pinentry.WithBinaryName("pinentry-mac")
|
||||||
|
}
|
||||||
|
|
||||||
client, err := pinentry.NewClient(
|
client, err := pinentry.NewClient(
|
||||||
pinentry.WithBinaryNameFromGnuPGAgentConf(),
|
binaryClientOption,
|
||||||
pinentry.WithGPGTTY(),
|
pinentry.WithGPGTTY(),
|
||||||
pinentry.WithTitle(title),
|
pinentry.WithTitle(title),
|
||||||
pinentry.WithDesc(description),
|
pinentry.WithDesc(description),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//go:build windows || darwin
|
//go:build windows
|
||||||
|
|
||||||
package pinentry
|
package pinentry
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -18,12 +19,12 @@ var sshCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// runCmd represents the run command
|
// sshAddCmd represents the ssh add command
|
||||||
var sshAddCmd = &cobra.Command{
|
var sshAddCmd = &cobra.Command{
|
||||||
Use: "add",
|
Use: "add",
|
||||||
Short: "Runs a command with environment variables from your vault",
|
Short: "Creates a new SSH key and adds it to the SSH Agent.",
|
||||||
Long: `Runs a command with environment variables from your vault.
|
Long: `Creates a new SSH key and adds it to the SSH Agent.
|
||||||
The variables are stored as a secure note. Consult the documentation for more information.`,
|
The key is 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) {
|
||||||
err := loginIfRequired()
|
err := loginIfRequired()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -92,6 +93,59 @@ var listSSHCmd = &cobra.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var importSSHCmd = &cobra.Command{
|
||||||
|
Use: "import",
|
||||||
|
Short: "Imports an SSH key into your vault",
|
||||||
|
Long: `Imports an SSH key into your vault.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
filename := args[0]
|
||||||
|
fmt.Println("Importing SSH key from " + filename)
|
||||||
|
|
||||||
|
name, _ := cmd.Flags().GetString("name")
|
||||||
|
if name == "" {
|
||||||
|
name = "Imported SSH Key"
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||||
|
fmt.Println("Error: File does not exist")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error: " + err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
buf.ReadFrom(file)
|
||||||
|
key := buf.String()
|
||||||
|
|
||||||
|
result, err := commandClient.SendToAgent(messages.ImportSSHKeyRequest{
|
||||||
|
Key: key,
|
||||||
|
Name: name,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
handleSendToAgentError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch result.(type) {
|
||||||
|
case messages.ImportSSHKeyResponse:
|
||||||
|
response := result.(messages.ImportSSHKeyResponse)
|
||||||
|
if response.Success {
|
||||||
|
fmt.Println("Success")
|
||||||
|
} else {
|
||||||
|
fmt.Println("Error: " + response.ErrorMsg)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
case messages.ActionResponse:
|
||||||
|
fmt.Println("Error: " + result.(messages.ActionResponse).Message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(sshCmd)
|
rootCmd.AddCommand(sshCmd)
|
||||||
sshCmd.AddCommand(sshAddCmd)
|
sshCmd.AddCommand(sshAddCmd)
|
||||||
@ -99,4 +153,6 @@ func init() {
|
|||||||
_ = sshAddCmd.MarkFlagRequired("name")
|
_ = sshAddCmd.MarkFlagRequired("name")
|
||||||
sshAddCmd.PersistentFlags().Bool("clipboard", false, "Copy the public key to the clipboard")
|
sshAddCmd.PersistentFlags().Bool("clipboard", false, "Copy the public key to the clipboard")
|
||||||
sshCmd.AddCommand(listSSHCmd)
|
sshCmd.AddCommand(listSSHCmd)
|
||||||
|
importSSHCmd.PersistentFlags().String("name", "", "")
|
||||||
|
sshCmd.AddCommand(importSSHCmd)
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,16 @@ type GetSSHKeysResponse struct {
|
|||||||
Keys []string
|
Keys []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ImportSSHKeyRequest struct {
|
||||||
|
Key string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
type ImportSSHKeyResponse struct {
|
||||||
|
Success bool
|
||||||
|
ErrorMsg string
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registerPayloadParser(func(payload []byte) (interface{}, error) {
|
registerPayloadParser(func(payload []byte) (interface{}, error) {
|
||||||
var req CreateSSHKeyRequest
|
var req CreateSSHKeyRequest
|
||||||
@ -53,4 +63,22 @@ func init() {
|
|||||||
}
|
}
|
||||||
return req, nil
|
return req, nil
|
||||||
}, GetSSHKeysResponse{})
|
}, GetSSHKeysResponse{})
|
||||||
|
|
||||||
|
registerPayloadParser(func(payload []byte) (interface{}, error) {
|
||||||
|
var req ImportSSHKeyRequest
|
||||||
|
err := json.Unmarshal(payload, &req)
|
||||||
|
if err != nil {
|
||||||
|
panic("Unmarshal: " + err.Error())
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}, ImportSSHKeyRequest{})
|
||||||
|
|
||||||
|
registerPayloadParser(func(payload []byte) (interface{}, error) {
|
||||||
|
var req ImportSSHKeyResponse
|
||||||
|
err := json.Unmarshal(payload, &req)
|
||||||
|
if err != nil {
|
||||||
|
panic("Unmarshal: " + err.Error())
|
||||||
|
}
|
||||||
|
return req, nil
|
||||||
|
}, ImportSSHKeyResponse{})
|
||||||
}
|
}
|
||||||
|
10
go.mod
10
go.mod
@ -19,15 +19,15 @@ require (
|
|||||||
github.com/lox/go-touchid v0.0.0-20170712105233-619cc8e578d0
|
github.com/lox/go-touchid v0.0.0-20170712105233-619cc8e578d0
|
||||||
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a
|
github.com/mikesmitty/edkey v0.0.0-20170222072505-3356ea4e686a
|
||||||
github.com/mitchellh/go-ps v1.0.0
|
github.com/mitchellh/go-ps v1.0.0
|
||||||
github.com/rymdport/portal v0.2.2
|
github.com/rymdport/portal v0.2.3
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4
|
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4
|
||||||
github.com/tink-crypto/tink-go/v2 v2.1.0
|
github.com/tink-crypto/tink-go/v2 v2.2.0
|
||||||
github.com/twpayne/go-pinentry v0.3.0
|
github.com/twpayne/go-pinentry v0.3.0
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1
|
github.com/vmihailenco/msgpack/v5 v5.4.1
|
||||||
golang.org/x/crypto v0.22.0
|
golang.org/x/crypto v0.23.0
|
||||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f
|
||||||
golang.org/x/sys v0.19.0
|
golang.org/x/sys v0.20.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -56,5 +56,3 @@ require (
|
|||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
replace github.com/rymdport/portal => github.com/quexten/portal v0.0.0-20240429200240-156297fa11c5
|
|
||||||
|
24
go.sum
24
go.sum
@ -76,8 +76,6 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/quexten/portal v0.0.0-20240429200240-156297fa11c5 h1:roVJ7WlvNo3R4NfVLysq3siLrVZgotg/JZkZ1dQEZ5k=
|
|
||||||
github.com/quexten/portal v0.0.0-20240429200240-156297fa11c5/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
|
|
||||||
github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM=
|
github.com/reiver/go-oi v1.0.0 h1:nvECWD7LF+vOs8leNGV/ww+F2iZKf3EYjYZ527turzM=
|
||||||
github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI=
|
github.com/reiver/go-oi v1.0.0/go.mod h1:RrDBct90BAhoDTxB1fenZwfykqeGvhI6LsNfStJoEkI=
|
||||||
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas=
|
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e h1:quuzZLi72kkJjl+f5AQ93FMcadG19WkS7MO6TXFOSas=
|
||||||
@ -86,6 +84,8 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
|||||||
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
|
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
|
||||||
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/rymdport/portal v0.2.3 h1:5RoAuMy5wNzEzITwK+9YpMQLU5m7F7IYfmPwN/aVpUk=
|
||||||
|
github.com/rymdport/portal v0.2.3/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
|
||||||
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
|
||||||
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
@ -98,16 +98,16 @@ github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG0
|
|||||||
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
|
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
|
||||||
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 h1:Gz0rz40FvFVLTBk/K8UNAenb36EbDSnh+q7Z9ldcC8w=
|
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4 h1:Gz0rz40FvFVLTBk/K8UNAenb36EbDSnh+q7Z9ldcC8w=
|
||||||
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4/go.mod h1:phI29ccmHQBc+wvroosENp1IF9195449VDnFDhJ4rJU=
|
github.com/tailscale/peercred v0.0.0-20240214030740-b535050b2aa4/go.mod h1:phI29ccmHQBc+wvroosENp1IF9195449VDnFDhJ4rJU=
|
||||||
github.com/tink-crypto/tink-go/v2 v2.1.0 h1:QXFBguwMwTIaU17EgZpEJWsUSc60b1BAGTzBIoMdmok=
|
github.com/tink-crypto/tink-go/v2 v2.2.0 h1:L2Da0F2Udh2agtKztdr69mV/KpnY3/lGTkMgLTVIXlA=
|
||||||
github.com/tink-crypto/tink-go/v2 v2.1.0/go.mod h1:y1TnYFt1i2eZVfx4OGc+C+EMp4CoKWAw2VSEuoicHHI=
|
github.com/tink-crypto/tink-go/v2 v2.2.0/go.mod h1:JJ6PomeNPF3cJpfWC0lgyTES6zpJILkAX0cJNwlS3xU=
|
||||||
github.com/twpayne/go-pinentry v0.3.0 h1:Rr+fEOZXmeItOb4thjeVaBWJKB9Xa/eojolycyF/26c=
|
github.com/twpayne/go-pinentry v0.3.0 h1:Rr+fEOZXmeItOb4thjeVaBWJKB9Xa/eojolycyF/26c=
|
||||||
github.com/twpayne/go-pinentry v0.3.0/go.mod h1:iOIZD+9np/2V24OdCGos7Y1/xX90wc6VEAZsgb+r9D4=
|
github.com/twpayne/go-pinentry v0.3.0/go.mod h1:iOIZD+9np/2V24OdCGos7Y1/xX90wc6VEAZsgb+r9D4=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
||||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
||||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||||
@ -118,12 +118,12 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import src.linux.main as linux_main
|
|
||||||
|
|
||||||
linux_main.main()
|
import platform
|
||||||
|
|
||||||
|
if platform.system() == 'Darwin':
|
||||||
|
import src.macos.main as macos_main
|
||||||
|
macos_main.main()
|
||||||
|
elif platform.system() == 'Linux':
|
||||||
|
import src.linux.main as linux_main
|
||||||
|
linux_main.main()
|
||||||
|
else:
|
||||||
|
print("Unsupported OS " + platform.system() + "... exiting...")
|
@ -1,10 +1,10 @@
|
|||||||
import gi
|
import gi
|
||||||
gi.require_version('Gtk', '4.0')
|
gi.require_version('Gtk', '4.0')
|
||||||
gi.require_version('Adw', '1')
|
gi.require_version('Adw', '1')
|
||||||
gi.require_version('Notify', '0.7')
|
# gi.require_version('Notify', '0.7')
|
||||||
import gc
|
import gc
|
||||||
import time
|
import time
|
||||||
from gi.repository import Gtk, Adw, GLib, Notify, Gdk
|
from gi.repository import Gtk, Adw, GLib, Gdk
|
||||||
from ..services import goldwarden
|
from ..services import goldwarden
|
||||||
from ..services.autotype import autotype
|
from ..services.autotype import autotype
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
@ -12,7 +12,6 @@ from .resource_loader import load_template
|
|||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
from ..services import totp
|
from ..services import totp
|
||||||
Notify.init("Goldwarden")
|
|
||||||
|
|
||||||
class GoldwardenQuickAccessApp(Adw.Application):
|
class GoldwardenQuickAccessApp(Adw.Application):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@ -115,8 +114,8 @@ class GoldwardenQuickAccessApp(Adw.Application):
|
|||||||
|
|
||||||
def run_autotype(self, text):
|
def run_autotype(self, text):
|
||||||
def perform_autotype(text):
|
def perform_autotype(text):
|
||||||
self.window.hide()
|
GLib.idle_add(self.window.hide)
|
||||||
time.sleep(0.1)
|
time.sleep(2)
|
||||||
autotype.autotype(text)
|
autotype.autotype(text)
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
@ -148,7 +147,7 @@ class GoldwardenQuickAccessApp(Adw.Application):
|
|||||||
self.filtered_logins = self.filtered_logins[0:7]
|
self.filtered_logins = self.filtered_logins[0:7]
|
||||||
|
|
||||||
def render_list(self):
|
def render_list(self):
|
||||||
if len(self.filtered_logins) > 1:
|
if len(self.filtered_logins) > 0:
|
||||||
self.results_list.set_visible(True)
|
self.results_list.set_visible(True)
|
||||||
while self.results_list.get_first_child() != None:
|
while self.results_list.get_first_child() != None:
|
||||||
self.results_list.remove(self.results_list.get_first_child())
|
self.results_list.remove(self.results_list.get_first_child())
|
||||||
|
@ -101,8 +101,7 @@ class GoldwardenSettingsApp(Adw.Application):
|
|||||||
if status == None:
|
if status == None:
|
||||||
is_daemon_running = goldwarden.is_daemon_running()
|
is_daemon_running = goldwarden.is_daemon_running()
|
||||||
if not is_daemon_running:
|
if not is_daemon_running:
|
||||||
self.status_row.set_subtitle("Daemon not running")
|
print("Daemon not running")
|
||||||
self.vault_status_icon.set_icon("dialog-error", "error")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
logged_in = status["loggedIn"]
|
logged_in = status["loggedIn"]
|
||||||
|
@ -7,6 +7,7 @@ gi.require_version('Gtk', '4.0')
|
|||||||
gi.require_version('Adw', '1')
|
gi.require_version('Adw', '1')
|
||||||
from gi.repository import GLib, Gio
|
from gi.repository import GLib, Gio
|
||||||
import sys
|
import sys
|
||||||
|
from threading import Timer
|
||||||
|
|
||||||
def set_status(message):
|
def set_status(message):
|
||||||
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
|
||||||
@ -29,9 +30,13 @@ def set_status(message):
|
|||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
set_status(sys.argv[1])
|
set_status(sys.argv[1])
|
||||||
|
|
||||||
|
thread = Timer(10, sys.exit, [0])
|
||||||
|
thread.start()
|
||||||
|
|
||||||
loop = GLib.MainLoop()
|
loop = GLib.MainLoop()
|
||||||
loop.run()
|
loop.run()
|
||||||
|
30
gui/src/macos/main.py
Normal file
30
gui/src/macos/main.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import os
|
||||||
|
import secrets
|
||||||
|
from src.services import goldwarden
|
||||||
|
from src.services import pinentry
|
||||||
|
import time
|
||||||
|
|
||||||
|
root_path = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir, os.pardir))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
token = secrets.token_hex(32)
|
||||||
|
if not os.environ.get("GOLDWARDEN_DAEMON_AUTH_TOKEN") == None:
|
||||||
|
token = os.environ["GOLDWARDEN_DAEMON_AUTH_TOKEN"]
|
||||||
|
print("Starting Goldwarden GUI")
|
||||||
|
goldwarden.run_daemon_background(token)
|
||||||
|
time.sleep(1)
|
||||||
|
#pinentry.daemonize()
|
||||||
|
if not "--hidden" in sys.argv:
|
||||||
|
p = subprocess.Popen(["python3", "-m", "src.gui.settings"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=root_path, start_new_session=True)
|
||||||
|
p.stdin.write(f"{token}\n".encode())
|
||||||
|
p.stdin.flush()
|
||||||
|
# print stdout
|
||||||
|
while True:
|
||||||
|
line = p.stderr.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
print(line.decode().strip())
|
||||||
|
while True:
|
||||||
|
time.sleep(60)
|
@ -1,5 +1,5 @@
|
|||||||
from ..goldwarden import autotype
|
from ..goldwarden import autotype
|
||||||
|
|
||||||
def libportal_autotype(text):
|
def autotype_libportal(text):
|
||||||
print("autotypeing with libportal")
|
print("autotypeing with libportal")
|
||||||
goldwarden.autotype(text)
|
goldwarden.autotype(text)
|
@ -2,4 +2,7 @@ import pyautogui
|
|||||||
|
|
||||||
def autotype_pyautogui(text):
|
def autotype_pyautogui(text):
|
||||||
print("autotypeing with pyautogui")
|
print("autotypeing with pyautogui")
|
||||||
pyautogui.write(text, interval=0.02)
|
pyautogui.write(text, interval=0.02)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
autotype_pyautogui("hello world")
|
Loading…
Reference in New Issue
Block a user