diff --git a/docs/RELEASE.md b/docs/RELEASE.md index 53c1c80732..ddfb379180 100644 --- a/docs/RELEASE.md +++ b/docs/RELEASE.md @@ -26,42 +26,33 @@ docker pull ghcr.io/scality/cloudserver: To release a production image: -* Create a PR to bump the package version - Update Cloudserver's `package.json` by bumping it to the relevant next - version in a new PR. Per example if the last released version was - `8.4.7`, the next version would be `8.4.8`. - -```js -{ - "name": "cloudserver", - "version": "8.4.8", <--- Here - [...] -} -``` +* Create a PR to bump the package version : + update Cloudserver's `package.json` by bumping it to the relevant next + version in a new PR. Per example if the last released version was `8.4.7`, + the next version would be `8.4.8`. + + ```js + { + "name": "cloudserver", + "version": "8.4.8", <--- Here + [...] + } + ``` * Review & merge the PR -* Create the release on GitHub - - * Go the Release tab (https://github.com/scality/cloudserver/releases); - * Click on the `Draft new release button`; - * In the `tag` field, type the name of the release (`8.4.8`), and confirm - to create the tag on publish; - * Click on `Generate release notes` button to fill the fields; - * Rename the release to `Release x.y.z` (e.g. `Release 8.4.8` in this case); - * Click to `Publish the release` to create the GitHub release and git tag - - Notes: - * the Git tag will be created automatically. - * this should be done as soon as the PR is merged, so that the tag - is put on the "version bump" commit. - -* With the following parameters, [force a build here](https://eve.devsca.com/github/scality/cloudserver/#/builders/3/force/force) - - * Branch Name: The one used for the tag earlier. In this example `development/8.4` - * Override Stage: 'release' - * Extra properties: - * name: `'tag'`, value: `[release version]`, in this example`'8.4.8'` +* Trigger the release workflow on GitHub + + * Go to the [**Actions** tab on GitHub](https://github.com/scality/cloudserver/actions) + * Select the `release` workflow from the list + * Click on **Run workflow** (manual dispatch) + * Enter the new tag (e.g., `8.4.8`) in the input field + * Start the workflow + + This workflow will create the tag and push the Docker images. + + This should be done as soon as the PR is merged, + so that the tag is put on the "version bump" commit. * Release the release version on Jira diff --git a/lib/api/apiUtils/authorization/prepareRequestContexts.js b/lib/api/apiUtils/authorization/prepareRequestContexts.js index c33fcc9c82..c62ace060a 100644 --- a/lib/api/apiUtils/authorization/prepareRequestContexts.js +++ b/lib/api/apiUtils/authorization/prepareRequestContexts.js @@ -252,6 +252,15 @@ function prepareRequestContexts(apiMethod, request, sourceBucket, generateRequestContext('bypassGovernanceRetention'); requestContexts.push(checkUserGovernanceBypassRequestContext); } + } else if (apiMethodAfterVersionCheck === 'bucketGet') { + requestContexts.push(generateRequestContext(apiMethodAfterVersionCheck)); + + const optionalAttributesHeader = request.headers['x-amz-optional-object-attributes']; + const requestedAttributes = optionalAttributesHeader ? optionalAttributesHeader.split(',') : []; + + if (requestedAttributes.filter(attr => attr != 'RestoreStatus').length > 0) { + requestContexts.push(generateRequestContext('listObjectsV2OptionalAttributes')); + } } else { const requestContext = generateRequestContext(apiMethodAfterVersionCheck); diff --git a/lib/api/bucketGet.js b/lib/api/bucketGet.js index d4e7e1b81b..767437b992 100644 --- a/lib/api/bucketGet.js +++ b/lib/api/bucketGet.js @@ -284,6 +284,15 @@ function bucketGet(authInfo, request, log, callback) { const params = request.query; const bucketName = request.bucketName; const v2 = params['list-type']; + + const optionalAttributes = + request.headers['x-amz-optional-object-attributes']?.split(',').map(attr => attr.trim()) ?? []; + if (optionalAttributes.some(attr => !attr.startsWith('x-amz-meta-') && attr != 'RestoreStatus')) { + return callback( + errorInstances.InvalidArgument.customizeDescription('Invalid header x-amz-optional-object-attributes') + ); + } + if (v2 !== undefined && Number.parseInt(v2, 10) !== 2) { return callback(errorInstances.InvalidArgument.customizeDescription('Invalid ' + 'List Type specified in Request')); @@ -352,14 +361,14 @@ function bucketGet(authInfo, request, log, callback) { } standardMetadataValidateBucket(metadataValParams, request.actionImplicitDenies, log, (err, bucket) => { - const corsHeaders = collectCorsHeaders(request.headers.origin, - request.method, bucket); + const corsHeaders = collectCorsHeaders(request.headers.origin, request.method, bucket); + if (err) { log.debug('error processing request', { error: err }); - monitoring.promMetrics( - 'GET', bucketName, err.code, 'listBucket'); + monitoring.promMetrics('GET', bucketName, err.code, 'listBucket'); return callback(err, null, corsHeaders); } + if (params.versions !== undefined) { listParams.listingType = 'DelimiterVersions'; delete listParams.marker; @@ -367,6 +376,7 @@ function bucketGet(authInfo, request, log, callback) { listParams.versionIdMarker = params['version-id-marker'] ? versionIdUtils.decode(params['version-id-marker']) : undefined; } + if (!requestMaxKeys) { const emptyList = { CommonPrefixes: [], @@ -377,14 +387,14 @@ function bucketGet(authInfo, request, log, callback) { return handleResult(listParams, requestMaxKeys, encoding, authInfo, bucketName, emptyList, corsHeaders, log, callback); } - return services.getObjectListing(bucketName, listParams, log, - (err, list) => { + + return services.getObjectListing(bucketName, listParams, log, (err, list) => { if (err) { log.debug('error processing request', { error: err }); - monitoring.promMetrics( - 'GET', bucketName, err.code, 'listBucket'); + monitoring.promMetrics('GET', bucketName, err.code, 'listBucket'); return callback(err, null, corsHeaders); } + return handleResult(listParams, requestMaxKeys, encoding, authInfo, bucketName, list, corsHeaders, log, callback); }); diff --git a/package.json b/package.json index d6865f5772..245b813e9e 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "node-mocks-http": "^1.16.1", "nodemon": "^3.1.10", "nyc": "^15.1.0", + "pino-pretty": "^13.1.3", "sinon": "^13.0.1", "tv4": "^1.3.0" }, @@ -82,7 +83,7 @@ }, "scripts": { "cloudserver": "S3METADATA=mongodb npm-run-all --parallel start_dataserver start_s3server", - "dev": "nodemon --exec \"yarn run start\"", + "dev": "nodemon --exec \"yarn run start\" | pino-pretty -c -S -m message -i \"pid,hostname,name,authn,authz,address,clientPort,clientIP,elapsed_ms\"", "ft_awssdk": "cd tests/functional/aws-node-sdk && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/ --exit", "ft_awssdk_aws": "cd tests/functional/aws-node-sdk && AWS_ON_AIR=true mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/ --exit", "ft_awssdk_buckets": "cd tests/functional/aws-node-sdk && mocha --reporter mocha-multi-reporters --reporter-options configFile=$INIT_CWD/tests/reporter-config.json test/bucket --exit", diff --git a/tests/unit/api/bucketGet.js b/tests/unit/api/bucketGet.js index ba166fd088..971e58748b 100644 --- a/tests/unit/api/bucketGet.js +++ b/tests/unit/api/bucketGet.js @@ -184,17 +184,17 @@ describe('bucketGet API', () => { async.waterfall([ next => bucketPut(authInfo, testPutBucketRequest, log, next), - (corsHeaders, next) => objectPut(authInfo, + (_, next) => objectPut(authInfo, testPutObjectRequest1, undefined, log, next), - (resHeaders, next) => objectPut(authInfo, + (_, next) => objectPut(authInfo, testPutObjectRequest2, undefined, log, next), - (resHeaders, next) => objectPut(authInfo, + (_, next) => objectPut(authInfo, testPutObjectRequest3, undefined, log, next), - (resHeaders, next) => + (_, next) => bucketGet(authInfo, testGetRequest, log, next), - (result, corsHeaders, next) => parseString(result, next), + (result, _, next) => parseString(result, next), ], - (err, result) => { + (_, result) => { test.assertion(result); done(); }); @@ -216,13 +216,13 @@ describe('bucketGet API', () => { async.waterfall([ next => bucketPut(authInfo, testPutBucketRequest, log, next), - (corsHeaders, next) => objectPut(authInfo, testPutObjectRequest4, + (_, next) => objectPut(authInfo, testPutObjectRequest4, undefined, log, next), - (resHeaders, next) => bucketGet(authInfo, testGetRequest, + (_, next) => bucketGet(authInfo, testGetRequest, log, next), - (result, corsHeaders, next) => parseString(result, next), + (result, _, next) => parseString(result, next), ], - (err, result) => { + (_, result) => { assert.strictEqual(result.ListBucketResult.Contents[0].Key[0], testPutObjectRequest4.objectKey); done(); @@ -235,11 +235,11 @@ describe('bucketGet API', () => { async.waterfall([ next => bucketPut(authInfo, testPutBucketRequest, log, next), - (corsHeaders, next) => + (_, next) => bucketGet(authInfo, testGetRequest, log, next), - (result, corsHeaders, next) => parseString(result, next), + (result, _, next) => parseString(result, next), ], - (err, result) => { + (_, result) => { assert.strictEqual(result.ListBucketResult.$.xmlns, 'http://s3.amazonaws.com/doc/2006-03-01/'); done(); @@ -307,17 +307,17 @@ describe('bucketGet API V2', () => { async.waterfall([ next => bucketPut(authInfo, testPutBucketRequest, log, next), - (corsHeaders, next) => objectPut(authInfo, + (_, next) => objectPut(authInfo, testPutObjectRequest1, undefined, log, next), - (resHeaders, next) => objectPut(authInfo, + (_, next) => objectPut(authInfo, testPutObjectRequest2, undefined, log, next), - (resHeaders, next) => objectPut(authInfo, + (_, next) => objectPut(authInfo, testPutObjectRequest3, undefined, log, next), - (resHeaders, next) => + (_, next) => bucketGet(authInfo, testGetRequest, log, next), - (result, corsHeaders, next) => parseString(result, next), + (result, _, next) => parseString(result, next), ], - (err, result) => { + (_, result) => { // v2 requests should return 'KeyCount' in response const keyCount = Number.parseInt(result.ListBucketResult.KeyCount[0], 10); @@ -333,4 +333,186 @@ describe('bucketGet API V2', () => { }); }); }); + + describe('z-amz-optional-attributes header', () => { + it('should return an error if the user does not have the permission', done => { + const authInfoNoPerm = makeAuthInfo('accessKey2'); // A new user without specific permissions + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'x-amz-meta-department'; + + + async.series([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + next => bucketGet(authInfoNoPerm, testGetRequest, log, next), + ], err => { + assert.strictEqual(err.is.AccessDenied, true); + done(); + }); + }); + + it('should ignore the missing permission if the header contains only RestoreStatus', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'RestoreStatus'; + + async.waterfall( + [ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + (_, next) => bucketGet(authInfo, testGetRequest, log, next), + (result, _, next) => parseString(result, next), + ], + (err, result) => { + assert.strictEqual(err, null); + assert.strictEqual(result.ListBucketResult.$.xmlns, 'http://s3.amazonaws.com/doc/2006-03-01/'); + done(); + }, + ); + }); + + it('should return valid xml if the user have the permission', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'x-amz-meta-department'; + + async.waterfall([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + (_, next) => bucketGet(authInfo, testGetRequest, log, next), + (result, _, next) => parseString(result, next), + ], + (err, result) => { + assert.strictEqual(err, null); + assert.strictEqual(result.ListBucketResult.$.xmlns, 'http://s3.amazonaws.com/doc/2006-03-01/'); + done(); + }); + }); + + it('should return an error if the user does not have all permissions for multiple attributes', done => { + const authInfoNoPerm = makeAuthInfo('accessKey2'); + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'RestoreStatus,x-amz-meta-department'; + + async.series([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + next => bucketGet(authInfoNoPerm, testGetRequest, log, next), + ], err => { + assert.strictEqual(err.is.AccessDenied, true); + done(); + }); + }); + + it('should return an error if the header is empty', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = ''; + + async.waterfall([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + (_, next) => bucketGet(authInfo, testGetRequest, log, next), + (result, _, next) => parseString(result, next), + ], err => { + assert.strictEqual(err.is.InvalidArgument, true); + done(); + }); + }); + + it('should return an error for invalid optional attributes', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'InvalidAttribute'; + + async.series([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + next => bucketGet(authInfo, testGetRequest, log, next), + ], err => { + assert.strictEqual(err.is.InvalidArgument, true); + done(); + }); + }); + + it('should accept wildcard value', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'x-amz-meta-*'; + + async.waterfall([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + (_, next) => bucketGet(authInfo, testGetRequest, log, next), + (result, _, next) => parseString(result, next), + ], (err, result) => { + assert.strictEqual(err, null); + assert.strictEqual(result.ListBucketResult.$.xmlns, 'http://s3.amazonaws.com/doc/2006-03-01/'); + done(); + }); + }); + + it('should return an error for a mix of valid and invalid attributes', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'RestoreStatus,InvalidAttribute'; + + async.series([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + next => bucketGet(authInfo, testGetRequest, log, next), + ], err => { + assert.strictEqual(err.is.InvalidArgument, true); + done(); + }); + }); + + it('should handle attributes with leading/trailing whitespace', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'x-amz-meta-foo'; + + async.waterfall([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + (_, next) => bucketGet(authInfo, testGetRequest, log, next), + (result, _, next) => parseString(result, next), + ], + (err, result) => { + assert.strictEqual(err, null); + assert.strictEqual(result.ListBucketResult.$.xmlns, 'http://s3.amazonaws.com/doc/2006-03-01/'); + done(); + }); + }); + + it('should handle multiple valid attributes', done => { + const testGetRequest = Object.assign({ + query: {}, + url: baseUrl, + }, baseGetRequest); + testGetRequest.headers['x-amz-optional-object-attributes'] = 'RestoreStatus,x-amz-meta-foo,x-amz-meta-bar'; + + async.waterfall([ + next => bucketPut(authInfo, testPutBucketRequest, log, next), + (_, next) => bucketGet(authInfo, testGetRequest, log, next), + (result, _, next) => parseString(result, next), + ], + (err, result) => { + assert.strictEqual(err, null); + assert.strictEqual(result.ListBucketResult.$.xmlns, 'http://s3.amazonaws.com/doc/2006-03-01/'); + done(); + }); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 8265351bdb..88c3dfed6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1573,6 +1573,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" @@ -2022,6 +2027,11 @@ color@^3.1.3: color-convert "^1.9.3" color-string "^1.6.0" +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + colorspace@1.1.x: version "1.1.4" resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" @@ -2201,6 +2211,11 @@ data-view-byte-offset@^1.0.1: es-errors "^1.3.0" is-data-view "^1.0.1" +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + dayjs@^1.11.10: version "1.11.15" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.15.tgz#fd7fd2db6fc92f08ffe4adc306756d45db00ada3" @@ -2461,6 +2476,13 @@ encoding@^0.1.13: dependencies: iconv-lite "^0.6.2" +end-of-stream@^1.1.0: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + engine.io-client@~6.6.1: version "6.6.3" resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.6.3.tgz#815393fa24f30b8e6afa8f77ccca2f28146be6de" @@ -2968,6 +2990,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== +fast-copy@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-4.0.1.tgz#be5c74baede1a72adf8168df2dc56e842c77a00e" + integrity sha512-+uUOQlhsaswsizHFmEFAQhB3lSiQ+lisxl50N6ZP0wywlZeWsIESxSi9ftPEps8UGfiBzyYP7x27zA674WUvXw== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3534,6 +3561,11 @@ he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -4298,6 +4330,11 @@ joi@^18.0.1: "@hapi/topo" "^6.0.2" "@standard-schema/spec" "^1.0.0" +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -5454,6 +5491,11 @@ object.values@^1.2.0: define-properties "^1.2.1" es-object-atoms "^1.0.0" +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -5461,7 +5503,7 @@ on-finished@2.4.1: dependencies: ee-first "1.1.1" -once@1.x, once@^1.3.0, once@^1.4.0: +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -5683,6 +5725,32 @@ pify@^4.0.0, pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +pino-abstract-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23" + integrity sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg== + dependencies: + split2 "^4.0.0" + +pino-pretty@^13.1.3: + version "13.1.3" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-13.1.3.tgz#2274cccda925dd355c104079a5029f6598d0381b" + integrity sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^4.0.0" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pump "^3.0.0" + secure-json-parse "^4.0.0" + sonic-boom "^4.0.1" + strip-json-comments "^5.0.2" + pkg-dir@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -5821,6 +5889,14 @@ pull-window@^2.1.4: dependencies: looper "^2.0.0" +pump@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" + integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -6117,6 +6193,11 @@ sax@>=0.6.0, sax@^1.2.4: "@smithy/signature-v4" "^2.1.1" axios "^1.3.4" +secure-json-parse@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c" + integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA== + "semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -6390,6 +6471,13 @@ socks@^2.8.3: ip-address "^9.0.5" smart-buffer "^4.2.0" +sonic-boom@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.0.tgz#e59a525f831210fa4ef1896428338641ac1c124d" + integrity sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww== + dependencies: + atomic-sleep "^1.0.0" + sorted-array-functions@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz#8605695563294dffb2c9796d602bd8459f7a0dd5" @@ -6452,6 +6540,11 @@ spdx-license-ids@^3.0.0: resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.21.tgz#6d6e980c9df2b6fc905343a3b2d702a6239536c3" integrity sha512-Bvg/8F5XephndSK3JffaRqdT+gyhfqIPwDHpX80tJrF8QQRYMo8sNMeaZ2Dp5+jhwKnUmIOyFFQfHRkjJm5nXg== +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a" @@ -6640,6 +6733,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.3.tgz#b7304249dd402ee67fd518ada993ab3593458bcf" + integrity sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw== + strnum@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.0.5.tgz#40700b1b5bf956acdc755e98e90005d7657aaaea"