Add TempUrl signature validation to local storage

Implemented local storage-based file handling with TempUrl signature validation for upload and retrieval. Added validation checks for parameters like max file size/count, expiration, and signature integrity. Included unit tests for TempUrl signature validation and adjusted configuration for local storage.
This commit is contained in:
2025-01-06 14:37:35 +01:00
parent 0c628c39db
commit 999ac3af2b
6 changed files with 609 additions and 25 deletions

View File

@@ -33,11 +33,11 @@ class TempUrlLocalStorageGenerator implements TempUrlGeneratorInterface
$expiration = $this->clock->now()->getTimestamp() + min($expire_delay ?? self::SIGNATURE_DURATION, self::SIGNATURE_DURATION);
return new SignedUrl(
$method,
strtoupper($method),
$this->urlGenerator->generate('chill_docstore_stored_object_operate', [
'object_name' => $object_name,
'exp' => $expiration,
'sig' => $this->sign($method, $object_name, $expiration),
'sig' => $this->sign(strtoupper($method), $object_name, $expiration),
], UrlGeneratorInterface::ABSOLUTE_URL),
\DateTimeImmutable::createFromFormat('U', (string) $expiration),
$object_name,
@@ -70,6 +70,38 @@ class TempUrlLocalStorageGenerator implements TempUrlGeneratorInterface
private function sign(string $method, string $object_name, int $expiration): string
{
return hash_hmac('sha512', $method, sprintf('%s.%s.%s.%d', $method, $this->secret, $object_name, $expiration));
return hash('sha512', sprintf('%s.%s.%s.%d', $method, $this->secret, $object_name, $expiration));
}
public function validateSignaturePost(string $signature, string $prefix, int $expiration, int $maxFileSize, int $maxFileCount): bool
{
if (15_000_000 !== $maxFileSize || 1 !== $maxFileCount) {
return false;
}
return $this->internalValidateSignature($signature, 'POST', $prefix, $expiration);
}
private function internalValidateSignature(string $signature, string $method, string $object_name, int $expiration): bool
{
if ($expiration < $this->clock->now()->format('U')) {
return false;
}
if ('' === $object_name) {
return false;
}
return $this->sign($method, $object_name, $expiration) === $signature;
}
public function validateSignature(string $signature, string $method, string $objectName, int $expiration): bool
{
if (!in_array($method, ['GET', 'HEAD'], true)) {
return false;
}
return $this->internalValidateSignature($signature, $method, $objectName, $expiration);
}
}