Skip to content

Commit

Permalink
login/logout commands
Browse files Browse the repository at this point in the history
Signed-off-by: Stefan Prodan <stefan@weave.works>
  • Loading branch information
stefanprodan authored and alexellis committed Nov 3, 2017
1 parent b606487 commit 5cd3ea2
Show file tree
Hide file tree
Showing 16 changed files with 953 additions and 18 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ obj
.vscode

*.swp

.idea
.DS_Store
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ The main commands supported by the CLI are:
* `faas-cli deploy` - deploys the functions into a local or remote OpenFaaS gateway
* `faas-cli remove` - removes the functions from a local or remote OpenFaaS gateway
* `faas-cli invoke` - invokes the functions and reads from STDIN for the body of the request
* `faas-cli login` - stores basic auth credentials for OpenFaaS gateway (supports multiple gateways)
* `faas-cli logout` - removes basic auth credentials fora given gateway

Help for all of the commands supported by the CLI can be found by running:

Expand All @@ -51,7 +53,7 @@ You can chose between using a [programming language template](https://github.com

**Templates**

Command: `faas-cli new FUNCTION_NAME --lang python/node/go//ruby/Dockerfile/etc`
Command: `faas-cli new FUNCTION_NAME --lang python/node/go/ruby/Dockerfile/etc`

In your YAML you can also specify `lang: node/python/go/csharp/ruby`

Expand Down
141 changes: 141 additions & 0 deletions commands/login.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Copyright (c) OpenFaaS Project 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"time"

"github.com/openfaas/faas-cli/config"
"github.com/spf13/cobra"
)

var (
username string
password string
passwordStdin bool
)

func init() {
loginCmd.Flags().StringVar(&gateway, "gateway", defaultGateway, "Gateway URI")
loginCmd.Flags().StringVarP(&username, "username", "u", "", "Gateway username")
loginCmd.Flags().StringVarP(&password, "password", "p", "", "Gateway password")
loginCmd.Flags().BoolVar(&passwordStdin, "password-stdin", false, "Reads the gateway password from stdin")

faasCmd.AddCommand(loginCmd)
}

var loginCmd = &cobra.Command{
Use: `login [--username USERNAME] [--password PASSWORD] [--gateway GATEWAY_URL]`,
Short: "Log in to OpenFaaS gateway",
Long: "Log in to OpenFaaS gateway.\nIf no gateway is specified, the default local one will be used.",
Example: ` faas-cli login -u user -p password --gateway http://localhost:8080
cat ~/faas_pass.txt | faas-cli login -u user --password-stdin --gateway https://openfaas.mydomain.com`,
RunE: runLogin,
}

func runLogin(cmd *cobra.Command, args []string) error {

if len(username) == 0 {
return errors.New("must provide --username or -u")
}

if len(password) > 0 {
fmt.Println("WARNING! Using --password is insecure, consider using: cat ~/faas_pass.txt | faas-cli login -u user --password-stdin")
if passwordStdin {
return errors.New("--password and --password-stdin are mutually exclusive")
}

if len(username) == 0 {
return errors.New("must provide --username with --password")
}
}

if passwordStdin {
if len(username) == 0 {
return errors.New("must provide --username with --password-stdin")
}

passwordStdin, err := ioutil.ReadAll(os.Stdin)
if err != nil {
return err
}

password = strings.TrimSpace(string(passwordStdin))
}

password = strings.TrimSpace(password)
if len(password) == 0 {
return errors.New("must provide a non-empty password via --password or --password-stdin")
}

fmt.Println("Calling the OpenFaaS server to validate the credentials...")
gateway = strings.TrimRight(strings.TrimSpace(gateway), "/")
if err := validateLogin(gateway, username, password); err != nil {
return err
}

if err := config.UpdateAuthConfig(gateway, username, password); err != nil {
return err
}

user, _, err := config.LookupAuthConfig(gateway)
if err != nil {
return err
}
fmt.Println("credentials saved for", user, gateway)

return nil
}

func validateLogin(url string, user string, pass string) error {
// TODO: provide --insecure flag for this
tr := &http.Transport{
DisableKeepAlives: true,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{
Transport: tr,
Timeout: time.Duration(5 * time.Second),
}

// TODO: implement ping in the gateway API and call that
gatewayUrl := strings.TrimRight(url, "/")
req, _ := http.NewRequest("GET", gateway+"/system/functions", nil)
req.SetBasicAuth(user, pass)

res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s", gatewayUrl)
}

if res.Body != nil {
defer res.Body.Close()
}

if res.TLS == nil {
fmt.Println("WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.")
}

switch res.StatusCode {
case http.StatusOK:
return nil
case http.StatusUnauthorized:
return errors.New("unable to login, either username or password is incorrect")
default:
bytesOut, err := ioutil.ReadAll(res.Body)
if err == nil {
return fmt.Errorf("server returned unexpected status code: %d - %s", res.StatusCode, string(bytesOut))
}
}

return nil
}
42 changes: 42 additions & 0 deletions commands/logout.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) OpenFaaS Project 2017. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package commands

import (
"errors"
"fmt"
"strings"

"github.com/openfaas/faas-cli/config"
"github.com/spf13/cobra"
)

func init() {
logoutCmd.Flags().StringVar(&gateway, "gateway", defaultGateway, "Gateway URI")

faasCmd.AddCommand(logoutCmd)
}

var logoutCmd = &cobra.Command{
Use: `logout [--gateway GATEWAY_URL]`,
Short: "Log out from OpenFaaS gateway",
Long: "Log out from OpenFaaS gateway.\nIf no gateway is specified, the default local one will be used.",
Example: ` faas-cli logout --gateway https://openfaas.mydomain.com`,
RunE: runLogout,
}

func runLogout(cmd *cobra.Command, args []string) error {
if len(gateway) == 0 {
return errors.New("gateway cannot be an empty string")
}

gateway = strings.TrimRight(strings.TrimSpace(gateway), "/")
err := config.RemoveAuthConfig(gateway)
if err != nil {
return err
}
fmt.Println("credentials removed for", gateway)

return nil
}
Loading

0 comments on commit 5cd3ea2

Please sign in to comment.