diff --git a/fortios/auth/auth.go b/fortios/auth/auth.go index 429a1a35..474676a8 100644 --- a/fortios/auth/auth.go +++ b/fortios/auth/auth.go @@ -20,10 +20,14 @@ type Auth struct { CaCert string ClientCert string ClientKey string + + PassAuth string + Username string + Passwd string } // NewAuth inits Auth object with the given metadata -func NewAuth(hostname, token, cabundle, cabundlecontent, peerauth, cacert, clientcert, clientkey, vdom, httpproxy string) *Auth { +func NewAuth(hostname, token, cabundle, cabundlecontent, peerauth, cacert, clientcert, clientkey, vdom, httpproxy string, passauth string, username string, passwd string) *Auth { return &Auth{ Hostname: hostname, Token: token, @@ -36,6 +40,10 @@ func NewAuth(hostname, token, cabundle, cabundlecontent, peerauth, cacert, clien CaCert: cacert, ClientCert: clientcert, ClientKey: clientkey, + + PassAuth: passauth, + Username: username, + Passwd: passwd, } } @@ -44,7 +52,7 @@ func NewAuth(hostname, token, cabundle, cabundlecontent, peerauth, cacert, clien func (m *Auth) GetEnvToken() (string, error) { token := os.Getenv("FORTIOS_ACCESS_TOKEN") - if token == "" { + if token == "" && m.PassAuth != "enable" && os.Getenv("FORTIOS_PASSAUTH") != "enable" { return token, fmt.Errorf("GetEnvToken error") } @@ -166,3 +174,44 @@ func (m *Auth) GetEnvHTTPProxy() (string, error) { return c, nil } +// GetEnvPassAuth gets the legacy PassAuth setting from OS environment +// It returns the PassAuth value +func (m *Auth) GetEnvPassAuth() (string, error) { + c := os.Getenv("FORTIOS_PASSAUTH") + + if c == "" { + return c, nil + } + + m.PassAuth = c + + return c, nil +} + +// GetEnvUserName gets the legacy username from OS environment +// It returns the legacy auth username +func (m *Auth) GetEnvUsername() (string, error) { + c := os.Getenv("FORTIOS_USERNAME") + + if c == "" { + return c, nil + } + + m.Username = c + + return c, nil +} + +// GetEnvUserName gets the legacy password from OS environment +// It returns the legacy auth password +func (m *Auth) GetEnvPasswd() (string, error) { + c := os.Getenv("FORTIOS_PASSWORD") + + if c == "" { + return c, nil + } + + m.Passwd = c + + return c, nil +} diff --git a/fortios/request/request.go b/fortios/request/request.go index b21074fa..3ec0655d 100644 --- a/fortios/request/request.go +++ b/fortios/request/request.go @@ -189,8 +189,10 @@ func buildURLWithoutVdom(r *Request) string { u += r.Path u += "?" - u += "access_token=" - u += r.Config.Auth.Token + if r.Config.Auth.PassAuth != "enable" { + u += "access_token=" + u += r.Config.Auth.Token + } return u } @@ -207,8 +209,10 @@ func buildURL(r *Request) string { u += "&" } - u += "access_token=" - u += r.Config.Auth.Token + if r.Config.Auth.PassAuth != "enable" { + u += "access_token=" + u += r.Config.Auth.Token + } return u } diff --git a/fortios/sdkcore/forticlient.go b/fortios/sdkcore/forticlient.go index 1eb47f65..7632c7a4 100644 --- a/fortios/sdkcore/forticlient.go +++ b/fortios/sdkcore/forticlient.go @@ -3,9 +3,11 @@ package forticlient import ( "bytes" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" + "net/http/cookiejar" "net/url" "strings" "time" @@ -60,6 +62,13 @@ func NewClient(auth *auth.Auth, client *http.Client) (*FortiSDKClient, error) { c.Config.HTTPCon = client c.Config.FwTarget = auth.Hostname + if auth.PassAuth == "enable" { + err := c.LoginWithPasswd() + if err != nil { + return nil, fmt.Errorf("%s", err) + } + } + vsave := client.Timeout client.Timeout = time.Second * 30 v, err := c.GetDeviceVersion() @@ -125,6 +134,70 @@ func (c *FortiSDKClient) GetDeviceVersion() (version string, err error) { return "", err } +func (c *FortiSDKClient) LoginWithPasswd() error { + jar, err := cookiejar.New(nil) + if err != nil { + return fmt.Errorf("Error creating passwd cookie jar: %w", err) + } + c.Config.HTTPCon.Jar = jar + + params := url.Values{} + params.Add("username", c.Config.Auth.Username) + params.Add("secretkey", c.Config.Auth.Passwd) + params.Add("ajax", `1`) + body := strings.NewReader(params.Encode()) + + req, err := http.NewRequest("POST", "https://"+c.Config.FwTarget+"/logincheck", body) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + resp, err := c.Config.HTTPCon.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + bodyText, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + responsebody := string(bodyText) + + // config system global + // set post-login-banner enable + // end + if strings.HasPrefix(responsebody[0:1], "1") && strings.Contains(responsebody, "logindisclaimer") { + params := url.Values{} + params.Add("confirm", `1`) + body := strings.NewReader(params.Encode()) + + req, err := http.NewRequest("POST", "https://"+c.Config.FwTarget+"/logindisclaimer", body) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + resp, err := c.Config.HTTPCon.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + bodyText, err := ioutil.ReadAll(resp.Body) + if err != nil { + return err + } + responsebody := string(bodyText) + + if !strings.Contains(responsebody, "document.location") { + return errors.New("Unable to accept Login Disclaimer. Please check") + } + + } else if !strings.HasPrefix(responsebody[0:1], "1") { + return errors.New("Wrong password credentials. Please check") + } + + return nil +} + func fortiAPIHttpStatus404Checking(result map[string]interface{}) (b404 bool) { b404 = false