diff --git a/cmd/breakglass/breakglass.go b/cmd/breakglass/breakglass.go index f1e7f81..a96b031 100644 --- a/cmd/breakglass/breakglass.go +++ b/cmd/breakglass/breakglass.go @@ -23,6 +23,9 @@ import ( "time" "github.com/gokrazy/internal/config" + "github.com/gokrazy/internal/httpclient" + "github.com/gokrazy/internal/tlsflag" + "github.com/gokrazy/internal/updateflag" ) type bg struct { @@ -31,7 +34,6 @@ type bg struct { pw string forceRestart bool sshConfig string - gokrazyURL string // state GOARCH string @@ -42,26 +44,62 @@ func (bg *bg) startBreakglass() error { if err != nil { return err } - client := &http.Client{Jar: jar} - urlPrefix := "http://gokrazy:" + bg.pw + "@" + bg.hostname - if bg.gokrazyURL != "" { - if strings.HasPrefix(bg.gokrazyURL, ":") { - // Append port - urlPrefix += bg.gokrazyURL - } else { - // Overwrite URL - urlPrefix = strings.TrimSuffix(bg.gokrazyURL, "/") - } + + _, updateHostname := updateflag.GetUpdateTarget(bg.hostname) + const configBaseName = "http-password.txt" + pw, err := config.HostnameSpecific(updateHostname).ReadFile(configBaseName) + if err != nil { + return err } port, err := config.HostnameSpecific(bg.hostname).ReadFile("http-port.txt") if err != nil && !os.IsNotExist(err) { return err } - if port != "" { - urlPrefix += ":" + port + if port == "" { + port = "80" } - form, err := client.Get(urlPrefix + "/status?path=/user/breakglass") + schema := "http" + certPath, _, err := tlsflag.CertificatePathsFor(bg.hostname) + if err != nil { + return err + } + if certPath != "" { + schema = "https" + } + updateBaseUrl, err := updateflag.BaseURL(port, schema, bg.hostname, pw) + if err != nil { + return err + } + + updateHttpClient, foundMatchingCertificate, err := tlsflag.GetTLSHttpClient(updateBaseUrl) + if err != nil { + return fmt.Errorf("getting http client by tls flag: %v", err) + } + updateHttpClient.Jar = jar + + remoteScheme, err := httpclient.GetRemoteScheme(updateBaseUrl) + if remoteScheme == "https" && !tlsflag.Insecure() { + updateBaseUrl.Scheme = "https" + updateflag.SetUpdate(updateBaseUrl.String()) + } + + if updateBaseUrl.Scheme != "https" && foundMatchingCertificate { + fmt.Printf("\n") + fmt.Printf("!!!WARNING!!! Possible SSL-Stripping detected!\n") + fmt.Printf("Found certificate for hostname in your client configuration but the host does not offer https!\n") + fmt.Printf("\n") + if !tlsflag.Insecure() { + log.Fatalf("update canceled: TLS certificate found, but negotiating a TLS connection with the target failed") + } + fmt.Printf("Proceeding anyway as requested (-insecure).\n") + } + + if err != nil { + return err + } + + form, err := updateHttpClient.Get(updateBaseUrl.String() + "status?path=/user/breakglass") if err != nil { return err } @@ -94,14 +132,14 @@ func (bg *bg) startBreakglass() error { } log.Printf("restarting breakglass") - resp, err := client.Post(urlPrefix+"/restart?path=/user/breakglass&xsrftoken="+xsrfToken, "", nil) + resp, err := updateHttpClient.Post(updateBaseUrl.String()+"restart?path=/user/breakglass&xsrftoken="+xsrfToken, "", nil) if err != nil { return err } if got, want := resp.StatusCode, http.StatusOK; got != want { b, _ := ioutil.ReadAll(form.Body) return fmt.Errorf("restarting breakglass: unexpected HTTP status: got %v (%s), want %v", - form.Status, + resp.Status, strings.TrimSpace(string(b)), want) } @@ -195,13 +233,11 @@ func breakglass() error { "ssh_config", "", "an alternative per-user configuration file for ssh and scp") - - gokrazyURL = flag.String( - "gokrazy_url", - "", - "a full URL like http://gokrazy:secret@host/") ) + tlsflag.RegisterFlags(flag.CommandLine) + updateflag.RegisterFlags(flag.CommandLine, "gokrazy_url") + flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n\n", os.Args[0]) @@ -216,6 +252,14 @@ func breakglass() error { if flag.NArg() < 1 { log.Fatalf("syntax: breakglass [command]") } + + // If the user did not explicitly specify -update=yes, we default to it. + // This differs from the gokr-packer, but breakglass is only useful for + // gokrazy instances that already exist. + if updateflag.NewInstallation() { + updateflag.SetUpdate("yes") + } + hostname := flag.Arg(0) b, err := config.HostnameSpecific(hostname).ReadFile("http-password.txt") @@ -228,7 +272,6 @@ func breakglass() error { pw: pw, forceRestart: *forceRestart, sshConfig: *sshConfig, - gokrazyURL: *gokrazyURL, } log.Printf("checking breakglass status on gokrazy installation %q", hostname) diff --git a/go.mod b/go.mod index 535a230..e201c64 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.17 require ( github.com/gokrazy/gokrazy v0.0.0-20211024151958-b718dd90ae71 - github.com/gokrazy/internal v0.0.0-20210621162516-1b3b5687a06d + github.com/gokrazy/internal v0.0.0-20220430192544-1821f343e404 github.com/google/renameio/v2 v2.0.0 github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf github.com/kr/pty v1.1.8 @@ -16,7 +16,7 @@ require ( github.com/creack/pty v1.1.7 // indirect github.com/kr/fs v0.1.0 // indirect github.com/mdlayher/watchdog v0.0.0-20201005150459-8bdc4f41966b // indirect - github.com/pkg/errors v0.9.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect rsc.io/goversion v1.2.0 // indirect ) diff --git a/go.sum b/go.sum index 59dcc44..857da22 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,9 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gokrazy/gokrazy v0.0.0-20211024151958-b718dd90ae71 h1:NHLkr4NYMY9gZGTI+jzIo38ZffMHkPbBzMcUDkyHs0g= github.com/gokrazy/gokrazy v0.0.0-20211024151958-b718dd90ae71/go.mod h1:eq2ROPhZJtxxEi21P8cbNqP8pwRBSpW/4LGKwNiQg2Y= -github.com/gokrazy/internal v0.0.0-20210621162516-1b3b5687a06d h1:qk95CKJfxvU5oi3lbrVkEgID5ak1pOjTyPTdaXs6Q9E= github.com/gokrazy/internal v0.0.0-20210621162516-1b3b5687a06d/go.mod h1:Gqv1x1DNrObmBvVvblpZbvZizZ0dU5PwiwYHipmtY9Y= +github.com/gokrazy/internal v0.0.0-20220430192544-1821f343e404 h1:2VNhTnO4DjxaH6U/hpFMzllkSyBL4aPRabMxMVuuhJs= +github.com/gokrazy/internal v0.0.0-20220430192544-1821f343e404/go.mod h1:Gc9sU6yJ/qxg3gJZ1pjfcTAULa0swdTa4TH51g1e00E= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gopacket v1.1.16/go.mod h1:UCLx9mCmAwsVbn6qQl1WIEt2SO7Nd2fD0th1TBAsqBw= @@ -22,45 +23,31 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/mdlayher/raw v0.0.0-20190303161257-764d452d77af/go.mod h1:rC/yE65s/DoHB6BzVOUBNYBGTg772JVytyAytffIZkY= github.com/mdlayher/watchdog v0.0.0-20201005150459-8bdc4f41966b h1:7tUBfsEEBWfFeHOB7CUfoOamak+Gx/BlirfXyPk1WjI= github.com/mdlayher/watchdog v0.0.0-20201005150459-8bdc4f41966b/go.mod h1:bmoJUS6qOA3uKFvF3KVuhf7mU1KQirzQMeHXtPyKEqg= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.13.0 h1:Riw6pgOKK41foc1I1Uu03CjvbLZDXeGpInycM4shXoI= -github.com/pkg/sftp v1.13.0/go.mod h1:41g+FIPlQUTDCveupEmEA65IoiQFrtgCeDopC4ajGIM= github.com/pkg/sftp v1.13.5-0.20220330091711-a17a626ab843 h1:aIV4Pjj4gI4eGy8t60Pfji8tdDDohxwBU5ZCb4ulHvw= github.com/pkg/sftp v1.13.5-0.20220330091711-a17a626ab843/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg= 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/rtr7/dhcp4 v0.0.0-20181120124042-778e8c2e24a5/go.mod h1:FwstIpm6vX98QgtR8KEwZcVjiRn2WP76LjXAHj84fK0= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871 h1:/pEO3GD/ABYAjuakUS6xSEmmlyVS4kxBNkeA9tLJiTI= -golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201005065044-765f4ea38db3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4= golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=