Compare commits
3 Commits
developmen
...
epic/ZENKO
Author | SHA1 | Date |
---|---|---|
bbuchanan9 | 8176560b2e | |
bbuchanan9 | d6752875e6 | |
bbuchanan9 | 0cf63d6fe3 |
|
@ -0,0 +1 @@
|
|||
node_modules
|
17
Dockerfile
17
Dockerfile
|
@ -1,19 +1,16 @@
|
|||
FROM node:6-slim
|
||||
FROM node:8-slim
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY package.json /usr/src/app
|
||||
COPY . /usr/src/app
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y jq --no-install-recommends \
|
||||
&& npm install --production \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get install git -y \
|
||||
&& apt install build-essential -y \
|
||||
&& apt-get install python -y \
|
||||
&& apt-get install g++ -y \
|
||||
&& npm cache clear --force \
|
||||
&& rm -rf ~/.node-gyp \
|
||||
&& rm -rf /tmp/npm-*
|
||||
|
||||
# Keep the .git directory in order to properly report version
|
||||
COPY . /usr/src/app
|
||||
&& npm install --production
|
||||
|
||||
ENTRYPOINT ["/usr/src/app/docker-entrypoint.sh"]
|
||||
CMD [ "npm", "start" ]
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
# Quickstart
|
||||
|
||||
## Server
|
||||
|
||||
### Using Docker (~5 minutes)
|
||||
|
||||
1. Build the image:
|
||||
```
|
||||
$ docker build --tag utapi .
|
||||
Sending build context to Docker daemon 10.79MB
|
||||
Step 1/7 : FROM node:8-slim
|
||||
---> bce75035da07
|
||||
...
|
||||
Successfully built 5699ea8e7dec
|
||||
```
|
||||
|
||||
2. Run the image:
|
||||
```
|
||||
$ docker run --publish 8100:8100 --detach utapi
|
||||
25fea1a990b18e7f1f6c76cc5d0c5d564fd6bffb87e1acf5f724db16d602a5b5
|
||||
```
|
||||
|
||||
You should now have a Utapi server running at port 8100.
|
||||
|
||||
### Using NPM (~1 minute)
|
||||
|
||||
```
|
||||
$ npm start
|
||||
> utapi@8.0.0 start /Users/bennettbuchanan/repos/scality/utapi
|
||||
> node start-server.js
|
||||
|
||||
{"name":"Utapi","time":1562008743439,"id":0,"childPid":55156,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743474,"id":5,"childPid":55161,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743493,"id":2,"childPid":55158,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743495,"id":1,"childPid":55157,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743556,"id":4,"childPid":55160,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743575,"id":3,"childPid":55159,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743582,"id":7,"childPid":55163,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743606,"id":9,"childPid":55165,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743619,"id":6,"childPid":55162,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
{"name":"Utapi","time":1562008743639,"id":8,"childPid":55164,"level":"info","message":"Worker started","hostname":"Bennetts-MacBook-Pro-2.local","pid":55155}
|
||||
```
|
||||
|
||||
## Client
|
||||
|
||||
See examples in examples/
|
||||
|
||||
```js
|
||||
const http = require('http');
|
||||
|
||||
const bucketName = 'test-bucket';
|
||||
|
||||
// Get the start and end times for a range of one month.
|
||||
const start = new Date(2016, 1, 1, 0, 0, 0, 0).getTime();
|
||||
const end = new Date(2016, 2, 1, 0, 0, 0, 0).getTime() - 1;
|
||||
const requestBody = JSON.stringify({
|
||||
buckets: [bucketName],
|
||||
timeRange: [start, end],
|
||||
});
|
||||
const header = {
|
||||
host: 'localhost',
|
||||
port: 8100,
|
||||
method: 'POST',
|
||||
service: 's3',
|
||||
path: '/buckets?Action=ListMetrics',
|
||||
signQuery: false,
|
||||
body: requestBody,
|
||||
};
|
||||
const request = http.request(header, response => {
|
||||
const body = [];
|
||||
response.on('data', chunk => body.push(chunk));
|
||||
response.on('end', () => {
|
||||
console.log(JSON.parse(body.join('')));
|
||||
});
|
||||
});
|
||||
request.on('error', e => process.stdout.write(`error: ${e.message}\n`));
|
||||
request.write(requestBody);
|
||||
request.end();
|
||||
```
|
12
README.md
12
README.md
|
@ -7,10 +7,22 @@
|
|||
|
||||
Service Utilization API for tracking resource usage and metrics reporting
|
||||
|
||||
## Quickstart
|
||||
|
||||
Please see the [quickstart](/DESIGN.md) guide.
|
||||
|
||||
## Design
|
||||
|
||||
Please refer to the [design](/DESIGN.md) for more information.
|
||||
|
||||
To run the server without using the [Signature Version 4 Signing Process](
|
||||
https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html), set the
|
||||
environment variable `NO_AUTH` to `'true'`:
|
||||
|
||||
```
|
||||
NO_AUTH=true npm start
|
||||
```
|
||||
|
||||
## Client
|
||||
|
||||
The module exposes a client, named UtapiClient. Projects can use this client to
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"port": 8100,
|
||||
"workers": 10,
|
||||
"noauth": false,
|
||||
"healthChecks": {
|
||||
"allowFrom": ["127.0.0.1/8", "::1"]
|
||||
},
|
||||
|
|
|
@ -39,6 +39,10 @@ if [[ "$HEALTHCHECKS_ALLOWFROM" ]]; then
|
|||
JQ_FILTERS_CONFIG="$JQ_FILTERS_CONFIG | .healthChecks.allowFrom=[\"$HEALTHCHECKS_ALLOWFROM\"]"
|
||||
fi
|
||||
|
||||
if [[ "$NO_AUTH" ]]; then
|
||||
JQ_FILTERS_CONFIG="$JQ_FILTERS_CONFIG | .noauth=[\"$NO_AUTH\"]"
|
||||
fi
|
||||
|
||||
if [[ $JQ_FILTERS_CONFIG != "." ]]; then
|
||||
jq "$JQ_FILTERS_CONFIG" config.json > config.json.tmp
|
||||
mv config.json.tmp config.json
|
||||
|
|
|
@ -44,6 +44,16 @@ class Config {
|
|||
this.workers = config.workers;
|
||||
}
|
||||
|
||||
this.noauth = false;
|
||||
if (config.noauth !== undefined) {
|
||||
assert(typeof config.noauth === 'boolean',
|
||||
'bad config: noauth must be a boolean');
|
||||
this.noauth = config.noauth;
|
||||
}
|
||||
if (process.env.NO_AUTH !== undefined) {
|
||||
this.noauth = process.env.NO_AUTH;
|
||||
}
|
||||
|
||||
this.log = { logLevel: 'debug', dumpLevel: 'error' };
|
||||
if (config.log !== undefined) {
|
||||
if (config.log.logLevel !== undefined) {
|
||||
|
|
|
@ -3,6 +3,7 @@ const url = require('url');
|
|||
const { auth, errors, policies } = require('arsenal');
|
||||
const safeJsonParse = require('../utils/safeJsonParse');
|
||||
const Vault = require('../lib/Vault');
|
||||
const config = require('../lib/Config');
|
||||
|
||||
class Router {
|
||||
|
||||
|
@ -199,6 +200,10 @@ class Router {
|
|||
*/
|
||||
_authSquared(utapiRequest, cb) {
|
||||
const log = utapiRequest.getLog();
|
||||
if (config.noauth === 'true') {
|
||||
log.trace('skipping authentication check');
|
||||
return process.nextTick(() => cb());
|
||||
}
|
||||
const authHeader = utapiRequest.getRequestHeaders().authorization;
|
||||
if (!authHeader || !authHeader.startsWith('AWS4')) {
|
||||
log.trace('missing auth header for v4 auth');
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import assert from 'assert';
|
||||
import { errors } from 'arsenal';
|
||||
import { Logger } from 'werelogs';
|
||||
import config from '../../src/lib/Config';
|
||||
import Router from '../../src/router/Router';
|
||||
import UtapiRequest from '../../src/lib/UtapiRequest';
|
||||
|
||||
describe('Router', () => {
|
||||
const router = new Router(config);
|
||||
|
||||
describe('::_authSquared', () => {
|
||||
const log = new Logger('UtapiRequest');
|
||||
const request = new UtapiRequest().setLog(log);
|
||||
|
||||
describe('with unauthorized request', () => {
|
||||
before(() => {
|
||||
const incomingMessage = {
|
||||
headers: {
|
||||
authorization: false,
|
||||
},
|
||||
};
|
||||
request.setRequest(incomingMessage);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
request.setRequest(null);
|
||||
});
|
||||
|
||||
it('should return InvalidRequest error', done => {
|
||||
const expected = errors.InvalidRequest
|
||||
.customizeDescription('Must use Auth V4 for this request.');
|
||||
router._authSquared(request, err => {
|
||||
assert.deepStrictEqual(expected, err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with NO_AUTH=true', () => {
|
||||
before(() => {
|
||||
process.env.NO_AUTH = 'true';
|
||||
});
|
||||
|
||||
after(() => {
|
||||
process.env.NO_AUTH = 'false';
|
||||
});
|
||||
|
||||
it('should not return InvalidRequest error', done => {
|
||||
router._authSquared(request, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue