Skip to content

Commit

Permalink
Adding new security changes made for PDF into new PNG code
Browse files Browse the repository at this point in the history
  • Loading branch information
bgaddis56 committed Oct 31, 2018
1 parent d6368f6 commit eb40541
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 167 deletions.
Expand Up @@ -16,18 +16,15 @@ function createJobFn(server) {
relativeUrl,
browserTimezone,
layout
}, headers, serializedSession, request) {
}, headers, request) {
const serializedEncryptedHeaders = await crypto.encrypt(headers);
const encryptedSerializedSession = await crypto.encrypt(serializedSession);


return {
type: objectType,
title: title,
relativeUrl,
headers: serializedEncryptedHeaders,
browserTimezone,
session: encryptedSerializedSession,
layout,
basePath: request.getBasePath(),
forceNow: new Date().toISOString(),
Expand Down

This file was deleted.

Expand Up @@ -5,13 +5,25 @@
*/

import url from 'url';
import cookie from 'cookie';
import * as Rx from 'rxjs';
import { mergeMap, catchError, map, takeUntil } from 'rxjs/operators';
import { oncePerServer } from '../../../../server/lib/once_per_server';
import { generatePngObservableFactory } from '../lib/generate_png';
import { cryptoFactory } from '../../../../server/lib/crypto';
import { getAbsoluteUrlFactory } from '../../../common/execute_job/get_absolute_url';
import { omit } from 'lodash';

const KBN_SCREENSHOT_HEADER_BLACKLIST = [
'accept-encoding',
'content-length',
'content-type',
'host',
'referer',
// `Transfer-Encoding` is hop-by-hop header that is meaningful
// only for a single transport-level connection, and shouldn't
// be stored by caches or forwarded by proxies.
'transfer-encoding',
];

function executeJobFn(server) {
const generatePngObservable = generatePngObservableFactory(server);
Expand All @@ -24,8 +36,12 @@ function executeJobFn(server) {
return { job, decryptedHeaders };
};

const getSavedObjectAbsoluteUrl = (job, relativeUrl) => {
const omitBlacklistedHeaders = ({ job, decryptedHeaders }) => {
const filteredHeaders = omit(decryptedHeaders, KBN_SCREENSHOT_HEADER_BLACKLIST);
return { job, filteredHeaders };
};

const getSavedObjectAbsoluteUrl = (job, relativeUrl) => {
if (relativeUrl) {
const { pathname: path, hash, search } = url.parse(relativeUrl);
return getAbsoluteUrl({ basePath: job.basePath, path, hash, search });
Expand All @@ -34,62 +50,26 @@ function executeJobFn(server) {
throw new Error(`Unable to generate report. Url is not defined.`);
};

const getSerializedSession = async ({ job, decryptedHeaders }) => {
if (!server.plugins.security) {
job.serializedSession = null;
return { decryptedHeaders, job };
}

if (job.session) {
try {
job.serializedSession = await crypto.decrypt(job.session);
return { decryptedHeaders, job };
} catch (err) {
throw new Error('Failed to decrypt report job data. Please re-generate this report.');
const getConditionalHeaders = ({ job, filteredHeaders }) => {
const conditionalHeaders = {
headers: filteredHeaders,
conditions: {
hostname: config.get('xpack.reporting.kibanaServer.hostname') || config.get('server.host'),
port: config.get('xpack.reporting.kibanaServer.port') || config.get('server.port'),
basePath: config.get('server.basePath'),
protocol: config.get('xpack.reporting.kibanaServer.protocol') || server.info.protocol,
}
}

const cookies = decryptedHeaders.cookie ? cookie.parse(decryptedHeaders.cookie) : null;
if (cookies === null) {
job.serializedSession = null;
return { decryptedHeaders, job };
}
};

const cookieName = server.plugins.security.getSessionCookieOptions().name;
if (!cookieName) {
throw new Error('Unable to determine the session cookie name');
}

job.serializedSession = cookies[cookieName];

return { decryptedHeaders, job };
};

const getSessionCookie = async ({ job, logo }) => {
if (!job.serializedSession) {
return { job, logo, sessionCookie: null };
}

const cookieOptions = await server.plugins.security.getSessionCookieOptions();
const { httpOnly, name, path, secure } = cookieOptions;

return { job, logo, sessionCookie: {
domain: config.get('xpack.reporting.kibanaServer.hostname') || config.get('server.host'),
httpOnly,
name,
path,
sameSite: 'Strict',
secure,
value: job.serializedSession,
} };
return { job, conditionalHeaders };
};

const addForceNowQuerystring = async ({ job, sessionCookie }) => {
const addForceNowQuerystring = async ({ job, conditionalHeaders }) => {

const jobUrl = getSavedObjectAbsoluteUrl(job, job.relativeUrl);

if (!job.forceNow) {
return { job, sessionCookie, hashUrl: jobUrl };
return { job, conditionalHeaders, hashUrl: jobUrl };
}

const parsed = url.parse(jobUrl, true);
Expand All @@ -107,19 +87,19 @@ function executeJobFn(server) {
...parsed,
hash: transformedHash
});
//});
return { job, sessionCookie, hashUrl };

return { job, conditionalHeaders, hashUrl };
};

return function executeJob(jobToExecute, cancellationToken) {
const process$ = Rx.of(jobToExecute).pipe(
mergeMap(decryptJobHeaders),
catchError(() => Rx.throwError('Failed to decrypt report job data. Please re-generate this report.')),
mergeMap(getSerializedSession),
mergeMap(getSessionCookie),
map(omitBlacklistedHeaders),
map(getConditionalHeaders),
mergeMap(addForceNowQuerystring),
mergeMap(({ job, sessionCookie, hashUrl }) => {
return generatePngObservable(hashUrl, job.browserTimezone, sessionCookie, job.layout);
mergeMap(({ job, conditionalHeaders, hashUrl }) => {
return generatePngObservable(hashUrl, job.browserTimezone, conditionalHeaders, job.layout);
}),
map(buffer => ({
content_type: 'image/png',
Expand Down

0 comments on commit eb40541

Please sign in to comment.