feat: Add ip_address to API keys (#2580)

Fixes #2561.
This commit is contained in:
Kyle Carberry
2022-06-22 12:32:21 -05:00
committed by GitHub
parent caf9c41a9e
commit b7eeb436ad
13 changed files with 144 additions and 49 deletions

View File

@ -7,12 +7,15 @@ import (
"database/sql"
"errors"
"fmt"
"net"
"net/http"
"strings"
"time"
"golang.org/x/oauth2"
"github.com/tabbed/pqtype"
"github.com/coder/coder/coderd/database"
"github.com/coder/coder/coderd/httpapi"
)
@ -164,6 +167,17 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
// Only update LastUsed once an hour to prevent database spam.
if now.Sub(key.LastUsed) > time.Hour {
key.LastUsed = now
remoteIP := net.ParseIP(r.RemoteAddr)
if remoteIP == nil {
remoteIP = net.IPv4(0, 0, 0, 0)
}
key.IPAddress = pqtype.Inet{
IPNet: net.IPNet{
IP: remoteIP,
Mask: remoteIP.DefaultMask(),
},
Valid: true,
}
changed = true
}
// Only update the ExpiresAt once an hour to prevent database spam.
@ -178,6 +192,7 @@ func ExtractAPIKey(db database.Store, oauth *OAuth2Configs) func(http.Handler) h
ID: key.ID,
LastUsed: key.LastUsed,
ExpiresAt: key.ExpiresAt,
IPAddress: key.IPAddress,
OAuthAccessToken: key.OAuthAccessToken,
OAuthRefreshToken: key.OAuthRefreshToken,
OAuthExpiry: key.OAuthExpiry,

View File

@ -402,6 +402,41 @@ func TestAPIKey(t *testing.T) {
require.Equal(t, token.Expiry, gotAPIKey.ExpiresAt)
require.Equal(t, token.AccessToken, gotAPIKey.OAuthAccessToken)
})
t.Run("RemoteIPUpdates", func(t *testing.T) {
t.Parallel()
var (
db = databasefake.New()
id, secret = randomAPIKeyParts()
hashed = sha256.Sum256([]byte(secret))
r = httptest.NewRequest("GET", "/", nil)
rw = httptest.NewRecorder()
user = createUser(r.Context(), t, db)
)
r.RemoteAddr = "1.1.1.1"
r.AddCookie(&http.Cookie{
Name: httpmw.SessionTokenKey,
Value: fmt.Sprintf("%s-%s", id, secret),
})
sentAPIKey, err := db.InsertAPIKey(r.Context(), database.InsertAPIKeyParams{
ID: id,
HashedSecret: hashed[:],
LastUsed: database.Now().AddDate(0, 0, -1),
ExpiresAt: database.Now().AddDate(0, 0, 1),
UserID: user.ID,
})
require.NoError(t, err)
httpmw.ExtractAPIKey(db, nil)(successHandler).ServeHTTP(rw, r)
res := rw.Result()
defer res.Body.Close()
require.Equal(t, http.StatusOK, res.StatusCode)
gotAPIKey, err := db.GetAPIKeyByID(r.Context(), id)
require.NoError(t, err)
require.NotEqual(t, sentAPIKey.IPAddress, gotAPIKey.IPAddress)
})
}
func createUser(ctx context.Context, t *testing.T, db database.Store) database.User {