AUTH-1136: addressing beta feedback
This commit is contained in:
parent
674eb33edc
commit
170f0acf4f
|
@ -461,6 +461,6 @@
|
||||||
[solve-meta]
|
[solve-meta]
|
||||||
analyzer-name = "dep"
|
analyzer-name = "dep"
|
||||||
analyzer-version = 1
|
analyzer-version = 1
|
||||||
inputs-digest = "4270289ba5f418a18a65373d2914d463a52aabd200eae3d8898914b027c59803"
|
inputs-digest = "0907565b36c43c6a1c461648f1e69d0367864b61f112e01948f7b008e44598e5"
|
||||||
solver-name = "gps-cdcl"
|
solver-name = "gps-cdcl"
|
||||||
solver-version = 1
|
solver-version = 1
|
||||||
|
|
|
@ -7,13 +7,14 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/shell"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/shell"
|
||||||
|
"golang.org/x/net/idna"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/log"
|
"github.com/cloudflare/cloudflared/log"
|
||||||
raven "github.com/getsentry/raven-go"
|
raven "github.com/getsentry/raven-go"
|
||||||
cli "gopkg.in/urfave/cli.v2"
|
cli "gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sentryDSN = "https://5a81ca98270b4aee89d4d9913b259fec:583d2c118b384712aa8b91afbdabde81@sentry.cfops.it/170" // we probably need a public accessable url.
|
const sentryDSN = "https://56a9c9fa5c364ab28f34b14f35ea0f1b@sentry.io/189878"
|
||||||
|
|
||||||
// Flags return the global flags for Access related commands (hopefully none)
|
// Flags return the global flags for Access related commands (hopefully none)
|
||||||
func Flags() []cli.Flag {
|
func Flags() []cli.Flag {
|
||||||
|
@ -37,7 +38,7 @@ func Commands() []*cli.Command {
|
||||||
Action: login,
|
Action: login,
|
||||||
Usage: "login <url of access application>",
|
Usage: "login <url of access application>",
|
||||||
Description: `The login subcommand initiates an authentication flow with your identity provider.
|
Description: `The login subcommand initiates an authentication flow with your identity provider.
|
||||||
The subcommand will launch a browser. For headless systems, a URL is provided.
|
The subcommand will launch a browser. For headless systems, a url is provided.
|
||||||
Once authenticated with your identity provider, the login command will generate a JSON Web Token (JWT)
|
Once authenticated with your identity provider, the login command will generate a JSON Web Token (JWT)
|
||||||
scoped to your identity, the application you intend to reach, and valid for a session duration set by your
|
scoped to your identity, the application you intend to reach, and valid for a session duration set by your
|
||||||
administrator. cloudflared stores the token in local storage.`,
|
administrator. cloudflared stores the token in local storage.`,
|
||||||
|
@ -52,15 +53,10 @@ func Commands() []*cli.Command {
|
||||||
Name: "curl",
|
Name: "curl",
|
||||||
Action: curl,
|
Action: curl,
|
||||||
Usage: "curl <args>",
|
Usage: "curl <args>",
|
||||||
Description: `The curl subcommand wraps curl and automatically injects the JWT into a cf-jwt-access-assertion
|
Description: `The curl subcommand wraps curl and automatically injects the JWT into a cf-access-token
|
||||||
header when using curl to reach an application behind Access.`,
|
header when using curl to reach an application behind Access.`,
|
||||||
ArgsUsage: "nojwt will allow the curl request to continue even if the jwt is not present.",
|
ArgsUsage: "allow-request will allow the curl request to continue even if the jwt is not present.",
|
||||||
Flags: []cli.Flag{
|
SkipFlagParsing: true,
|
||||||
&cli.BoolFlag{
|
|
||||||
Name: "allow-request",
|
|
||||||
Aliases: []string{"ar"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "token",
|
Name: "token",
|
||||||
|
@ -86,10 +82,10 @@ func login(c *cli.Context) error {
|
||||||
args := c.Args()
|
args := c.Args()
|
||||||
appURL, err := url.Parse(args.First())
|
appURL, err := url.Parse(args.First())
|
||||||
if args.Len() < 1 || err != nil {
|
if args.Len() < 1 || err != nil {
|
||||||
logger.Errorf("Please provide the URL of the Access application\n")
|
logger.Errorf("Please provide the url of the Access application\n")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := fetchToken(c, appURL); err != nil {
|
if _, err := fetchToken(c, appURL); err != nil {
|
||||||
logger.Errorf("Failed to fetch token: %s\n", err)
|
logger.Errorf("Failed to fetch token: %s\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -107,36 +103,26 @@ func curl(c *cli.Context) error {
|
||||||
return errors.New("incorrect args")
|
return errors.New("incorrect args")
|
||||||
}
|
}
|
||||||
|
|
||||||
var appURL *url.URL
|
cmdArgs, appURL, allowRequest, err := buildCurlCmdArgs(args.Slice())
|
||||||
cmdArgs := args.Slice()
|
if err != nil {
|
||||||
for _, arg := range cmdArgs {
|
return err
|
||||||
u, err := url.ParseRequestURI(arg)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
appURL = u
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := getTokenIfExists(appURL)
|
token, err := getTokenIfExists(appURL)
|
||||||
if err != nil || token == "" {
|
if err != nil || token == "" {
|
||||||
if !c.Bool("nojwt") {
|
if allowRequest {
|
||||||
if err := fetchToken(c, appURL); err != nil {
|
|
||||||
logger.Errorf("Failed to refresh token: %s\n", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
token, err = getTokenIfExists(appURL)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("Failed pull existing token: %s\n", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
logger.Warn("You don't have an Access token set. Please run access token <access application> to fetch one.")
|
logger.Warn("You don't have an Access token set. Please run access token <access application> to fetch one.")
|
||||||
|
return shell.Run("curl", cmdArgs...)
|
||||||
|
}
|
||||||
|
token, err = fetchToken(c, appURL)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to refresh token: ", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdArgs = append(cmdArgs, "-H")
|
cmdArgs = append(cmdArgs, "-H")
|
||||||
cmdArgs = append(cmdArgs, fmt.Sprintf("cf-jwt-access-assertion=%s", token))
|
cmdArgs = append(cmdArgs, fmt.Sprintf("cf-access-token: %s", token))
|
||||||
return shell.Run("curl", cmdArgs...)
|
return shell.Run("curl", cmdArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +131,7 @@ func token(c *cli.Context) error {
|
||||||
raven.SetDSN(sentryDSN)
|
raven.SetDSN(sentryDSN)
|
||||||
appURL, err := url.Parse(c.String("app"))
|
appURL, err := url.Parse(c.String("app"))
|
||||||
if err != nil || c.NumFlags() < 1 {
|
if err != nil || c.NumFlags() < 1 {
|
||||||
fmt.Fprintln(os.Stderr, "Please provide access application.")
|
fmt.Fprintln(os.Stderr, "Please provide a url.")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
token, err := getTokenIfExists(appURL)
|
token, err := getTokenIfExists(appURL)
|
||||||
|
@ -160,3 +146,53 @@ func token(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// processURL will preprocess the string (parse to a url, convert to punycode, etc).
|
||||||
|
func processURL(s string) (*url.URL, error) {
|
||||||
|
u, err := url.ParseRequestURI(s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
host, err := idna.ToASCII(u.Hostname())
|
||||||
|
if err != nil { // we fail to convert to punycode, just return the url we parsed.
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
if u.Port() != "" {
|
||||||
|
u.Host = fmt.Sprintf("%s:%s", host, u.Port())
|
||||||
|
} else {
|
||||||
|
u.Host = host
|
||||||
|
}
|
||||||
|
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildCurlCmdArgs will build the curl cmd args
|
||||||
|
func buildCurlCmdArgs(cmdArgs []string) ([]string, *url.URL, bool, error) {
|
||||||
|
allowRequest, iAllowRequest := false, 0
|
||||||
|
var appURL *url.URL
|
||||||
|
for i, arg := range cmdArgs {
|
||||||
|
if arg == "-allow-request" || arg == "-ar" {
|
||||||
|
iAllowRequest = i
|
||||||
|
allowRequest = true
|
||||||
|
}
|
||||||
|
|
||||||
|
u, err := processURL(arg)
|
||||||
|
if err == nil {
|
||||||
|
appURL = u
|
||||||
|
cmdArgs[i] = appURL.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if appURL == nil {
|
||||||
|
logger.Error("Please provide a valid URL.")
|
||||||
|
return cmdArgs, appURL, allowRequest, errors.New("invalid url")
|
||||||
|
}
|
||||||
|
|
||||||
|
if allowRequest {
|
||||||
|
// remove from cmdArgs
|
||||||
|
cmdArgs[iAllowRequest] = cmdArgs[len(cmdArgs)-1]
|
||||||
|
cmdArgs = cmdArgs[:len(cmdArgs)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmdArgs, appURL, allowRequest, nil
|
||||||
|
}
|
||||||
|
|
|
@ -21,24 +21,28 @@ import (
|
||||||
var logger = log.CreateLogger()
|
var logger = log.CreateLogger()
|
||||||
|
|
||||||
// fetchToken will either load a stored token or generate a new one
|
// fetchToken will either load a stored token or generate a new one
|
||||||
func fetchToken(c *cli.Context, appURL *url.URL) error {
|
func fetchToken(c *cli.Context, appURL *url.URL) (string, error) {
|
||||||
if token, err := getTokenIfExists(appURL); token != "" && err == nil {
|
if token, err := getTokenIfExists(appURL); token != "" && err == nil {
|
||||||
fmt.Fprintf(os.Stdout, "You have an existing token:\n\n%s\n\n", token)
|
fmt.Fprintf(os.Stdout, "You have an existing token:\n\n%s\n\n", token)
|
||||||
return nil
|
return token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
path, err := generateFilePathForTokenURL(appURL)
|
path, err := generateFilePathForTokenURL(appURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := transfer.Run(c, appURL, "token", path, true)
|
// this weird parameter is the resource name (token) and the key/value
|
||||||
|
// we want to send to the transfer service. the key is token and the value
|
||||||
|
// is blank (basically just the id generated in the transfer service)
|
||||||
|
const resourceName, key, value = "token", "token", ""
|
||||||
|
token, err := transfer.Run(c, appURL, resourceName, key, value, path, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stdout, "Successfully fetched your token:\n\n%s\n\n", string(token))
|
fmt.Fprintf(os.Stdout, "Successfully fetched your token:\n\n%s\n\n", string(token))
|
||||||
return nil
|
return string(token), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getTokenIfExists will return the token from local storage if it exists
|
// getTokenIfExists will return the token from local storage if it exists
|
||||||
|
|
|
@ -47,7 +47,7 @@ type Encrypter struct {
|
||||||
// New returns a new encrypter with initialized keypair
|
// New returns a new encrypter with initialized keypair
|
||||||
func New(privateKey, publicKey string) (*Encrypter, error) {
|
func New(privateKey, publicKey string) (*Encrypter, error) {
|
||||||
e := &Encrypter{}
|
e := &Encrypter{}
|
||||||
key, pubKey, err := e.fetchOrGenerateKeys(privateKey, publicKey)
|
pubKey, key, err := e.fetchOrGenerateKeys(privateKey, publicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ func New(privateKey, publicKey string) (*Encrypter, error) {
|
||||||
|
|
||||||
// PublicKey returns a base64 encoded public key. Useful for transport (like in HTTP requests)
|
// PublicKey returns a base64 encoded public key. Useful for transport (like in HTTP requests)
|
||||||
func (e *Encrypter) PublicKey() string {
|
func (e *Encrypter) PublicKey() string {
|
||||||
return base64.StdEncoding.EncodeToString(e.publicKey[:])
|
return base64.URLEncoding.EncodeToString(e.publicKey[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt data that was encrypted using our publicKey. It will use our privateKey and the sender's publicKey to decrypt
|
// Decrypt data that was encrypted using our publicKey. It will use our privateKey and the sender's publicKey to decrypt
|
||||||
|
@ -122,7 +122,7 @@ func (e *Encrypter) fetchOrGenerateKeys(privateKey, publicKey string) (*[32]byte
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return key, pub, nil
|
return pub, key, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// writeKey will write a key to disk in DER format (it's a standard pem key)
|
// writeKey will write a key to disk in DER format (it's a standard pem key)
|
||||||
|
@ -166,7 +166,7 @@ func (e *Encrypter) fetchKey(filename string) (*[32]byte, error) {
|
||||||
|
|
||||||
// decodePublicKey will base64 decode the provided key to the box representation
|
// decodePublicKey will base64 decode the provided key to the box representation
|
||||||
func (e *Encrypter) decodePublicKey(key string) (*[32]byte, error) {
|
func (e *Encrypter) decodePublicKey(key string) (*[32]byte, error) {
|
||||||
pub, err := base64.StdEncoding.DecodeString(key)
|
pub, err := base64.URLEncoding.DecodeString(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,11 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/crypto/ssh/terminal"
|
||||||
|
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/access"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/access"
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/config"
|
||||||
"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
|
"github.com/cloudflare/cloudflared/cmd/cloudflared/tunnel"
|
||||||
|
@ -84,6 +87,11 @@ func flags() []cli.Flag {
|
||||||
|
|
||||||
func action(version string, shutdownC, graceShutdownC chan struct{}) cli.ActionFunc {
|
func action(version string, shutdownC, graceShutdownC chan struct{}) cli.ActionFunc {
|
||||||
return func(c *cli.Context) (err error) {
|
return func(c *cli.Context) (err error) {
|
||||||
|
if isRunningFromTerminal() {
|
||||||
|
logger.Error("Use of cloudflared without commands is deprecated.")
|
||||||
|
cli.ShowAppHelp(c)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
tags := make(map[string]string)
|
tags := make(map[string]string)
|
||||||
tags["hostname"] = c.String("hostname")
|
tags["hostname"] = c.String("hostname")
|
||||||
raven.SetTagsContext(tags)
|
raven.SetTagsContext(tags)
|
||||||
|
@ -125,3 +133,7 @@ func userHomeDir() (string, error) {
|
||||||
}
|
}
|
||||||
return homeDir, nil
|
return homeDir, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isRunningFromTerminal() bool {
|
||||||
|
return terminal.IsTerminal(int(os.Stdout.Fd()))
|
||||||
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
baseStoreURL = "https://login.cloudflarewarp.com"
|
baseStoreURL = "https://login.cloudflarewarp.com/"
|
||||||
clientTimeout = time.Second * 60
|
clientTimeout = time.Second * 60
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,12 +32,12 @@ var logger = log.CreateLogger()
|
||||||
// The "dance" we refer to is building a HTTP request, opening that in a browser waiting for
|
// The "dance" we refer to is building a HTTP request, opening that in a browser waiting for
|
||||||
// the user to complete an action, while it long polls in the background waiting for an
|
// the user to complete an action, while it long polls in the background waiting for an
|
||||||
// action to be completed to download the resource.
|
// action to be completed to download the resource.
|
||||||
func Run(c *cli.Context, transferURL *url.URL, resourceName, path string, shouldEncrypt bool) ([]byte, error) {
|
func Run(c *cli.Context, transferURL *url.URL, resourceName, key, value, path string, shouldEncrypt bool) ([]byte, error) {
|
||||||
encrypterClient, err := encrypter.New("cloudflared_priv.pem", "cloudflared_pub.pem")
|
encrypterClient, err := encrypter.New("cloudflared_priv.pem", "cloudflared_pub.pem")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
requestURL, err := buildRequestURL(transferURL, resourceName, encrypterClient.PublicKey(), true)
|
requestURL, err := buildRequestURL(transferURL, key, value+encrypterClient.PublicKey(), shouldEncrypt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -58,19 +58,23 @@ func Run(c *cli.Context, transferURL *url.URL, resourceName, path string, should
|
||||||
var resourceData []byte
|
var resourceData []byte
|
||||||
|
|
||||||
if shouldEncrypt {
|
if shouldEncrypt {
|
||||||
buf, key, err := transferRequest(filepath.Join(baseURL, "transfer", encrypterClient.PublicKey()))
|
buf, key, err := transferRequest(baseURL + filepath.Join("transfer", encrypterClient.PublicKey()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
decrypted, err := encrypterClient.Decrypt(buf, key)
|
decodedBuf, err := base64.StdEncoding.DecodeString(string(buf))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
decrypted, err := encrypterClient.Decrypt(decodedBuf, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceData = decrypted
|
resourceData = decrypted
|
||||||
} else {
|
} else {
|
||||||
buf, _, err := transferRequest(filepath.Join(baseURL, encrypterClient.PublicKey()))
|
buf, _, err := transferRequest(baseURL + filepath.Join(encrypterClient.PublicKey()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -84,7 +88,7 @@ func Run(c *cli.Context, transferURL *url.URL, resourceName, path string, should
|
||||||
return resourceData, nil
|
return resourceData, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildRequestURL creates a request suitable for a resource transfer.
|
// BuildRequestURL creates a request suitable for a resource transfer.
|
||||||
// it will return a constructed url based off the base url and query key/value provided.
|
// it will return a constructed url based off the base url and query key/value provided.
|
||||||
// follow will follow redirects.
|
// follow will follow redirects.
|
||||||
func buildRequestURL(baseURL *url.URL, key, value string, follow bool) (string, error) {
|
func buildRequestURL(baseURL *url.URL, key, value string, follow bool) (string, error) {
|
||||||
|
@ -106,8 +110,9 @@ func buildRequestURL(baseURL *url.URL, key, value string, follow bool) (string,
|
||||||
// transferRequest downloads the requested resource from the request URL
|
// transferRequest downloads the requested resource from the request URL
|
||||||
func transferRequest(requestURL string) ([]byte, string, error) {
|
func transferRequest(requestURL string) ([]byte, string, error) {
|
||||||
client := &http.Client{Timeout: clientTimeout}
|
client := &http.Client{Timeout: clientTimeout}
|
||||||
|
const pollAttempts = 10
|
||||||
// we do "long polling" on the endpoint to get the resource.
|
// we do "long polling" on the endpoint to get the resource.
|
||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < pollAttempts; i++ {
|
||||||
buf, key, err := poll(client, requestURL)
|
buf, key, err := poll(client, requestURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
|
@ -143,12 +148,7 @@ func poll(client *http.Client, requestURL string) ([]byte, string, error) {
|
||||||
if _, err := io.Copy(buf, resp.Body); err != nil {
|
if _, err := io.Copy(buf, resp.Body); err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
return buf.Bytes(), resp.Header.Get("service-public-key"), nil
|
||||||
decodedBuf, err := base64.StdEncoding.DecodeString(string(buf.Bytes()))
|
|
||||||
if err != nil {
|
|
||||||
return nil, "", err
|
|
||||||
}
|
|
||||||
return decodedBuf, resp.Header.Get("service-public-key"), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// putSuccess tells the server we successfully downloaded the resource
|
// putSuccess tells the server we successfully downloaded the resource
|
||||||
|
|
|
@ -98,7 +98,7 @@ func Commands() []*cli.Command {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ArgsUsage: " ", // can't be the empty string or we get the default output
|
ArgsUsage: " ", // can't be the empty string or we get the default output
|
||||||
Hidden: true,
|
Hidden: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "db",
|
Name: "db",
|
||||||
|
|
|
@ -13,12 +13,15 @@ import (
|
||||||
cli "gopkg.in/urfave/cli.v2"
|
cli "gopkg.in/urfave/cli.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const baseLoginURL = "https://dash.cloudflare.com/argotunnel"
|
const (
|
||||||
|
baseLoginURL = "https://dash.cloudflare.com/argotunnel"
|
||||||
|
callbackStoreURL = "https://login.cloudflarewarp.com/"
|
||||||
|
)
|
||||||
|
|
||||||
func login(c *cli.Context) error {
|
func login(c *cli.Context) error {
|
||||||
path, ok, err := checkForExistingCert()
|
path, ok, err := checkForExistingCert()
|
||||||
if ok {
|
if ok {
|
||||||
fmt.Fprintf(os.Stdout, "You have an existing certificate at %s which login would overwrite.\nIf this is intentional, please move or delete that file then run this command again.", path)
|
fmt.Fprintf(os.Stdout, "You have an existing certificate at %s which login would overwrite.\nIf this is intentional, please move or delete that file then run this command again.\n", path)
|
||||||
return nil
|
return nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -30,9 +33,9 @@ func login(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = transfer.Run(c, loginURL, "cert", path, false)
|
_, err = transfer.Run(c, loginURL, "cert", "callback", callbackStoreURL, path, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Failed to write the certificate due to the following error:\n%v\n\nYour browser will download the certificate instead. You will have to manually\ncopy it to the following path:\n\n%s", err, path)
|
fmt.Fprintf(os.Stderr, "Failed to write the certificate due to the following error:\n%v\n\nYour browser will download the certificate instead. You will have to manually\ncopy it to the following path:\n\n%s\n", err, path)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue