diff --git a/docker/nginx/conf.d/include/cors-headers b/docker/nginx/conf.d/include/cors-headers index 0f0bb328..80ee73bd 100644 --- a/docker/nginx/conf.d/include/cors-headers +++ b/docker/nginx/conf.d/include/cors-headers @@ -1,5 +1,5 @@ more_set_headers 'Access-Control-Allow-Origin: $http_origin'; more_set_headers 'Access-Control-Allow-Credentials: true'; more_set_headers 'Access-Control-Allow-Methods: GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE'; -more_set_headers 'Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,If-None-Match,Cache-Control,Content-Type,Range,X-HTTP-Method-Override,upload-offset,upload-metadata,upload-length,tus-version,tus-resumable,tus-extension,tus-max-size,upload-concat,location,Skynet-API-Key'; +more_set_headers 'Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,If-None-Match,Cache-Control,Content-Type,Range,X-HTTP-Method-Override,upload-offset,upload-metadata,upload-length,tus-version,tus-resumable,tus-extension,tus-max-size,upload-concat,location,Skynet-Api-Key'; more_set_headers 'Access-Control-Expose-Headers: Content-Length,Content-Range,ETag,Skynet-File-Metadata,Skynet-Skylink,Skynet-Proof,Skynet-Portal-Api,Skynet-Server-Api,upload-offset,upload-metadata,upload-length,tus-version,tus-resumable,tus-extension,tus-max-size,upload-concat,location'; diff --git a/packages/health-check/bin/cli b/packages/health-check/bin/cli index dbf39344..5bf0064c 100755 --- a/packages/health-check/bin/cli +++ b/packages/health-check/bin/cli @@ -6,16 +6,6 @@ require("yargs/yargs")(process.argv.slice(2)) .help() .demandCommand() .strict(true) - .command( - "__authenticate", // Internal only function - this function will be removed when API keys are implemented - false, // hide this function cli help - () => {}, - async () => { - const { getAuthCookie } = require("../src/utils"); - - console.log(await getAuthCookie(true)); - } - ) .command( "enable", "Mark portal as enabled", diff --git a/packages/health-check/src/checks/critical.js b/packages/health-check/src/checks/critical.js index ac406f10..db9617e3 100644 --- a/packages/health-check/src/checks/critical.js +++ b/packages/health-check/src/checks/critical.js @@ -1,12 +1,14 @@ const got = require("got"); const FormData = require("form-data"); const { isEqual } = require("lodash"); -const { calculateElapsedTime, getResponseContent, getAuthCookie, isPortalModuleEnabled } = require("../utils"); +const { calculateElapsedTime, getResponseContent, isPortalModuleEnabled } = require("../utils"); const { SkynetClient, stringToUint8ArrayUtf8, genKeyPairAndSeed } = require("skynet-js"); const MODULE_BLOCKER = "b"; -const skynetClient = new SkynetClient(process.env.SKYNET_PORTAL_API); +const skynetClient = new SkynetClient(process.env.SKYNET_PORTAL_API, { + skynetApiKey: process.env.ACCOUNTS_TEST_USER_API_KEY, +}); const exampleSkylink = "AACogzrAimYPG42tDOKhS3lXZD8YvlF8Q8R17afe95iV2Q"; // check that any relevant configuration is properly set in skyd @@ -36,7 +38,6 @@ async function skydConfigCheck(done) { // uploadCheck returns the result of uploading a sample file async function uploadCheck(done) { - const authCookie = await getAuthCookie(); const time = process.hrtime(); const form = new FormData(); const payload = Buffer.from(new Date()); // current date to ensure data uniqueness @@ -47,7 +48,9 @@ async function uploadCheck(done) { try { const response = await got.post(`${process.env.SKYNET_PORTAL_API}/skynet/skyfile`, { body: form, - headers: { cookie: authCookie }, + headers: { + "Skynet-Api-Key": process.env.ACCOUNTS_TEST_USER_API_KEY, + }, }); data.statusCode = response.statusCode; @@ -106,15 +109,14 @@ async function accountWebsiteCheck(done) { // registryWriteAndReadCheck writes to registry and immediately reads and compares the data async function registryWriteAndReadCheck(done) { - const authCookie = await getAuthCookie(); const time = process.hrtime(); const data = { name: "registry_write_and_read", up: false }; const { privateKey, publicKey } = genKeyPairAndSeed(); const expected = { dataKey: "foo-key", data: stringToUint8ArrayUtf8("foo-data"), revision: BigInt(0) }; try { - await skynetClient.registry.setEntry(privateKey, expected, { customCookie: authCookie }); - const { entry } = await skynetClient.registry.getEntry(publicKey, expected.dataKey, { customCookie: authCookie }); + await skynetClient.registry.setEntry(privateKey, expected); + const { entry } = await skynetClient.registry.getEntry(publicKey, expected.dataKey); if (isEqual(expected, entry)) { data.up = true; @@ -204,12 +206,16 @@ async function blockerHealthCheck(done) { } async function genericAccessCheck(name, url) { - const authCookie = await getAuthCookie(); const time = process.hrtime(); const data = { up: false, url }; try { - const response = await got(url, { headers: { cookie: `nocache=true;${authCookie}` } }); + const response = await got(url, { + headers: { + cookie: "nocache=true", + "Skynet-Api-Key": process.env.ACCOUNTS_TEST_USER_API_KEY, + }, + }); data.statusCode = response.statusCode; data.up = true; diff --git a/packages/health-check/src/checks/extended.js b/packages/health-check/src/checks/extended.js index 170bd9d1..5c620c61 100644 --- a/packages/health-check/src/checks/extended.js +++ b/packages/health-check/src/checks/extended.js @@ -2,7 +2,7 @@ const got = require("got"); const hasha = require("hasha"); const { detailedDiff } = require("deep-object-diff"); const { isEqual } = require("lodash"); -const { calculateElapsedTime, ensureValidJSON, getResponseContent, getAuthCookie } = require("../utils"); +const { calculateElapsedTime, ensureValidJSON, getResponseContent } = require("../utils"); const { parseSkylink } = require("skynet-js"); // audioExampleCheck returns the result of trying to download the skylink @@ -1130,13 +1130,18 @@ function parseHeaderString(header) { // skylinkVerification verifies a skylink against provided information. async function skylinkVerification(done, expected, { followRedirect = true, method = "get" } = {}) { - const authCookie = await getAuthCookie(); const time = process.hrtime(); const details = { name: expected.name, skylink: expected.skylink }; try { const query = `${process.env.SKYNET_PORTAL_API}/${expected.skylink}`; - const response = await got[method](query, { followRedirect, headers: { cookie: `nocache=true;${authCookie}` } }); + const response = await got[method](query, { + followRedirect, + headers: { + cookie: "nocache=true", + "Skynet-Api-Key": process.env.ACCOUNTS_TEST_USER_API_KEY, + }, + }); const entry = { ...details, up: true, statusCode: response.statusCode, time: calculateElapsedTime(time) }; const info = {}; diff --git a/packages/health-check/src/utils.js b/packages/health-check/src/utils.js index 8dbab0de..19a8e594 100644 --- a/packages/health-check/src/utils.js +++ b/packages/health-check/src/utils.js @@ -61,70 +61,6 @@ function getRequiredEnvironmentVariable(name) { return value; } -/** - * Authenticate with given credentials and return auth cookie - * Creates new account if username does not exist - * Only authenticates when portal is set to authenticated users only mode - * @param {boolean} forceAuth forcibly ensure authentication with test credentials - */ -function getAuthCookie(forceAuth = false) { - // cache auth promise so only one actual request will be made - if (getAuthCookie.cache) return getAuthCookie.cache; - - // accounts disabled, do not try to authenticate - if (!isPortalModuleEnabled("a")) return ""; - - // do not authenticate if it is not required by portal limit access rule - if (!forceAuth && !["authenticated", "subscription"].includes(process.env.ACCOUNTS_LIMIT_ACCESS)) return ""; - - // assign all required environment variables - const portalDomain = getRequiredEnvironmentVariable("PORTAL_DOMAIN"); - const email = getRequiredEnvironmentVariable("ACCOUNTS_TEST_USER_EMAIL"); - const password = getRequiredEnvironmentVariable("ACCOUNTS_TEST_USER_PASSWORD"); - - async function authenticate() { - const got = require("got"); - - try { - // authenticate with given test user credentials - const response = await got.post(`https://account.${portalDomain}/api/login`, { - json: { email, password }, - }); - - // extract set-cookie from successful authentication request - const cookies = response.headers["set-cookie"]; - - // throw meaningful error when set-cookie header is missing - if (!cookies) throw new Error(`Auth successful (code ${response.statusCode}) but 'set-cookie' header is missing`); - - // find the skynet-jwt cookie - const jwtcookie = cookies.find((cookie) => cookie.startsWith("skynet-jwt")); - - // throw meaningful error when skynet-jwt cookie is missing - if (!jwtcookie) throw new Error(`Header 'set-cookie' found but 'skynet-jwt' cookie is missing`); - - // extract just the cookie value (no set-cookie props) from set-cookie - return jwtcookie.match(/skynet-jwt=[^;]+;/)[0]; - } catch (error) { - // 401 means that service worked but user could not have been authenticated - if (error.response && error.response.statusCode === 401) { - // sign up with the given credentials - await got.post(`https://account.${portalDomain}/api/user`, { - json: { email, password }, - }); - - // retry authentication - return authenticate(); - } - - // rethrow unhandled exception - throw error; - } - } - - return (getAuthCookie.cache = authenticate()); -} - /** * isPortalModuleEnabled returns true if the given module is enabled */ @@ -137,7 +73,6 @@ module.exports = { getYesterdayISOString, getResponseContent, ensureValidJSON, - getAuthCookie, isPortalModuleEnabled, ipCheckService, ipRegex,