Compare commits

..

4 Commits

Author SHA1 Message Date
Rainer Killinger
2982c8598e 1.4.0 2022-11-09 16:55:43 +01:00
Rainer Killinger
0486d733a1 refactor: update dependencies 2022-11-09 16:46:31 +01:00
Rainer Killinger
8c49c31760 feat: add support for log aggregators 2022-11-09 16:28:21 +01:00
Rainer Killinger
8ec8fb3386 docs: update changelog 2022-08-22 17:04:50 +02:00
10 changed files with 444 additions and 361 deletions

View File

@@ -1,3 +1,7 @@
# [1.3.0](https://gitlab.com/openstapps/proxy/compare/v1.2.0...v1.3.0) (2022-08-22)
# [1.2.0](https://gitlab.com/openstapps/proxy/compare/v1.1.0...v1.2.0) (2022-06-08) # [1.2.0](https://gitlab.com/openstapps/proxy/compare/v1.1.0...v1.2.0) (2022-06-08)

View File

@@ -18,6 +18,7 @@ import {ConfigFile} from '../src/common';
const config: ConfigFile = { const config: ConfigFile = {
activeVersions: ['1\\.0\\.\\d+', '2\\.0\\.\\d+'], activeVersions: ['1\\.0\\.\\d+', '2\\.0\\.\\d+'],
hiddenRoutes: ['/bulk'], hiddenRoutes: ['/bulk'],
logFormat: 'default',
metrics: false, metrics: false,
outdatedVersions: ['0\\.8\\.\\d+', '0\\.5\\.\\d+', '0\\.6\\.\\d+', '0\\.7\\.\\d+'], outdatedVersions: ['0\\.8\\.\\d+', '0\\.5\\.\\d+', '0\\.6\\.\\d+', '0\\.7\\.\\d+'],
output: '/etc/nginx/http.d/default.conf', output: '/etc/nginx/http.d/default.conf',

View File

@@ -0,0 +1,32 @@
map $time_iso8601 $time_iso8601_dateTime {
~([^+]+) $1;
}
map $time_iso8601 $time_iso8601_TZ {
~\+([0-9:]+)$ $1;
}
map $msec $millisec {
~\.([0-9]+)$ $1;
}
log_format json escape=json '{ "nginx_timestamp": "$time_iso8601_dateTime.$millisec+$time_iso8601_TZ", '
'"remote_addr": "$remote_addr", '
'"connection": "$connection", '
'"connection_requests": $connection_requests, '
'"pipe": "$pipe", '
'"body_bytes_sent": $body_bytes_sent, '
'"request_length": $request_length, '
'"request_time": $request_time, '
'"response_status": $status, '
'"request": "$request", '
'"request_method": "$request_method", '
'"host": "$host", '
'"upstream_cache_status": "$upstream_cache_status", '
'"upstream_addr": "$upstream_addr", '
'"http_x_forwarded_for": "$http_x_forwarded_for", '
'"http_referrer": "$http_referer", '
'"http_user_agent": "$http_user_agent", '
'"http_version": "$server_protocol", '
'"remote_user": "$remote_user", '
'"http_x_forwarded_proto": "$http_x_forwarded_proto", '
'"upstream_response_time": "$upstream_response_time", '
'"nginx_access": true }';

View File

@@ -5,9 +5,10 @@ map $status $omitOKs {
server { server {
listen 8080; listen 8080;
access_log /dev/stdout combined if=$omitOKs; error_log stderr;
access_log /dev/stdout {{{ logFormat }}} if=$omitOKs;
location /metrics { location /metrics {
vhost_traffic_status_display; vhost_traffic_status_display;
vhost_traffic_status_display_format prometheus; vhost_traffic_status_display_format prometheus;
} }
} }

View File

@@ -1,3 +1,5 @@
{{{ logFormatters }}}
{{{ metrics }}} {{{ metrics }}}
{{{ dockerVersionMap }}} {{{ dockerVersionMap }}}
@@ -19,6 +21,9 @@ map $isRateLimited $rateLimit {
limit_req_zone $rateLimit zone=customstappslimit:10m rate=20r/s; limit_req_zone $rateLimit zone=customstappslimit:10m rate=20r/s;
server { server {
error_log stderr;
access_log /dev/stdout {{{ logFormat }}};
{{{ listener }}} {{{ listener }}}
{{{ visibleRoutes }}} {{{ visibleRoutes }}}

675
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,40 +1,40 @@
{ {
"name": "@openstapps/proxy", "name": "@openstapps/proxy",
"version": "1.3.0", "version": "1.4.0",
"description": "NGINX proxy that is dynamically configured by a Node.js script", "description": "NGINX proxy that is dynamically configured by a Node.js script",
"main": "./lib/cli.js", "main": "./lib/cli.js",
"dependencies": { "dependencies": {
"@openstapps/logger": "1.0.0", "@openstapps/logger": "1.1.1",
"@types/config": "3.3.0", "@types/config": "3.3.0",
"@types/dockerode": "3.3.9", "@types/dockerode": "3.3.12",
"@types/node": "14.18.24", "@types/node": "14.18.24",
"@types/sha1": "1.1.3", "@types/sha1": "1.1.3",
"config": "3.3.7", "config": "3.3.8",
"dockerode": "3.3.3", "dockerode": "3.3.4",
"is-cidr": "4.0.2", "is-cidr": "4.0.2",
"mustache": "4.2.0", "mustache": "4.2.0",
"node-port-scanner": "3.0.1", "node-port-scanner": "3.0.1",
"semver": "7.3.7" "semver": "7.3.8"
}, },
"devDependencies": { "devDependencies": {
"@openstapps/configuration": "0.33.0", "@openstapps/configuration": "0.33.0",
"@openstapps/eslint-config": "1.1.0", "@openstapps/eslint-config": "1.1.0",
"@testdeck/mocha": "0.2.0", "@testdeck/mocha": "0.3.0",
"@types/chai": "4.3.3", "@types/chai": "4.3.4",
"@types/chai-spies": "1.0.3", "@types/chai-spies": "1.0.3",
"@types/mustache": "4.2.1", "@types/mustache": "4.2.1",
"@types/proxyquire": "1.3.28", "@types/proxyquire": "1.3.28",
"@typescript-eslint/eslint-plugin": "5.33.1", "@typescript-eslint/eslint-plugin": "5.42.1",
"@typescript-eslint/parser": "5.33.1", "@typescript-eslint/parser": "5.42.1",
"chai": "4.3.6", "chai": "4.3.7",
"chai-spies": "1.0.0", "chai-spies": "1.0.0",
"conventional-changelog-cli": "2.2.2", "conventional-changelog-cli": "2.2.2",
"eslint": "8.22.0", "eslint": "8.27.0",
"eslint-config-prettier": "8.5.0", "eslint-config-prettier": "8.5.0",
"eslint-plugin-jsdoc": "39.3.6", "eslint-plugin-jsdoc": "39.6.2",
"eslint-plugin-prettier": "4.2.1", "eslint-plugin-prettier": "4.2.1",
"eslint-plugin-unicorn": "43.0.2", "eslint-plugin-unicorn": "44.0.2",
"mocha": "9.2.2", "mocha": "10.1.0",
"nyc": "15.1.0", "nyc": "15.1.0",
"prepend-file-cli": "1.0.6", "prepend-file-cli": "1.0.6",
"prettier": "2.7.1", "prettier": "2.7.1",

View File

@@ -47,6 +47,20 @@ export interface SSLFilePaths {
dhparam: string; dhparam: string;
} }
/**
* Supported log formats for config
*/
type SupportedLogFormatsKeys = 'default' | 'combined' | 'json';
/**
* Map supported formats to stings used in template view
*/
export const SupportedLogFormats: {[key in SupportedLogFormatsKeys]: string} = {
default: 'combined',
combined: 'combined',
json: 'json',
};
/** /**
* A representation of the config file * A representation of the config file
*/ */
@@ -59,10 +73,14 @@ export interface ConfigFile {
* List of hidden routes * List of hidden routes
*/ */
hiddenRoutes: string[]; hiddenRoutes: string[];
/**
* Sets log format (default or json)
*/
logFormat: SupportedLogFormatsKeys;
/** /**
* Enables metrics on /metrics route * Enables metrics on /metrics route
*/ */
metrics: boolean; metrics?: boolean;
/** /**
* List of outdated versions * List of outdated versions
*/ */
@@ -97,6 +115,14 @@ export interface TemplateView {
* Listener * Listener
*/ */
listener: string; listener: string;
/**
* Log format to use
*/
logFormat: string;
/**
* Custom Log formatters
*/
logFormatters: string;
/** /**
* Local server with listener for /metrics route * Local server with listener for /metrics route
*/ */

View File

@@ -26,6 +26,7 @@ import {
protocolHardeningParameters, protocolHardeningParameters,
SSLFilePaths, SSLFilePaths,
sslHardeningParameters, sslHardeningParameters,
SupportedLogFormats,
TemplateView, TemplateView,
} from './common'; } from './common';
@@ -244,11 +245,14 @@ ${protocolHardeningParameters}
/** /**
* Reads predefined server entry with metrics location * Reads predefined server entry with metrics location
*/ */
export async function generateMetricsServer(enableMetrics: boolean): Promise<string> { export async function generateMetricsServer(logFormat: string, enableMetrics?: boolean): Promise<string> {
if (!enableMetrics) { if (!enableMetrics) {
return ''; return '';
} }
return asyncReadFile('./fixtures/metrics.template', 'utf8');
return renderTemplate(path.join('fixtures', 'metrics.template'), {
logFormat: logFormat,
});
} }
/** /**
@@ -302,6 +306,13 @@ export async function getTemplateView(containers: Dockerode.ContainerInfo[]): Pr
}); });
}); });
const logFormattingPromise = renderTemplate(path.join('fixtures', 'logFormatters.template'), {});
const logFormat =
configFile.logFormat in SupportedLogFormats
? SupportedLogFormats[configFile.logFormat]
: SupportedLogFormats.default;
return { return {
dockerVersionMap: await generateUpstreamMap( dockerVersionMap: await generateUpstreamMap(
configFile.activeVersions, configFile.activeVersions,
@@ -310,7 +321,9 @@ export async function getTemplateView(containers: Dockerode.ContainerInfo[]): Pr
), ),
hiddenRoutes: (await Promise.all(hiddenRoutesPromises)).join(''), hiddenRoutes: (await Promise.all(hiddenRoutesPromises)).join(''),
listener: generateListener(configFile.sslFilePaths), listener: generateListener(configFile.sslFilePaths),
metrics: await generateMetricsServer(configFile.metrics), logFormat: logFormat,
logFormatters: await logFormattingPromise,
metrics: await generateMetricsServer(logFormat, configFile.metrics),
rateLimitAllowList: generateRateLimitAllowList(configFile.rateLimitAllowList), rateLimitAllowList: generateRateLimitAllowList(configFile.rateLimitAllowList),
staticRoute: await renderTemplate(path.join('fixtures', 'staticRoute.template'), {cors}), staticRoute: await renderTemplate(path.join('fixtures', 'staticRoute.template'), {cors}),
visibleRoutes: (await Promise.all(visibleRoutesPromises)).join(''), visibleRoutes: (await Promise.all(visibleRoutesPromises)).join(''),

View File

@@ -402,12 +402,12 @@ Please check if docker is running and Node.js can access the docker socket (/var
@test @test
async 'include metrics config'() { async 'include metrics config'() {
expect(await generateMetricsServer(true)).length.to.be.greaterThan(1); expect(await generateMetricsServer('test', true)).length.to.be.greaterThan(1);
} }
@test @test
async 'omit metrics config'() { async 'omit metrics config'() {
expect(await generateMetricsServer(false)).to.equal(''); expect(await generateMetricsServer('test', false)).to.equal('');
} }
@test @test