Skip to content

feat: add signature to ZIP tarball URL stored in KV store#875

Merged
vladfrangu merged 5 commits intomasterfrom
feat/sign-tarball-kv-record-url
Aug 12, 2025
Merged

feat: add signature to ZIP tarball URL stored in KV store#875
vladfrangu merged 5 commits intomasterfrom
feat/sign-tarball-kv-record-url

Conversation

@danpoletaev
Copy link
Contributor

@danpoletaev danpoletaev commented Aug 6, 2025

Recently we introduced restricted resource access, which disables anonymous access to resources. More context

Later we found a bug 👇
When user with disabled anonymous access tries to apify push Actor, the build can't be done, because worker tries to download ZIP file stored in KV-store without token.
This PR fixes it by generating KV-store record signature and appending it to the download URL.

More context about bug: Slack conversation

Note: I'll merge it after, we'll release new apify-client method: apify/apify-client-js#725

@danpoletaev danpoletaev requested a review from tobice August 6, 2025 14:39
@danpoletaev danpoletaev self-assigned this Aug 6, 2025
@github-actions github-actions bot added t-core-services Issues with this label are in the ownership of the core services team. tested Temporary label used only programatically for some analytics. labels Aug 6, 2025
yarn.lock Outdated
languageName: node
linkType: hard

"apify-client@npm:^2.13.0":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please deduplicate the lockfile so we dont have two installations of the client

(just run yarn dedupe)

Copy link
Contributor

@tobice tobice left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks for taking care of this! ❤️

const store = await testUserClient.keyValueStores().getOrCreate(`actor-${testActor.id}-source`);

expect(store.urlSigningSecretKey).toBeDefined();
const signature = createHmacSignature(store.urlSigningSecretKey!, `version-${actorJson.version}.zip`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(opt) I'm never fond of when tests simply replicate the code being tested 😄 It's not much of a test...

Is this running against actual Apify?

If so, I'd suggest to:

  1. Send a request to restrict access on the key-value store.
  2. Test that the tarballUrl can be downloaded.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this running against actual Apify?

Yes, yes it is!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactored the test

Comment on lines +259 to +276
const tempTarballUrl = new URL(
`${apifyClient.baseUrl}/key-value-stores/${store.id}/records/${key}?disableRedirect=true`,
);

/**
* Signs the tarball URL to grant temporary access for restricted resources.
* When a store is set to 'RESTRICTED', direct URLs are disabled. Instead of
* appending a security token, we add a signature to the URL parameters.
* https://github.com/apify/apify-core/issues/22197
*
* TODO: Use keyValueStore(:storeId).getRecordPublicUrl from apify-client instead once it is released.
*/
if (store?.urlSigningSecretKey) {
const signature = createHmacSignature(store.urlSigningSecretKey, key);
tempTarballUrl.searchParams.set('signature', signature);
}

tarballUrl = tempTarballUrl.toString();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this use the same getRecordPublicUrl?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd leave it as it is! It helps to make sure, that the URL has correct signature.

If for some reason getRecordPublicUrl will return URL without signature, we'll catch it in the test

@vladfrangu vladfrangu merged commit a1e9982 into master Aug 12, 2025
24 checks passed
@vladfrangu vladfrangu deleted the feat/sign-tarball-kv-record-url branch August 12, 2025 11:37
@tobice tobice added the validated Issues that are resolved and their solutions fulfill the acceptance criteria. label Aug 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

t-core-services Issues with this label are in the ownership of the core services team. tested Temporary label used only programatically for some analytics. validated Issues that are resolved and their solutions fulfill the acceptance criteria.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants