Skip to content

Commit 3a41053

Browse files
fix: login (#2019)
Signed-off-by: Peter Matseykanets <peter.matseykanets@suse.com> Co-authored-by: Peter Matseykanets <peter.matseykanets@suse.com>
1 parent 8ca2e99 commit 3a41053

2 files changed

Lines changed: 93 additions & 26 deletions

File tree

rancher2/util.go

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"net/url"
1616
"reflect"
1717
"sort"
18+
"strconv"
1819
"strings"
1920
"time"
2021

@@ -139,58 +140,63 @@ func NewListOpts(filters map[string]interface{}) *types.ListOpts {
139140
}
140141

141142
func DoUserLogin(url, user, pass, ttl, desc, cacert string, insecure bool) (string, string, error) {
142-
loginURL := url + "/v1-public/login"
143-
v3loginURL := url + "/v3-public/localProviders/local?action=login"
143+
TTL, err := strconv.ParseInt(ttl, 10, 64)
144+
if err != nil || TTL < 0 {
145+
return "", "", fmt.Errorf("Invalid ttl value: %s", ttl)
146+
}
144147

145-
loginData, err := json.Marshal(map[string]string{
148+
payload, err := json.Marshal(map[string]any{
146149
"type": "localProvider",
147150
"username": user,
148151
"password": pass,
149-
"ttl": ttl,
152+
"ttl": TTL,
150153
"description": desc,
151154
})
152155
if err != nil {
153-
return "", "", err
156+
return "", "", fmt.Errorf("Marshalling login data: %v", err)
154157
}
155158

159+
loginURL := url + "/v1-public/login"
160+
v3loginURL := url + "/v3-public/localProviders/local?action=login"
161+
156162
loginHead := map[string]string{
157163
"Accept": "application/json",
158164
"Content-Type": "application/json",
159165
}
160166

167+
errPrefix := "Doing user login"
168+
161169
// Login with user and pass
162-
respBody, resp, err := DoPost(loginURL, string(loginData), cacert, insecure, loginHead)
170+
respBody, resp, err := DoPost(loginURL, string(payload), cacert, insecure, loginHead)
163171
if err != nil {
164-
return "", "", err
172+
return "", "", fmt.Errorf("%s: %v", errPrefix, err)
165173
}
166174

167175
if resp.StatusCode == http.StatusNotFound {
168176
// /v1-public/login endpoint is not available
169177
// try to fall back to /v3-public endpoint.
170-
respBody, _, err = DoPost(v3loginURL, string(loginData), cacert, insecure, loginHead)
178+
respBody, _, err = DoPost(v3loginURL, string(payload), cacert, insecure, loginHead)
171179
if err != nil {
172-
return "", "", err
180+
return "", "", fmt.Errorf("%s: %v", errPrefix, err)
173181
}
174182
}
175183

176-
token := ""
177-
errMsg := "Doing user login"
178-
184+
var token string
179185
if respBody["token"] != nil {
180186
token, _ = respBody["token"].(string)
181187
}
182188

183189
if token == "" {
184190
if respBody["code"] != nil {
185191
code, _ := respBody["code"].(string)
186-
errMsg += ": " + code
192+
errPrefix += ": " + code
187193
}
188-
return "", "", errors.New(errMsg)
194+
return "", "", errors.New(errPrefix)
189195
}
190196

191197
id, _, ok := strings.Cut(token, ":")
192198
if !ok {
193-
return "", "", errors.New(errMsg + ": invalid token format")
199+
return "", "", errors.New(errPrefix + ": invalid token format")
194200
}
195201
id = strings.TrimPrefix(id, "ext/")
196202

rancher2/util_test.go

Lines changed: 72 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ import (
1010
"github.com/stretchr/testify/require"
1111
)
1212

13+
type loginInput struct {
14+
Type string `json:"type"`
15+
Username string `json:"username"`
16+
Password string `json:"password"`
17+
TTL int64 `json:"ttl"`
18+
Description string `json:"description"`
19+
}
20+
1321
func TestDoUserLogin(t *testing.T) {
1422
t.Run("success", func(t *testing.T) {
1523
tokenID := "token-xqmfl"
@@ -20,12 +28,14 @@ func TestDoUserLogin(t *testing.T) {
2028
assert.Equal(t, "/v1-public/login", r.URL.Path)
2129
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
2230

23-
var reqBody map[string]string
31+
var reqBody loginInput
2432
err := json.NewDecoder(r.Body).Decode(&reqBody)
2533
require.NoError(t, err)
26-
assert.Equal(t, "localProvider", reqBody["type"])
27-
assert.Equal(t, "admin", reqBody["username"])
28-
assert.Equal(t, "secret", reqBody["password"])
34+
assert.Equal(t, "localProvider", reqBody.Type)
35+
assert.Equal(t, bootstrapDefaultUser, reqBody.Username)
36+
assert.Equal(t, bootstrapDefaultPassword, reqBody.Password)
37+
assert.Equal(t, int64(60000), reqBody.TTL)
38+
assert.Equal(t, bootstrapDefaultSessionDesc, reqBody.Description)
2939

3040
w.Header().Set("Content-Type", "application/json")
3141
_ = json.NewEncoder(w).Encode(map[string]any{
@@ -34,7 +44,7 @@ func TestDoUserLogin(t *testing.T) {
3444
}))
3545
defer srv.Close()
3646

37-
id, token, err := DoUserLogin(srv.URL, "admin", "secret", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
47+
id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
3848
require.NoError(t, err)
3949
assert.Equal(t, tokenID, id)
4050
assert.Equal(t, tokenValue, token)
@@ -52,7 +62,7 @@ func TestDoUserLogin(t *testing.T) {
5262
}))
5363
defer srv.Close()
5464

55-
id, token, err := DoUserLogin(srv.URL, "admin", "secret", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
65+
id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
5666
require.NoError(t, err)
5767
assert.Equal(t, "saml-user-abc123", id, "ext/ prefix should be stripped from ID")
5868
assert.Equal(t, tokenValue, token)
@@ -68,7 +78,7 @@ func TestDoUserLogin(t *testing.T) {
6878
}))
6979
defer srv.Close()
7080

71-
_, _, err := DoUserLogin(srv.URL, "admin", "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
81+
_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
7282
require.Error(t, err)
7383
assert.Contains(t, err.Error(), "Unauthorized")
7484
})
@@ -82,7 +92,7 @@ func TestDoUserLogin(t *testing.T) {
8292
}))
8393
defer srv.Close()
8494

85-
_, _, err := DoUserLogin(srv.URL, "admin", "secret", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
95+
_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
8696
require.Error(t, err)
8797
assert.Contains(t, err.Error(), "invalid token format")
8898
})
@@ -99,7 +109,7 @@ func TestDoUserLogin(t *testing.T) {
99109
}))
100110
defer srv.Close()
101111

102-
_, _, err := DoUserLogin(srv.URL, "admin", "secret", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
112+
_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
103113
require.Error(t, err)
104114
})
105115

@@ -124,6 +134,12 @@ func TestDoUserLogin(t *testing.T) {
124134

125135
if r.URL.Path == "/v3-public/localProviders/local" {
126136
assert.Equal(t, "login", r.URL.Query().Get("action"))
137+
138+
var reqBody loginInput
139+
err := json.NewDecoder(r.Body).Decode(&reqBody)
140+
require.NoError(t, err)
141+
assert.Equal(t, int64(60000), reqBody.TTL)
142+
127143
_ = json.NewEncoder(w).Encode(map[string]any{
128144
"token": tokenValue,
129145
})
@@ -134,7 +150,7 @@ func TestDoUserLogin(t *testing.T) {
134150
}))
135151
defer srv.Close()
136152

137-
id, token, err := DoUserLogin(srv.URL, "admin", "secret", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
153+
id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
138154
require.NoError(t, err)
139155
assert.Equal(t, tokenID, id)
140156
assert.Equal(t, tokenValue, token)
@@ -162,8 +178,53 @@ func TestDoUserLogin(t *testing.T) {
162178
}))
163179
defer srv.Close()
164180

165-
_, _, err := DoUserLogin(srv.URL, "admin", "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
181+
_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, "wrongpass", bootstrapDefaultTTL, bootstrapDefaultSessionDesc, "", true)
166182
require.Error(t, err)
167183
assert.Contains(t, err.Error(), "Unauthorized")
168184
})
185+
186+
t.Run("invalid ttl value - not a number", func(t *testing.T) {
187+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
188+
t.Error("should not make request with invalid TTL")
189+
}))
190+
defer srv.Close()
191+
192+
_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, "not-a-number", bootstrapDefaultSessionDesc, "", true)
193+
require.Error(t, err)
194+
assert.Contains(t, err.Error(), "Invalid ttl value")
195+
})
196+
197+
t.Run("invalid ttl value - negative number", func(t *testing.T) {
198+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
199+
t.Error("should not make request with negative TTL")
200+
}))
201+
defer srv.Close()
202+
203+
_, _, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, "-1000", bootstrapDefaultSessionDesc, "", true)
204+
require.Error(t, err)
205+
assert.Contains(t, err.Error(), "Invalid ttl value")
206+
})
207+
208+
t.Run("valid ttl value - zero", func(t *testing.T) {
209+
tokenID := "token-zero-ttl"
210+
tokenValue := tokenID + ":secrettoken"
211+
212+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
213+
var reqBody loginInput
214+
err := json.NewDecoder(r.Body).Decode(&reqBody)
215+
require.NoError(t, err)
216+
assert.Equal(t, int64(0), reqBody.TTL)
217+
218+
w.Header().Set("Content-Type", "application/json")
219+
_ = json.NewEncoder(w).Encode(map[string]any{
220+
"token": tokenValue,
221+
})
222+
}))
223+
defer srv.Close()
224+
225+
id, token, err := DoUserLogin(srv.URL, bootstrapDefaultUser, bootstrapDefaultPassword, "0", bootstrapDefaultSessionDesc, "", true)
226+
require.NoError(t, err)
227+
assert.Equal(t, tokenID, id)
228+
assert.Equal(t, tokenValue, token)
229+
})
169230
}

0 commit comments

Comments
 (0)