Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf5a9570

Browse files
committed
move api key generation to its own package
1 parentd865841 commitf5a9570

File tree

5 files changed

+147
-136
lines changed

5 files changed

+147
-136
lines changed

‎coderd/apikey.go

Lines changed: 9 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,24 @@ package coderd
22

33
import (
44
"context"
5-
"crypto/sha256"
65
"fmt"
7-
"net"
86
"net/http"
97
"strconv"
108
"time"
119

1210
"github.com/go-chi/chi/v5"
1311
"github.com/google/uuid"
1412
"github.com/moby/moby/pkg/namesgenerator"
15-
"github.com/tabbed/pqtype"
1613
"golang.org/x/xerrors"
1714

15+
"github.com/coder/coder/coderd/apikey"
1816
"github.com/coder/coder/coderd/audit"
1917
"github.com/coder/coder/coderd/database"
2018
"github.com/coder/coder/coderd/httpapi"
2119
"github.com/coder/coder/coderd/httpmw"
2220
"github.com/coder/coder/coderd/rbac"
2321
"github.com/coder/coder/coderd/telemetry"
2422
"github.com/coder/coder/codersdk"
25-
"github.com/coder/coder/cryptorand"
2623
)
2724

2825
// Creates a new token API key that effectively doesn't expire.
@@ -83,7 +80,7 @@ func (api *API) postToken(rw http.ResponseWriter, r *http.Request) {
8380
return
8481
}
8582

86-
cookie,key,err:=api.createAPIKey(ctx,createAPIKeyParams{
83+
cookie,key,err:=api.createAPIKey(ctx,apikey.CreateParams{
8784
UserID:user.ID,
8885
LoginType:database.LoginTypeToken,
8986
ExpiresAt:database.Now().Add(lifeTime),
@@ -127,7 +124,7 @@ func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) {
127124
user:=httpmw.UserParam(r)
128125

129126
lifeTime:=time.Hour*24*7
130-
cookie,_,err:=api.createAPIKey(ctx,createAPIKeyParams{
127+
cookie,_,err:=api.createAPIKey(ctx,apikey.CreateParams{
131128
UserID:user.ID,
132129
LoginType:database.LoginTypePassword,
133130
RemoteAddr:r.RemoteAddr,
@@ -359,21 +356,6 @@ func (api *API) tokenConfig(rw http.ResponseWriter, r *http.Request) {
359356
)
360357
}
361358

362-
// Generates a new ID and secret for an API key.
363-
funcGenerateAPIKeyIDSecret() (idstring,secretstring,errerror) {
364-
// Length of an API Key ID.
365-
id,err=cryptorand.String(10)
366-
iferr!=nil {
367-
return"","",err
368-
}
369-
// Length of an API Key secret.
370-
secret,err=cryptorand.String(22)
371-
iferr!=nil {
372-
return"","",err
373-
}
374-
returnid,secret,nil
375-
}
376-
377359
typecreateAPIKeyParamsstruct {
378360
UserID uuid.UUID
379361
RemoteAddrstring
@@ -401,79 +383,27 @@ func (api *API) validateAPIKeyLifetime(lifetime time.Duration) error {
401383
returnnil
402384
}
403385

404-
func (api*API)createAPIKey(ctx context.Context,paramscreateAPIKeyParams) (*http.Cookie,*database.APIKey,error) {
405-
keyID,keySecret,err:=GenerateAPIKeyIDSecret()
386+
func (api*API)createAPIKey(ctx context.Context,paramsapikey.CreateParams) (*http.Cookie,*database.APIKey,error) {
387+
secret,key,err:=apikey.Generate(params)
406388
iferr!=nil {
407389
returnnil,nil,xerrors.Errorf("generate API key: %w",err)
408390
}
409-
hashed:=sha256.Sum256([]byte(keySecret))
410391

411-
// Default expires at to now+lifetime, or use the configured value if not
412-
// set.
413-
ifparams.ExpiresAt.IsZero() {
414-
ifparams.LifetimeSeconds!=0 {
415-
params.ExpiresAt=database.Now().Add(time.Duration(params.LifetimeSeconds)*time.Second)
416-
}else {
417-
params.ExpiresAt=database.Now().Add(api.DeploymentValues.SessionDuration.Value())
418-
params.LifetimeSeconds=int64(api.DeploymentValues.SessionDuration.Value().Seconds())
419-
}
420-
}
421-
ifparams.LifetimeSeconds==0 {
422-
params.LifetimeSeconds=int64(time.Until(params.ExpiresAt).Seconds())
423-
}
424-
425-
ip:=net.ParseIP(params.RemoteAddr)
426-
ifip==nil {
427-
ip=net.IPv4(0,0,0,0)
428-
}
429-
bitlen:=len(ip)*8
430-
431-
scope:=database.APIKeyScopeAll
432-
ifparams.Scope!="" {
433-
scope=params.Scope
434-
}
435-
switchscope {
436-
casedatabase.APIKeyScopeAll,database.APIKeyScopeApplicationConnect:
437-
default:
438-
returnnil,nil,xerrors.Errorf("invalid API key scope: %q",scope)
439-
}
440-
441-
key,err:=api.Database.InsertAPIKey(ctx, database.InsertAPIKeyParams{
442-
ID:keyID,
443-
UserID:params.UserID,
444-
LifetimeSeconds:params.LifetimeSeconds,
445-
IPAddress: pqtype.Inet{
446-
IPNet: net.IPNet{
447-
IP:ip,
448-
Mask:net.CIDRMask(bitlen,bitlen),
449-
},
450-
Valid:true,
451-
},
452-
// Make sure in UTC time for common time zone
453-
ExpiresAt:params.ExpiresAt.UTC(),
454-
CreatedAt:database.Now(),
455-
UpdatedAt:database.Now(),
456-
HashedSecret:hashed[:],
457-
LoginType:params.LoginType,
458-
Scope:scope,
459-
TokenName:params.TokenName,
460-
})
392+
newkey,err:=api.Database.InsertAPIKey(ctx,key)
461393
iferr!=nil {
462394
returnnil,nil,xerrors.Errorf("insert API key: %w",err)
463395
}
464396

465397
api.Telemetry.Report(&telemetry.Snapshot{
466-
APIKeys: []telemetry.APIKey{telemetry.ConvertAPIKey(key)},
398+
APIKeys: []telemetry.APIKey{telemetry.ConvertAPIKey(newkey)},
467399
})
468400

469-
// This format is consumed by the APIKey middleware.
470-
sessionToken:=fmt.Sprintf("%s-%s",keyID,keySecret)
471401
return&http.Cookie{
472402
Name:codersdk.SessionTokenCookie,
473-
Value:sessionToken,
403+
Value:secret,
474404
Path:"/",
475405
HttpOnly:true,
476406
SameSite:http.SameSiteLaxMode,
477407
Secure:api.SecureAuthCookie,
478-
},&key,nil
408+
},&newkey,nil
479409
}

‎coderd/apikey/apikey.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package apikey
2+
3+
import (
4+
"crypto/sha256"
5+
"fmt"
6+
"net"
7+
"time"
8+
9+
"github.com/google/uuid"
10+
"github.com/tabbed/pqtype"
11+
"golang.org/x/xerrors"
12+
13+
"github.com/coder/coder/coderd/database"
14+
"github.com/coder/coder/codersdk"
15+
"github.com/coder/coder/cryptorand"
16+
)
17+
18+
typeCreateParamsstruct {
19+
UserID uuid.UUID
20+
LoginType database.LoginType
21+
DeploymentValues*codersdk.DeploymentValues
22+
23+
// Optional.
24+
ExpiresAt time.Time
25+
LifetimeSecondsint64
26+
Scope database.APIKeyScope
27+
TokenNamestring
28+
RemoteAddrstring
29+
}
30+
31+
// Generate generates an API key, returning the key as a string as well as the
32+
// database representation. It is the responsibility of the caller to insert it
33+
// into the database.
34+
funcGenerate(paramsCreateParams) (string, database.InsertAPIKeyParams,error) {
35+
keyID,keySecret,err:=generateKey()
36+
iferr!=nil {
37+
return"", database.InsertAPIKeyParams{},xerrors.Errorf("generate API key: %w",err)
38+
}
39+
40+
hashed:=sha256.Sum256([]byte(keySecret))
41+
42+
// Default expires at to now+lifetime, or use the configured value if not
43+
// set.
44+
ifparams.ExpiresAt.IsZero() {
45+
ifparams.LifetimeSeconds!=0 {
46+
params.ExpiresAt=database.Now().Add(time.Duration(params.LifetimeSeconds)*time.Second)
47+
}else {
48+
params.ExpiresAt=database.Now().Add(params.DeploymentValues.SessionDuration.Value())
49+
params.LifetimeSeconds=int64(params.DeploymentValues.SessionDuration.Value().Seconds())
50+
}
51+
}
52+
ifparams.LifetimeSeconds==0 {
53+
params.LifetimeSeconds=int64(time.Until(params.ExpiresAt).Seconds())
54+
}
55+
56+
ip:=net.ParseIP(params.RemoteAddr)
57+
ifip==nil {
58+
ip=net.IPv4(0,0,0,0)
59+
}
60+
61+
bitlen:=len(ip)*8
62+
63+
scope:=database.APIKeyScopeAll
64+
ifparams.Scope!="" {
65+
scope=params.Scope
66+
}
67+
switchscope {
68+
casedatabase.APIKeyScopeAll,database.APIKeyScopeApplicationConnect:
69+
default:
70+
return"", database.InsertAPIKeyParams{},xerrors.Errorf("invalid API key scope: %q",scope)
71+
}
72+
73+
keyStr:=fmt.Sprintf("%s-%s",keyID,keySecret)
74+
75+
returnkeyStr, database.InsertAPIKeyParams{
76+
ID:keyID,
77+
UserID:params.UserID,
78+
LifetimeSeconds:params.LifetimeSeconds,
79+
IPAddress: pqtype.Inet{
80+
IPNet: net.IPNet{
81+
IP:ip,
82+
Mask:net.CIDRMask(bitlen,bitlen),
83+
},
84+
Valid:true,
85+
},
86+
// Make sure in UTC time for common time zone
87+
ExpiresAt:params.ExpiresAt.UTC(),
88+
CreatedAt:database.Now(),
89+
UpdatedAt:database.Now(),
90+
HashedSecret:hashed[:],
91+
LoginType:params.LoginType,
92+
Scope:scope,
93+
TokenName:params.TokenName,
94+
},nil
95+
}
96+
97+
// generateKey a new ID and secret for an API key.
98+
funcgenerateKey() (idstring,secretstring,errerror) {
99+
// Length of an API Key ID.
100+
id,err=cryptorand.String(10)
101+
iferr!=nil {
102+
return"","",err
103+
}
104+
// Length of an API Key secret.
105+
secret,err=cryptorand.String(22)
106+
iferr!=nil {
107+
return"","",err
108+
}
109+
returnid,secret,nil
110+
}

‎coderd/provisionerdserver/provisionerdserver.go

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ package provisionerdserver
22

33
import (
44
"context"
5-
"crypto/sha256"
65
"database/sql"
76
"encoding/json"
87
"errors"
98
"fmt"
10-
"net"
119
"net/http"
1210
"net/url"
1311
"reflect"
@@ -29,6 +27,7 @@ import (
2927

3028
"cdr.dev/slog"
3129

30+
"github.com/coder/coder/coderd/apikey"
3231
"github.com/coder/coder/coderd/audit"
3332
"github.com/coder/coder/coderd/database"
3433
"github.com/coder/coder/coderd/database/dbauthz"
@@ -39,7 +38,6 @@ import (
3938
"github.com/coder/coder/coderd/telemetry"
4039
"github.com/coder/coder/coderd/tracing"
4140
"github.com/coder/coder/codersdk"
42-
"github.com/coder/coder/cryptorand"
4341
"github.com/coder/coder/provisioner"
4442
"github.com/coder/coder/provisionerd/proto"
4543
"github.com/coder/coder/provisionersdk"
@@ -1424,28 +1422,16 @@ func workspaceSessionTokenName(workspace database.Workspace) string {
14241422
returnfmt.Sprintf("%s_%s_session_token",workspace.OwnerID,workspace.ID)
14251423
}
14261424

1427-
// Generates a new ID and secret for an API key.
1428-
// TODO put API key logic in separate package.
1429-
funcGenerateAPIKeyIDSecret() (idstring,secretstring,errerror) {
1430-
// Length of an API Key ID.
1431-
id,err=cryptorand.String(10)
1432-
iferr!=nil {
1433-
return"","",err
1434-
}
1435-
// Length of an API Key secret.
1436-
secret,err=cryptorand.String(22)
1437-
iferr!=nil {
1438-
return"","",err
1439-
}
1440-
returnid,secret,nil
1441-
}
1442-
14431425
func (server*Server)regenerateSessionToken(ctx context.Context,user database.User,workspace database.Workspace) (string,error) {
1444-
id,secret,err:=GenerateAPIKeyIDSecret()
1426+
secret,newkey,err:=apikey.Generate(apikey.CreateParams{
1427+
UserID:user.ID,
1428+
LoginType:user.LoginType,
1429+
DeploymentValues:server.DeploymentValues,
1430+
TokenName:workspaceSessionTokenName(workspace),
1431+
})
14451432
iferr!=nil {
14461433
return"",xerrors.Errorf("generate API key: %w",err)
14471434
}
1448-
hashed:=sha256.Sum256([]byte(secret))
14491435

14501436
err=server.Database.InTx(
14511437
func(tx database.Store)error {
@@ -1463,27 +1449,7 @@ func (server *Server) regenerateSessionToken(ctx context.Context, user database.
14631449
returnxerrors.Errorf("get api key by name: %w",err)
14641450
}
14651451

1466-
ip:=net.IPv4(0,0,0,0)
1467-
bitlen:=len(ip)*8
1468-
_,err=tx.InsertAPIKey(ctx, database.InsertAPIKeyParams{
1469-
ID:id,
1470-
UserID:workspace.OwnerID,
1471-
LifetimeSeconds:int64(server.DeploymentValues.MaxTokenLifetime.Value().Seconds()),
1472-
ExpiresAt:database.Now().Add(server.DeploymentValues.MaxTokenLifetime.Value()).UTC(),
1473-
IPAddress: pqtype.Inet{
1474-
IPNet: net.IPNet{
1475-
IP:ip,
1476-
Mask:net.CIDRMask(bitlen,bitlen),
1477-
},
1478-
Valid:true,
1479-
},
1480-
CreatedAt:database.Now(),
1481-
UpdatedAt:database.Now(),
1482-
HashedSecret:hashed[:],
1483-
LoginType:user.LoginType,
1484-
Scope:database.APIKeyScopeAll,
1485-
TokenName:workspaceSessionTokenName(workspace),
1486-
})
1452+
_,err=tx.InsertAPIKey(ctx,newkey)
14871453
iferr!=nil {
14881454
returnxerrors.Errorf("insert API key: %w",err)
14891455
}
@@ -1493,7 +1459,7 @@ func (server *Server) regenerateSessionToken(ctx context.Context, user database.
14931459
iferr!=nil {
14941460
return"",xerrors.Errorf("regenerate API key: %w",err)
14951461
}
1496-
returnfmt.Sprintf("%s-%s",id,secret),nil
1462+
returnsecret,nil
14971463
}
14981464

14991465
// obtainOIDCAccessToken returns a valid OpenID Connect access token

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp