Skip to content

Commit 905cd1a

Browse files
committed
add apikey pkg test
1 parent 01f7a5e commit 905cd1a

File tree

1 file changed

+163
-0
lines changed

1 file changed

+163
-0
lines changed

coderd/apikey/apikey_test.go

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
package apikey_test
2+
3+
import (
4+
"crypto/sha256"
5+
"strings"
6+
"testing"
7+
"time"
8+
9+
"github.com/google/uuid"
10+
"github.com/stretchr/testify/require"
11+
12+
"github.com/coder/coder/cli/clibase"
13+
"github.com/coder/coder/coderd/apikey"
14+
"github.com/coder/coder/coderd/database"
15+
"github.com/coder/coder/codersdk"
16+
)
17+
18+
func TestGenerate(t *testing.T) {
19+
t.Parallel()
20+
21+
type testcase struct {
22+
name string
23+
params apikey.CreateParams
24+
fail bool
25+
}
26+
27+
cases := []testcase{
28+
{
29+
name: "OK",
30+
params: apikey.CreateParams{
31+
UserID: uuid.New(),
32+
LoginType: database.LoginTypeOIDC,
33+
DeploymentValues: &codersdk.DeploymentValues{},
34+
ExpiresAt: time.Now().Add(time.Hour),
35+
LifetimeSeconds: int64(time.Hour.Seconds()),
36+
TokenName: "hello",
37+
RemoteAddr: "1.2.3.4",
38+
Scope: database.APIKeyScopeApplicationConnect,
39+
},
40+
},
41+
{
42+
name: "InvalidScope",
43+
params: apikey.CreateParams{
44+
UserID: uuid.New(),
45+
LoginType: database.LoginTypeOIDC,
46+
DeploymentValues: &codersdk.DeploymentValues{},
47+
ExpiresAt: time.Now().Add(time.Hour),
48+
LifetimeSeconds: int64(time.Hour.Seconds()),
49+
TokenName: "hello",
50+
RemoteAddr: "1.2.3.4",
51+
Scope: database.APIKeyScope("test"),
52+
},
53+
fail: true,
54+
},
55+
{
56+
name: "DeploymentSessionDuration",
57+
params: apikey.CreateParams{
58+
UserID: uuid.New(),
59+
LoginType: database.LoginTypeOIDC,
60+
DeploymentValues: &codersdk.DeploymentValues{
61+
SessionDuration: clibase.Duration(time.Hour),
62+
},
63+
LifetimeSeconds: 0,
64+
ExpiresAt: time.Time{},
65+
TokenName: "hello",
66+
RemoteAddr: "1.2.3.4",
67+
Scope: database.APIKeyScopeApplicationConnect,
68+
},
69+
},
70+
{
71+
name: "DefaultIP",
72+
params: apikey.CreateParams{
73+
UserID: uuid.New(),
74+
LoginType: database.LoginTypeOIDC,
75+
DeploymentValues: &codersdk.DeploymentValues{},
76+
ExpiresAt: time.Now().Add(time.Hour),
77+
LifetimeSeconds: int64(time.Hour.Seconds()),
78+
TokenName: "hello",
79+
RemoteAddr: "",
80+
Scope: database.APIKeyScopeApplicationConnect,
81+
},
82+
},
83+
{
84+
name: "DefaultScope",
85+
params: apikey.CreateParams{
86+
UserID: uuid.New(),
87+
LoginType: database.LoginTypeOIDC,
88+
DeploymentValues: &codersdk.DeploymentValues{},
89+
ExpiresAt: time.Now().Add(time.Hour),
90+
LifetimeSeconds: int64(time.Hour.Seconds()),
91+
TokenName: "hello",
92+
RemoteAddr: "1.2.3.4",
93+
Scope: database.APIKeyScopeApplicationConnect,
94+
},
95+
},
96+
}
97+
98+
for _, tc := range cases {
99+
tc := tc
100+
t.Run(tc.name, func(t *testing.T) {
101+
t.Parallel()
102+
103+
keystr, key, err := apikey.Generate(tc.params)
104+
if tc.fail {
105+
require.Error(t, err)
106+
return
107+
}
108+
require.NoError(t, err)
109+
require.NotEmpty(t, keystr)
110+
require.NotEmpty(t, key.ID)
111+
require.NotEmpty(t, key.HashedSecret)
112+
113+
// Assert the string secret is formatted correctly
114+
keytokens := strings.Split(keystr, "-")
115+
require.Len(t, keytokens, 2)
116+
require.Equal(t, key.ID, keytokens[0])
117+
118+
// Assert that the hashed secret is correct.
119+
hashed := sha256.Sum256([]byte(keytokens[1]))
120+
require.ElementsMatch(t, hashed, key.HashedSecret[:])
121+
122+
require.Equal(t, tc.params.UserID, key.UserID)
123+
require.WithinDuration(t, database.Now(), key.CreatedAt, time.Second*5)
124+
require.WithinDuration(t, database.Now(), key.UpdatedAt, time.Second*5)
125+
126+
if tc.params.LifetimeSeconds > 0 {
127+
require.Equal(t, tc.params.LifetimeSeconds, key.LifetimeSeconds)
128+
} else if !tc.params.ExpiresAt.IsZero() {
129+
// Should not be a delta greater than 5 seconds.
130+
require.InDelta(t, time.Until(tc.params.ExpiresAt).Seconds(), key.LifetimeSeconds, 5)
131+
} else {
132+
require.Equal(t, int64(tc.params.DeploymentValues.SessionDuration.Value().Seconds()), key.LifetimeSeconds)
133+
}
134+
135+
if !tc.params.ExpiresAt.IsZero() {
136+
require.Equal(t, tc.params.ExpiresAt.UTC(), key.ExpiresAt)
137+
} else if tc.params.LifetimeSeconds > 0 {
138+
require.WithinDuration(t, database.Now().Add(time.Duration(tc.params.LifetimeSeconds)), key.ExpiresAt, time.Second*5)
139+
} else {
140+
require.WithinDuration(t, database.Now().Add(tc.params.DeploymentValues.SessionDuration.Value()), key.ExpiresAt, time.Second*5)
141+
}
142+
143+
if tc.params.RemoteAddr != "" {
144+
require.Equal(t, tc.params.RemoteAddr, key.IPAddress.IPNet.IP.String())
145+
} else {
146+
require.Equal(t, "0.0.0.0", key.IPAddress.IPNet.IP.String())
147+
}
148+
149+
if tc.params.Scope != "" {
150+
require.Equal(t, tc.params.Scope, key.Scope)
151+
} else {
152+
require.Equal(t, database.APIKeyScopeAll, key.Scope)
153+
}
154+
155+
if tc.params.TokenName != "" {
156+
require.Equal(t, tc.params.TokenName, key.TokenName)
157+
}
158+
if tc.params.LoginType != "" {
159+
require.Equal(t, tc.params.LoginType, key.LoginType)
160+
}
161+
})
162+
}
163+
}

0 commit comments

Comments
 (0)