Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
61 changes: 47 additions & 14 deletions x-pack/plugins/fleet/server/routes/epm/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { TypeOf } from '@kbn/config-schema';
import mime from 'mime-types';
import path from 'path';
import { RequestHandler, ResponseHeaders, KnownHeaders } from 'src/core/server';
import {
GetInfoResponse,
Expand Down Expand Up @@ -43,6 +45,8 @@ import {
import { defaultIngestErrorHandler, ingestErrorToResponseOptions } from '../../errors';
import { splitPkgKey } from '../../services/epm/registry';
import { licenseService } from '../../services';
import { getArchiveEntry } from '../../services/epm/archive/cache';
import { bufferToStream } from '../../services/epm/streams';

export const getCategoriesHandler: RequestHandler<
undefined,
Expand Down Expand Up @@ -102,22 +106,51 @@ export const getFileHandler: RequestHandler<TypeOf<typeof GetFileRequestSchema.p
) => {
try {
const { pkgName, pkgVersion, filePath } = request.params;
const registryResponse = await getFile(`/package/${pkgName}/${pkgVersion}/${filePath}`);

const headersToProxy: KnownHeaders[] = ['content-type', 'cache-control'];
const proxiedHeaders = headersToProxy.reduce((headers, knownHeader) => {
const value = registryResponse.headers.get(knownHeader);
if (value !== null) {
headers[knownHeader] = value;
const savedObjectsClient = context.core.savedObjects.client;
const savedObject = await getInstallationObject({ savedObjectsClient, pkgName });
const pkgInstallSource = savedObject?.attributes.install_source;
// TODO: when package storage is available, remove installSource check and check cache and storage, remove registry call
if (pkgInstallSource === 'upload') {
const headerContentType = mime.contentType(path.extname(filePath));
if (!headerContentType) {
return response.custom({
body: `unknown content type for file: ${filePath}`,
statusCode: 400,
});
}
return headers;
}, {} as ResponseHeaders);
const archiveFile = getArchiveEntry(`${pkgName}-${pkgVersion}/${filePath}`);
if (!archiveFile) {
return response.custom({
body: `uploaded package file not found: ${filePath}`,
statusCode: 404,
});
}
const headers: ResponseHeaders = {
'cache-control': 'max-age=10, public',
Comment thread
neptunian marked this conversation as resolved.
Outdated
'content-type': headerContentType,
};
return response.custom({
body: bufferToStream(archiveFile),
statusCode: 200,
headers,
});
} else {
const registryResponse = await getFile(`/package/${pkgName}/${pkgVersion}/${filePath}`);
const headersToProxy: KnownHeaders[] = ['content-type', 'cache-control'];
const proxiedHeaders = headersToProxy.reduce((headers, knownHeader) => {
const value = registryResponse.headers.get(knownHeader);
if (value !== null) {
headers[knownHeader] = value;
}
return headers;
}, {} as ResponseHeaders);

return response.custom({
body: registryResponse.body,
statusCode: registryResponse.status,
headers: proxiedHeaders,
});
return response.custom({
body: registryResponse.body,
statusCode: registryResponse.status,
headers: proxiedHeaders,
});
}
} catch (error) {
return defaultIngestErrorHandler({ error, response });
}
Expand Down
204 changes: 137 additions & 67 deletions x-pack/test/fleet_api_integration/apis/epm/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
* you may not use this file except in compliance with the Elastic License.
*/

import fs from 'fs';
import path from 'path';
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../api_integration/ftr_provider_context';
import { warnAndSkipTest } from '../../helpers';

Expand All @@ -14,79 +17,146 @@ export default function ({ getService }: FtrProviderContext) {

const server = dockerServers.get('registry');
describe('EPM - package file', () => {
it('fetches a .png screenshot image', async function () {
if (server.enabled) {
await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/img/screenshots/metricbeat_dashboard.png')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'image/png')
.expect(200);
} else {
warnAndSkipTest(this, log);
}
});
describe('it gets files from registry', () => {
it('fetches a .png screenshot image', async function () {
if (server.enabled) {
const res = await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/img/screenshots/metricbeat_dashboard.png')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'image/png')
.expect(200);
expect(Buffer.isBuffer(res.body)).to.equal(true);
} else {
warnAndSkipTest(this, log);
}
});

it('fetches an .svg icon image', async function () {
if (server.enabled) {
await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/img/logo.svg')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'image/svg+xml')
.expect(200);
} else {
warnAndSkipTest(this, log);
}
});
it('fetches an .svg icon image', async function () {
if (server.enabled) {
const res = await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/img/logo.svg')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'image/svg+xml')
.expect(200);
expect(Buffer.isBuffer(res.body)).to.equal(true);
} else {
warnAndSkipTest(this, log);
}
});

it('fetches a .json kibana visualization file', async function () {
if (server.enabled) {
await supertest
.get(
'/api/fleet/epm/packages/filetest/0.1.0/kibana/visualization/sample_visualization.json'
)
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200);
} else {
warnAndSkipTest(this, log);
}
});
it('fetches a .json kibana visualization file', async function () {
if (server.enabled) {
const res = await supertest
.get(
'/api/fleet/epm/packages/filetest/0.1.0/kibana/visualization/sample_visualization.json'
)
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200);
expect(typeof res.body).to.equal('object');
} else {
warnAndSkipTest(this, log);
}
});

it('fetches a .json kibana dashboard file', async function () {
if (server.enabled) {
await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/kibana/dashboard/sample_dashboard.json')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200);
} else {
warnAndSkipTest(this, log);
}
});
it('fetches a .json kibana dashboard file', async function () {
if (server.enabled) {
const res = await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/kibana/dashboard/sample_dashboard.json')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200);
expect(typeof res.body).to.equal('object');
} else {
warnAndSkipTest(this, log);
}
});

it('fetches a .json search file', async function () {
if (server.enabled) {
it('fetches a .json search file', async function () {
if (server.enabled) {
const res = await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/kibana/search/sample_search.json')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200);
expect(typeof res.body).to.equal('object');
} else {
warnAndSkipTest(this, log);
}
});
});
describe('it gets files from an uploaded package', () => {
before(async () => {
if (!server.enabled) return;
const testPkgArchiveTgz = path.join(
path.dirname(__filename),
'../fixtures/direct_upload_packages/apache_0.1.4.tar.gz'
);
const buf = fs.readFileSync(testPkgArchiveTgz);
await supertest
.get('/api/fleet/epm/packages/filetest/0.1.0/kibana/search/sample_search.json')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'application/json; charset=utf-8')
.post(`/api/fleet/epm/packages`)
.set('kbn-xsrf', 'xxxx')
.type('application/gzip')
.send(buf)
Comment thread
neptunian marked this conversation as resolved.
Outdated
.expect(200);
} else {
warnAndSkipTest(this, log);
}
});
after(async () => {
if (!server.enabled) return;
await supertest.delete(`/api/fleet/epm/packages/apache-0.1.4`).set('kbn-xsrf', 'xxxx');
});
it('fetches a .png screenshot image', async function () {
if (server.enabled) {
const res = await supertest
.get('/api/fleet/epm/packages/apache/0.1.4/img/kibana-apache-new.png')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'image/png')
.expect(200);
Comment thread
neptunian marked this conversation as resolved.
Outdated
expect(Buffer.isBuffer(res.body)).to.equal(true);
} else {
warnAndSkipTest(this, log);
}
});

it('fetches a .json kibana dashboard file', async function () {
if (server.enabled) {
const res = await supertest
.get(
'/api/fleet/epm/packages/apache/0.1.4/kibana/dashboard/apache-Logs-Apache-Dashboard-ecs-new.json'
)
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200);
expect(typeof res.body).to.equal('object');
} else {
warnAndSkipTest(this, log);
}
});

it('fetches a README file', async function () {
if (server.enabled) {
const res = await supertest
.get('/api/fleet/epm/packages/apache/0.1.4/docs/README.md')
.set('kbn-xsrf', 'xxx')
.expect('Content-Type', 'text/markdown; charset=utf-8')
.expect(200);
expect(res.text).to.equal('# Apache Uploaded Test Integration');
} else {
warnAndSkipTest(this, log);
}
});
});
});

// Disabled for now as we don't serve prebuilt index patterns in current packages.
// it('fetches an .json index pattern file', async function () {
// if (server.enabled) {
// await supertest
// .get('/api/fleet/epm/packages/filetest/0.1.0/kibana/index-pattern/sample-*.json')
// .set('kbn-xsrf', 'xxx')
// .expect('Content-Type', 'application/json; charset=utf-8')
// .expect(200);
// } else {
// warnAndSkipTest(this, log);
// }
// });
// Disabled for now as we don't serve prebuilt index patterns in current packages.
// it('fetches an .json index pattern file', async function () {
// if (server.enabled) {
// await supertest
// .get('/api/fleet/epm/packages/filetest/0.1.0/kibana/index-pattern/sample-*.json')
// .set('kbn-xsrf', 'xxx')
// .expect('Content-Type', 'application/json; charset=utf-8')
// .expect(200);
// } else {
// warnAndSkipTest(this, log);
// }
// });
});
}
Binary file not shown.
Binary file not shown.