diff --git a/packages/lambda-tiler/src/util/validate.ts b/packages/lambda-tiler/src/util/validate.ts index f80e35549..5f6fd6403 100644 --- a/packages/lambda-tiler/src/util/validate.ts +++ b/packages/lambda-tiler/src/util/validate.ts @@ -1,5 +1,5 @@ import { ImageFormat, Projection, TileMatrixSet, TileMatrixSets, VectorFormat } from '@basemaps/geo'; -import { Const, isValidApiKey } from '@basemaps/shared'; +import { Const, isValidApiKey, truncateApiKey } from '@basemaps/shared'; import { getImageFormat } from '@basemaps/tiler'; import { LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda'; import { TileXyzGet } from '../routes/tile.xyz'; @@ -25,7 +25,8 @@ export const Validate = { const valid = isValidApiKey(apiKey); if (!valid.valid) throw new LambdaHttpResponse(400, 'API Key Invalid: ' + valid.message); - req.set('api', apiKey); + // Truncate the API Key so we are not logging the full key + req.set('api', truncateApiKey(apiKey)); return apiKey as string; }, diff --git a/packages/shared/src/__tests__/api.test.ts b/packages/shared/src/__tests__/api.test.ts index 244f7ef50..02733e91c 100644 --- a/packages/shared/src/__tests__/api.test.ts +++ b/packages/shared/src/__tests__/api.test.ts @@ -1,6 +1,6 @@ import o from 'ospec'; -import { getApiKey, OneDayMs } from '../api.js'; -import { ulid, decodeTime, encodeTime } from 'ulid'; +import { decodeTime, encodeTime, ulid } from 'ulid'; +import { getApiKey, OneDayMs, truncateApiKey } from '../api.js'; declare const global: { localStorage?: { getItem: (a: string) => string | null; setItem: (k: string, v: string) => void }; @@ -53,3 +53,21 @@ o.spec('ApiKey', () => { o(Date.now() - decodeTime(newApiKey.slice(1).toUpperCase()) < 1000).equals(true); }); }); + +o.spec('ApiKeyTruncate', () => { + o('should truncate apikeys', () => { + o(truncateApiKey('c01h3e17kjsw5evq8ndjxbda80e')).equals('cbda80e'); + o(truncateApiKey('d01h3e17kjsw5evq8ndjxbda80e')).equals('dbda80e'); + }); + + o('should not truncate invalid api keys', () => { + o(truncateApiKey([{ hello: 'world' }])).deepEquals('invalid'); + o(truncateApiKey(null)).equals('invalid'); + o(truncateApiKey(1)).equals('invalid'); + }); + + o('should not truncate truncated', () => { + o(truncateApiKey('cbda80e')).equals('cbda80e'); + o(truncateApiKey('dbda80e')).equals('dbda80e'); + }); +}); diff --git a/packages/shared/src/api.ts b/packages/shared/src/api.ts index 78ef0d53d..78224ace0 100644 --- a/packages/shared/src/api.ts +++ b/packages/shared/src/api.ts @@ -56,3 +56,11 @@ export function isValidApiKey(apiKey?: string | null): ApiKeyStatus { return { valid: true, key: apiKey }; } + +/** Truncate a API key to the last 6 digits */ +export function truncateApiKey(x: unknown): string | undefined { + if (typeof x !== 'string') return 'invalid'; + if (x.startsWith('c')) return 'c' + x.slice(x.length - 6); + if (x.startsWith('d')) return 'd' + x.slice(x.length - 6); + return 'invalid'; +}