Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 40 additions & 44 deletions bin/ensureServiceUser
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't have test for that ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This file is actually used for cmd line commands , when I checked we indeed don't have tests for it as not really needed

Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ const { errors } = require('arsenal');
const { program } = require('commander');
const werelogs = require('werelogs');
const async = require('async');
const { IAM } = require('aws-sdk');
const {
IAMClient,
GetUserCommand,
CreateUserCommand,
GetUserPolicyCommand,
PutUserPolicyCommand,
ListAccessKeysCommand,
CreateAccessKeyCommand,
} = require('@aws-sdk/client-iam');
const { version } = require('../package.json');

const systemPrefix = '/scality-internal/';
Expand All @@ -33,7 +41,7 @@ function generateUserPolicyDocument() {
}

function createIAMClient(opts) {
return new IAM({
return new IAMClient({
endpoint: opts.iamEndpoint,
region: 'us-east-1',
});
Expand Down Expand Up @@ -98,22 +106,18 @@ class UserHandler extends BaseHandler {
resourceType = 'user';

async collect() {
return this.iamClient
.getUser({
UserName: this.serviceName,
})
.promise()
.then(res => res.User);
const res = await this.iamClient.send(new GetUserCommand({
UserName: this.serviceName,
}));
return res.User;
}

async create() {
return this.iamClient
.createUser({
UserName: this.serviceName,
Path: systemPrefix,
})
.promise()
.then(res => res.User);
const res = await this.iamClient.send(new CreateUserCommand({
UserName: this.serviceName,
Path: systemPrefix,
}));
return res.User;
}

conflicts(u) {
Expand All @@ -125,26 +129,22 @@ class UserPolicyHandler extends BaseHandler {
resourceType = 'userPolicy';

async collect() {
return this.iamClient
.getUserPolicy({
UserName: this.serviceName,
PolicyName: this.serviceName,
})
.promise()
.then(() => true);
await this.iamClient.send(new GetUserPolicyCommand({
UserName: this.serviceName,
PolicyName: this.serviceName,
}));
return true;
}

async create() {
const doc = generateUserPolicyDocument();

return this.iamClient
.putUserPolicy({
UserName: this.serviceName,
PolicyName: this.serviceName,
PolicyDocument: JSON.stringify(doc),
})
.promise()
.then(() => true);
await this.iamClient.send(new PutUserPolicyCommand({
UserName: this.serviceName,
PolicyName: this.serviceName,
PolicyDocument: JSON.stringify(doc),
}));
return true;
}

conflicts() {
Expand All @@ -158,22 +158,18 @@ class AccessKeyHandler extends BaseHandler {
async collect() {
// if at least one key already exists, the script won't create a new key
// and will display the list of existing keys
return this.iamClient
.listAccessKeys({
UserName: this.serviceName,
MaxItems: 100,
})
.promise()
.then(res => res.AccessKeyMetadata);
const res = await this.iamClient.send(new ListAccessKeysCommand({
UserName: this.serviceName,
MaxItems: 100,
}));
return res.AccessKeyMetadata;
}

async create() {
return this.iamClient
.createAccessKey({
UserName: this.serviceName,
})
.promise()
.then(res => res.AccessKey);
const res = await this.iamClient.send(new CreateAccessKeyCommand({
UserName: this.serviceName,
}));
return res.AccessKey;
}

conflicts() {
Expand All @@ -185,7 +181,7 @@ function collectResource(v, done) {
v.collect()
.then(res => done(null, res))
.catch((err) => {
if (err.code === 'NoSuchEntity') {
if (err.name === 'NoSuchEntity') {
return done();
}

Expand Down
18 changes: 10 additions & 8 deletions docs/CLIENTS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,16 @@ JavaScript

.. code:: javascript

const AWS = require('aws-sdk');

const s3 = new AWS.S3({
accessKeyId: 'accessKey1',
secretAccessKey: 'verySecretKey1',
endpoint: 'localhost:8000',
sslEnabled: false,
s3ForcePathStyle: true,
const { S3Client } = require('@aws-sdk/client-s3');

const s3 = new S3Client({
region: 'us-east-1',
endpoint: 'http://localhost:8000',
forcePathStyle: true,
credentials: {
accessKeyId: 'accessKey1',
secretAccessKey: 'verySecretKey1',
},
});

JAVA
Expand Down
80 changes: 40 additions & 40 deletions docs/GETTING_STARTED.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,10 +247,13 @@ if you are using the AWS SDK for JavaScript, instantiate your client like this:

.. code:: js

const s3 = new aws.S3({
endpoint: 'http://127.0.0.1:8000',
s3ForcePathStyle: true,
});
const { S3Client } = require('@aws-sdk/client-s3');

const s3 = new S3Client({
endpoint: 'http://127.0.0.1:8000',
forcePathStyle: true,
region: 'us-east-1',
});

Setting Your Own Access and Secret Key Pairs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -379,47 +382,44 @@ SSL certificates.
Test the Config
^^^^^^^^^^^^^^^

If aws-sdk is not installed, run ``$> yarn install aws-sdk``.
If the AWS SDK for JavaScript v3 packages are not installed locally, run ``$> yarn add @aws-sdk/client-s3 @aws-sdk/node-http-handler``.

Paste the following script into a file named "test.js":

.. code:: js

const AWS = require('aws-sdk');
const fs = require('fs');
const https = require('https');

const httpOptions = {
agent: new https.Agent({
// path on your host of the self-signed certificate
ca: fs.readFileSync('./ca.crt', 'ascii'),
}),
};

const s3 = new AWS.S3({
httpOptions,
accessKeyId: 'accessKey1',
secretAccessKey: 'verySecretKey1',
// The endpoint must be s3.scality.test, else SSL will not work
endpoint: 'https://s3.scality.test:8000',
sslEnabled: true,
// With this setup, you must use path-style bucket access
s3ForcePathStyle: true,
});

const bucket = 'cocoriko';

s3.createBucket({ Bucket: bucket }, err => {
if (err) {
return console.log('err createBucket', err);
}
return s3.deleteBucket({ Bucket: bucket }, err => {
if (err) {
return console.log('err deleteBucket', err);
}
return console.log('SSL is cool!');
});
});
const { S3Client, CreateBucketCommand, DeleteBucketCommand } = require('@aws-sdk/client-s3');
const { NodeHttpHandler } = require('@aws-sdk/node-http-handler');
const fs = require('fs');
const https = require('https');

const httpsAgent = new https.Agent({
// path on your host of the self-signed certificate
ca: fs.readFileSync('./ca.crt', 'ascii'),
});

const s3 = new S3Client({
requestHandler: new NodeHttpHandler({ httpsAgent }),
credentials: {
accessKeyId: 'accessKey1',
secretAccessKey: 'verySecretKey1',
},
endpoint: 'https://s3.scality.test:8000',
forcePathStyle: true,
region: 'us-east-1',
});

const bucket = 'cocoriko';

(async () => {
try {
await s3.send(new CreateBucketCommand({ Bucket: bucket }));
await s3.send(new DeleteBucketCommand({ Bucket: bucket }));
console.log('SSL is cool!');
} catch (err) {
console.error('error running sample', err);
}
})();

Now run this script with:

Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenko/cloudserver",
"version": "9.3.0",
"version": "9.3.1",
"description": "Zenko CloudServer, an open-source Node.js implementation of a server handling the Amazon S3 protocol",
"main": "index.js",
"engines": {
Expand Down Expand Up @@ -32,7 +32,6 @@
"@smithy/node-http-handler": "^3.0.0",
"arsenal": "git+https://github.com/scality/arsenal#8.3.1",
"async": "2.6.4",
"aws-sdk": "^2.1692.0",
"bucketclient": "scality/bucketclient#8.2.7",
"bufferutil": "^4.0.8",
"commander": "^12.1.0",
Expand Down
73 changes: 48 additions & 25 deletions tests/functional/aws-node-sdk/test/rateLimit/tooling.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,65 @@
const nodeFetch = require('node-fetch');
const AWS = require('aws-sdk');
const { SignatureV4 } = require('@aws-sdk/signature-v4');
const { HttpRequest } = require('@aws-sdk/protocol-http');
const { Sha256 } = require('@aws-crypto/sha256-js');
const xml2js = require('xml2js');
const { URL } = require('url');
const { getCredentials } = require('../support/credentials');

const { config } = require('../../../../../lib/Config');

const skipIfRateLimitDisabled = config.rateLimiting.enabled ? describe : describe.skip;

function buildHttpRequest(method, host, rawPath, body = '') {
const endpoint = new URL(`http://${host}`);
const target = new URL(rawPath, `http://${host}`);

const query = {};
target.searchParams.forEach((value, key) => {
if (Object.prototype.hasOwnProperty.call(query, key)) {
const current = query[key];
query[key] = Array.isArray(current) ? current.concat(value) : [current, value];
} else {
query[key] = value ?? '';
}
});

const request = new HttpRequest({
method: method.toUpperCase(),
protocol: endpoint.protocol,
hostname: endpoint.hostname,
port: endpoint.port ? Number(endpoint.port) : undefined,
path: target.pathname,
query: Object.keys(query).length ? query : undefined,
headers: {
host,
},
body: body || undefined,
});

return { request, target };
}

async function sendRateLimitRequest(method, host, path, body = '') {
const service = 's3';
const endpoint = new AWS.Endpoint(host);

const request = new AWS.HttpRequest(endpoint);
request.method = method.toUpperCase();
request.path = path;
request.body = body;
request.headers.Host = host;
request.headers['X-Amz-Date'] = new Date().toISOString().replace(/[:\-]|\.\d{3}/g, '');
const sha256hash = AWS.util.crypto.sha256(request.body || '', 'hex');
request.headers['X-Amz-Content-SHA256'] = sha256hash;
request.region = 'us-east-1';

const signer = new AWS.Signers.V4(request, service);
const { request, target } = buildHttpRequest(method, host, path, body);

const credentials = getCredentials('lisa');
const awsCredentials = new AWS.Credentials(
credentials.accessKeyId,
credentials.secretAccessKey
);
signer.addAuthorization(awsCredentials, new Date());
const signer = new SignatureV4({
credentials,
region: 'us-east-1',
service: 's3',
sha256: Sha256,
});
const signedRequest = await signer.sign(request);

const url = `http://${host}${path}`;
const url = target.href;
const options = {
method: request.method,
headers: request.headers,
method: signedRequest.method,
headers: signedRequest.headers,
};

if (method !== 'GET' && method !== 'DELETE') {
options.body = request.body;
if (signedRequest.body && method !== 'GET' && method !== 'DELETE') {
options.body = signedRequest.body;
}

const response = await nodeFetch(url, options);
Expand Down
Loading
Loading