Skip to content

Commit 5cd3ea2

Browse files
stefanprodanalexellis
authored andcommitted
login/logout commands
Signed-off-by: Stefan Prodan <[email protected]>
1 parent b606487 commit 5cd3ea2

File tree

16 files changed

+953
-18
lines changed

16 files changed

+953
-18
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@ obj
1616
.vscode
1717

1818
*.swp
19+
20+
.idea
21+
.DS_Store

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ The main commands supported by the CLI are:
4242
* `faas-cli deploy` - deploys the functions into a local or remote OpenFaaS gateway
4343
* `faas-cli remove` - removes the functions from a local or remote OpenFaaS gateway
4444
* `faas-cli invoke` - invokes the functions and reads from STDIN for the body of the request
45+
* `faas-cli login` - stores basic auth credentials for OpenFaaS gateway (supports multiple gateways)
46+
* `faas-cli logout` - removes basic auth credentials fora given gateway
4547

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

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

5254
**Templates**
5355

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

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

commands/login.go

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright (c) OpenFaaS Project 2017. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
package commands
5+
6+
import (
7+
"crypto/tls"
8+
"errors"
9+
"fmt"
10+
"io/ioutil"
11+
"net/http"
12+
"os"
13+
"strings"
14+
"time"
15+
16+
"github.com/openfaas/faas-cli/config"
17+
"github.com/spf13/cobra"
18+
)
19+
20+
var (
21+
username string
22+
password string
23+
passwordStdin bool
24+
)
25+
26+
func init() {
27+
loginCmd.Flags().StringVar(&gateway, "gateway", defaultGateway, "Gateway URI")
28+
loginCmd.Flags().StringVarP(&username, "username", "u", "", "Gateway username")
29+
loginCmd.Flags().StringVarP(&password, "password", "p", "", "Gateway password")
30+
loginCmd.Flags().BoolVar(&passwordStdin, "password-stdin", false, "Reads the gateway password from stdin")
31+
32+
faasCmd.AddCommand(loginCmd)
33+
}
34+
35+
var loginCmd = &cobra.Command{
36+
Use: `login [--username USERNAME] [--password PASSWORD] [--gateway GATEWAY_URL]`,
37+
Short: "Log in to OpenFaaS gateway",
38+
Long: "Log in to OpenFaaS gateway.\nIf no gateway is specified, the default local one will be used.",
39+
Example: ` faas-cli login -u user -p password --gateway http://localhost:8080
40+
cat ~/faas_pass.txt | faas-cli login -u user --password-stdin --gateway https://openfaas.mydomain.com`,
41+
RunE: runLogin,
42+
}
43+
44+
func runLogin(cmd *cobra.Command, args []string) error {
45+
46+
if len(username) == 0 {
47+
return errors.New("must provide --username or -u")
48+
}
49+
50+
if len(password) > 0 {
51+
fmt.Println("WARNING! Using --password is insecure, consider using: cat ~/faas_pass.txt | faas-cli login -u user --password-stdin")
52+
if passwordStdin {
53+
return errors.New("--password and --password-stdin are mutually exclusive")
54+
}
55+
56+
if len(username) == 0 {
57+
return errors.New("must provide --username with --password")
58+
}
59+
}
60+
61+
if passwordStdin {
62+
if len(username) == 0 {
63+
return errors.New("must provide --username with --password-stdin")
64+
}
65+
66+
passwordStdin, err := ioutil.ReadAll(os.Stdin)
67+
if err != nil {
68+
return err
69+
}
70+
71+
password = strings.TrimSpace(string(passwordStdin))
72+
}
73+
74+
password = strings.TrimSpace(password)
75+
if len(password) == 0 {
76+
return errors.New("must provide a non-empty password via --password or --password-stdin")
77+
}
78+
79+
fmt.Println("Calling the OpenFaaS server to validate the credentials...")
80+
gateway = strings.TrimRight(strings.TrimSpace(gateway), "/")
81+
if err := validateLogin(gateway, username, password); err != nil {
82+
return err
83+
}
84+
85+
if err := config.UpdateAuthConfig(gateway, username, password); err != nil {
86+
return err
87+
}
88+
89+
user, _, err := config.LookupAuthConfig(gateway)
90+
if err != nil {
91+
return err
92+
}
93+
fmt.Println("credentials saved for", user, gateway)
94+
95+
return nil
96+
}
97+
98+
func validateLogin(url string, user string, pass string) error {
99+
// TODO: provide --insecure flag for this
100+
tr := &http.Transport{
101+
DisableKeepAlives: true,
102+
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
103+
}
104+
client := &http.Client{
105+
Transport: tr,
106+
Timeout: time.Duration(5 * time.Second),
107+
}
108+
109+
// TODO: implement ping in the gateway API and call that
110+
gatewayUrl := strings.TrimRight(url, "/")
111+
req, _ := http.NewRequest("GET", gateway+"/system/functions", nil)
112+
req.SetBasicAuth(user, pass)
113+
114+
res, err := client.Do(req)
115+
if err != nil {
116+
fmt.Println(err)
117+
return fmt.Errorf("cannot connect to OpenFaaS on URL: %s", gatewayUrl)
118+
}
119+
120+
if res.Body != nil {
121+
defer res.Body.Close()
122+
}
123+
124+
if res.TLS == nil {
125+
fmt.Println("WARNING! Communication is not secure, please consider using HTTPS. Letsencrypt.org offers free SSL/TLS certificates.")
126+
}
127+
128+
switch res.StatusCode {
129+
case http.StatusOK:
130+
return nil
131+
case http.StatusUnauthorized:
132+
return errors.New("unable to login, either username or password is incorrect")
133+
default:
134+
bytesOut, err := ioutil.ReadAll(res.Body)
135+
if err == nil {
136+
return fmt.Errorf("server returned unexpected status code: %d - %s", res.StatusCode, string(bytesOut))
137+
}
138+
}
139+
140+
return nil
141+
}

commands/logout.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright (c) OpenFaaS Project 2017. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
package commands
5+
6+
import (
7+
"errors"
8+
"fmt"
9+
"strings"
10+
11+
"github.com/openfaas/faas-cli/config"
12+
"github.com/spf13/cobra"
13+
)
14+
15+
func init() {
16+
logoutCmd.Flags().StringVar(&gateway, "gateway", defaultGateway, "Gateway URI")
17+
18+
faasCmd.AddCommand(logoutCmd)
19+
}
20+
21+
var logoutCmd = &cobra.Command{
22+
Use: `logout [--gateway GATEWAY_URL]`,
23+
Short: "Log out from OpenFaaS gateway",
24+
Long: "Log out from OpenFaaS gateway.\nIf no gateway is specified, the default local one will be used.",
25+
Example: ` faas-cli logout --gateway https://openfaas.mydomain.com`,
26+
RunE: runLogout,
27+
}
28+
29+
func runLogout(cmd *cobra.Command, args []string) error {
30+
if len(gateway) == 0 {
31+
return errors.New("gateway cannot be an empty string")
32+
}
33+
34+
gateway = strings.TrimRight(strings.TrimSpace(gateway), "/")
35+
err := config.RemoveAuthConfig(gateway)
36+
if err != nil {
37+
return err
38+
}
39+
fmt.Println("credentials removed for", gateway)
40+
41+
return nil
42+
}

0 commit comments

Comments
 (0)