Skip to content

Commit

Permalink
Install user components on startup; Install KBFS later (keybase#7733)
Browse files Browse the repository at this point in the history
* Install user components (only) on startup

* Exit with non-zero code on install error

* Use go install path exclusively; Allow mount-type none

* Fuse status and install from RPC folders tab

* Fix install helper CLI missing

* Install result, progress indicators

* Auto install based on fuse status

* Default non-darwin methods for service compile

* Move CLI uninstall last

* Fix dead code

* Uninstall KBFS rpc

* Install option for /etc/paths.d in native installer

Instead of CLI, which is handled by go install package.
Also remove install all option which is ununsed and not entirely
accurate (it's not all).


* Upgrade fuse to 3.6.3

* Update Xcode instructions

* Install banner

* Security prefs UI

* Break up into install fuse, load kext, install KBFS

* Return specific fuse status error codes

* Have to load kext to get perm error later

* Need to load kext after install to trigger system policy block

* Don't want Quit dialog on error

* Fuse install with kextPermissionRequired status

* Set permission error

* Kext error from install

* Load kext on install

* Remove unused loadFuseKext

* Refresh fuse status on focus if in secprefs

* Finish install after kextStarting

* Update DMG background

* Install everything is Fuse is installed

* Underline properly even in widget

* Handle general Fuse kext error

* Update comment

* Uninstall KBFS impl

* Install/uninstall CLI privileged

* Fix compile

* Fix installing indication

* Change some text on uninstall, move open link

* Remove progress indicator

* Don't show banner in small mode

* Wait for mount and open after install

* Wait for mount, show progress

* Back button instead of close

* Open after KBFS install (show progress)

* Change uninstall wording

* Set opening before finished

* Un-stale protocol

* Open in KBFS on link click

* Parse and handle install errors in app

* Fix comment

* Install docs

* Update docs

* Diagram for installer

* Install CLI privileged on CLI error

* Don't uninstall cli paths by default

* Remove test code

* Move CLI to last

* Fix links

* Type the actions

* Rename to getFuseStatus

* Use compose branch for Banner

* Fix action is method

* Needs to call saga

* Fuse status update saga

* Fix saga getting canceled

* Move fuse status to promise all

* Type actions

* Remove existing /usr/local/bin/keybase

* Ensure that it is a link and resolves correctly for installed

* Overwrite non-symlink on cli install

Do Windows version of split install
  • Loading branch information
gabriel authored and Steve Sanders committed Aug 25, 2017
1 parent d22b643 commit 8a073ff
Show file tree
Hide file tree
Showing 92 changed files with 2,100 additions and 354 deletions.
2 changes: 1 addition & 1 deletion go/client/cmd_ctl_start_osx.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func ctlStart(g *libkb.GlobalContext, components map[string]bool) error {
}
}
if ok := components[install.ComponentNameKBFS.String()]; ok {
if err := install.InstallKBFS(g, "", false, defaultLaunchdWait, g.Log); err != nil {
if err := install.InstallKBFS(g, "", false, false, defaultLaunchdWait, g.Log); err != nil {
errs = append(errs, err)
g.Log.Errorf("%s", err)
}
Expand Down
91 changes: 89 additions & 2 deletions go/client/cmd_install_osx.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func NewCmdInstall(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Comma
},
cli.StringFlag{
Name: "o, format",
Usage: "Format for output. Specify 'j' for JSON or blank for default.",
Usage: "Format for output. Specify 'json' for JSON or blank for default.",
},
cli.StringFlag{
Name: "b, bin-path",
Expand Down Expand Up @@ -87,6 +87,9 @@ func (v *CmdInstall) GetUsage() libkb.Usage {
var defaultInstallComponents = []string{
install.ComponentNameUpdater.String(),
install.ComponentNameService.String(),
install.ComponentNameCLI.String(),
install.ComponentNameHelper.String(),
install.ComponentNameFuse.String(),
install.ComponentNameMountDir.String(),
install.ComponentNameKBFS.String(),
install.ComponentNameKBNM.String(),
Expand Down Expand Up @@ -141,9 +144,21 @@ func (v *CmdInstall) Run() error {
}
fmt.Fprintf(os.Stdout, "%s\n", out)
}
exitOnError(result)
return nil
}

func exitOnError(result keybase1.InstallResult) {
if result.Fatal {
os.Exit(1)
}
for _, r := range result.ComponentResults {
if r.Status.Code != 0 {
os.Exit(2)
}
}
}

var defaultUninstallComponents = []string{
install.ComponentNameService.String(),
install.ComponentNameKBFS.String(),
Expand All @@ -161,7 +176,7 @@ func NewCmdUninstall(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Com
Flags: []cli.Flag{
cli.StringFlag{
Name: "o, format",
Usage: "Format for output. Specify 'j' for JSON or blank for default.",
Usage: "Format for output. Specify 'json' for JSON or blank for default.",
},
cli.StringFlag{
Name: "c, components",
Expand Down Expand Up @@ -274,3 +289,75 @@ func DiagnoseSocketError(ui libkb.UI, err error) {
}
}
}

func newCmdInstallAuto(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
return cli.Command{
Name: "install-auto",
Flags: []cli.Flag{
cli.StringFlag{
Name: "b, bin-path",
Usage: "Full path to the executable, if it would be ambiguous otherwise.",
},
cli.DurationFlag{
Name: "t, timeout",
Usage: "Timeout as duration, such as '10s' or '1m'.",
},
cli.StringFlag{
Name: "source-path",
Usage: "Source path to app bundle.",
},
cli.StringFlag{
Name: "o, format",
Usage: "Format for output. Specify 'json' for JSON or blank for default.",
},
},
ArgumentHelp: "",
Usage: "Installs Keybase by choosing automatically which components to install",
Action: func(c *cli.Context) {
cl.SetLogForward(libcmdline.LogForwardNone)
cl.SetForkCmd(libcmdline.NoFork)
cl.ChooseCommand(newCmdInstallAutoRunner(g), "install-auto", c)
},
}
}

type cmdInstallAuto struct {
libkb.Contextified
binPath string
sourcePath string
format string
timeout time.Duration
}

func newCmdInstallAutoRunner(g *libkb.GlobalContext) *cmdInstallAuto {
return &cmdInstallAuto{
Contextified: libkb.NewContextified(g),
}
}

func (v *cmdInstallAuto) GetUsage() libkb.Usage {
return libkb.Usage{}
}

func (v *cmdInstallAuto) ParseArgv(ctx *cli.Context) error {
v.binPath = ctx.String("bin-path")
v.timeout = ctx.Duration("timeout")
v.sourcePath = ctx.String("source-path")
v.format = ctx.String("format")
if v.timeout == 0 {
v.timeout = 11 * time.Second
}
return nil
}

func (v *cmdInstallAuto) Run() error {
result := install.InstallAuto(v.G(), v.binPath, v.sourcePath, v.timeout, v.G().Log)
if v.format == "json" {
out, err := json.MarshalIndent(result, "", " ")
if err != nil {
return err
}
fmt.Fprintf(os.Stdout, "%s\n", out)
}
return nil
}
17 changes: 15 additions & 2 deletions go/client/cmd_kbfs_mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@
package client

import (
"encoding/json"
"errors"
"fmt"

"github.com/keybase/client/go/install"

"github.com/keybase/cli"
"github.com/keybase/client/go/libcmdline"
"github.com/keybase/client/go/libkb"
Expand All @@ -18,7 +21,7 @@ import (
func NewCmdKbfsMount(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command {
return cli.Command{
Name: "kbfsmount",
Usage: "kbfsmount [get|set|getall]",
Usage: "kbfsmount [get|set|getall|status|install]",
Action: func(c *cli.Context) {
cl.ChooseCommand(&CmdKbfsMount{libkb.NewContextified(g), "", ""}, "kbfsmount", c)
},
Expand All @@ -33,7 +36,7 @@ type CmdKbfsMount struct {

func (s *CmdKbfsMount) ParseArgv(ctx *cli.Context) error {
if len(ctx.Args()) < 1 {
return fmt.Errorf("kbfsmount needs one of [get|set|getall]")
return fmt.Errorf("kbfsmount needs one of [get|set|getall|status|install]")
}
s.cmd = ctx.Args()[0]
if s.cmd == "set" {
Expand Down Expand Up @@ -62,6 +65,16 @@ func (s *CmdKbfsMount) Run() error {
results, err2 := cli.GetAllAvailableMountDirs(context.TODO())
dui.Printf("%v", results)
err = err2
case "status":
status := install.KeybaseFuseStatus("", s.G().Log)
out, err := json.MarshalIndent(status, "", " ")
if err != nil {
return err
}
dui.Printf("%s\n", out)
case "install":
result := install.Install(s.G(), "", "", []string{install.ComponentNameFuse.String()}, false, 0, s.G().Log)
dui.Printf("%v\n", result.Status)
}
return err
}
Expand Down
4 changes: 2 additions & 2 deletions go/client/cmd_launchd_osx.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func NewCmdLaunchdList(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.C
Flags: []cli.Flag{
cli.StringFlag{
Name: "f, format",
Usage: "Format for output. Specify 'j' for JSON or blank for default.",
Usage: "Format for output. Specify 'json' for JSON or blank for default.",
},
},
Action: func(c *cli.Context) {
Expand Down Expand Up @@ -154,7 +154,7 @@ func NewCmdLaunchdStatus(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli
},
cli.StringFlag{
Name: "f, format",
Usage: "Format for output. Specify 'j' for JSON or blank for default.",
Usage: "Format for output. Specify 'json' for JSON or blank for default.",
},
cli.DurationFlag{
Name: "t, timeout",
Expand Down
1 change: 1 addition & 0 deletions go/client/commands_osx.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ func getPlatformSpecificCommands(cl *libcmdline.CommandLine, g *libkb.GlobalCont
return []cli.Command{
NewCmdFuse(cl, g),
NewCmdInstall(cl, g),
newCmdInstallAuto(cl, g),
NewCmdLaunchd(cl, g),
NewCmdUninstall(cl, g),
}
Expand Down
12 changes: 12 additions & 0 deletions go/install/fuse_status_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

// +build !darwin,!windows

package install

import "github.com/keybase/client/go/protocol/keybase1"

func KeybaseFuseStatus(bundleVersion string, log Log) keybase1.FuseStatus {
return keybase1.FuseStatus{}
}
61 changes: 61 additions & 0 deletions go/install/fuse_status_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

// +build windows

package install

import (
"github.com/keybase/client/go/protocol/keybase1"
"golang.org/x/sys/windows/registry"
)

func KeybaseFuseStatus(bundleVersion string, log Log) keybase1.FuseStatus {
status := keybase1.FuseStatus{}
if checkKeybaseDokanCodes(log) {
status.InstallStatus = keybase1.InstallStatus_INSTALLED
status.InstallAction = keybase1.InstallAction_NONE
status.KextStarted = true
} else {
status.InstallStatus = keybase1.InstallStatus_NOT_INSTALLED
status.InstallAction = keybase1.InstallAction_INSTALL
}
return status
}

func checkKeybaseDokanCodes(log Log) bool {
foundDokan, err := checkRegistryKeybaseDokan("DOKANPRODUCT64", log)
if !foundDokan || err != nil {
foundDokan, err = checkRegistryKeybaseDokan("DOKANPRODUCT86", log)
}
if err != nil {
log.Errorf("checkKeybaseDokanCodes error: %v", err.Error())
}
return foundDokan
}

// Our installer writes the dokan product codes to our registry location,
// which we can then look for in the list of windows uninstall keys.
// Another alternative might be to look for %windir%\system32\dokan1.dll
func checkRegistryKeybaseDokan(productIDKey string, log Log) (bool, error) {
k, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Keybase\Keybase\`, registry.QUERY_VALUE|registry.WOW64_64KEY)
if err != nil {
return false, err
}
defer k.Close()
productID, _, err := k.GetStringValue(productIDKey)
if err != nil {
return false, err
}
log.Info("CheckRegistryKeybaseDokan: Searching registry for %s", productID)
if productID == "" {
log.Info("CheckRegistryKeybaseDokan: Empty product ID, returning false")
return false, err
}
k2, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\`+productID, registry.QUERY_VALUE|registry.WOW64_64KEY)
if err == nil {
return true, nil
}
defer k2.Close()
return false, err
}
8 changes: 7 additions & 1 deletion go/install/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ const (
ComponentNameHelper ComponentName = "helper"
// ComponentNameMountDir is the mount directory
ComponentNameMountDir ComponentName = "mountdir"
// ComponentNameCLIPaths is for /etc/paths.d/Keybase
ComponentNameCLIPaths ComponentName = "clipaths"
// ComponentNameUnknown is placeholder for unknown components
ComponentNameUnknown ComponentName = "unknown"
)

// ComponentNames are all the valid component names
var ComponentNames = []ComponentName{ComponentNameCLI, ComponentNameService, ComponentNameKBFS, ComponentNameUpdater, ComponentNameFuse, ComponentNameHelper, ComponentNameApp, ComponentNameKBNM}
var ComponentNames = []ComponentName{ComponentNameCLI, ComponentNameService, ComponentNameKBFS, ComponentNameUpdater, ComponentNameFuse, ComponentNameHelper, ComponentNameApp, ComponentNameKBNM, ComponentNameCLIPaths}

// String returns string for ComponentName
func (c ComponentName) String() string {
Expand All @@ -93,6 +95,8 @@ func (c ComponentName) Description() string {
return "Privileged Helper Tool"
case ComponentNameKBNM:
return "Browser Native Messaging"
case ComponentNameCLIPaths:
return "Command Line (privileged)"
}
return "Unknown"
}
Expand All @@ -116,6 +120,8 @@ func ComponentNameFromString(s string) ComponentName {
return ComponentNameFuse
case string(ComponentNameHelper):
return ComponentNameHelper
case string(ComponentNameCLIPaths):
return ComponentNameCLIPaths
}
return ComponentNameUnknown
}
Expand Down
Loading

0 comments on commit 8a073ff

Please sign in to comment.