Skip to content

Commit

Permalink
initial mtls client
Browse files Browse the repository at this point in the history
  • Loading branch information
eyalkraft committed Nov 30, 2023
1 parent 10ec713 commit 9cfee43
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import axios, { AxiosRequestConfig } from 'axios';
import https from 'https';

interface TLSSettings {
rejectUnauthorized?: boolean;
cert?: string;
key?: string;
ca?: string;
}

export class SimpleAPIClient {
private baseUrl: string;
private authorization: string;
private httpsAgent: https.Agent;

constructor(baseUrl: string, username?: string, password?: string, tlsConfig: TLSSettings = {}) {
this.baseUrl = baseUrl;
this.authorization =
username && password
? `Basic ${Buffer.from(`${username}:${password}`).toString('base64')}`
: '';
this.httpsAgent = new https.Agent({
rejectUnauthorized: tlsConfig.rejectUnauthorized ?? true,
cert: tlsConfig.cert,
key: tlsConfig.key,
ca: tlsConfig.ca,
});
}

async get(endpoint: string) {
return this.request('GET', endpoint);
}

async post(endpoint: string, data: any) {
return this.request('POST', endpoint, data);
}

async put(endpoint: string, data: any) {
return this.request('PUT', endpoint, data);
}

async delete(endpoint: string) {
return this.request('DELETE', endpoint);
}

private async request(method: string, endpoint: string, data: any = null) {
const url = `${this.baseUrl}/${endpoint}`;
const headers = this.authorization ? { Authorization: this.authorization } : {};

const config: AxiosRequestConfig = {
method,
url,
data,
headers,
httpsAgent: this.httpsAgent,
};

try {
const response = await axios(config);
return response.data;
} catch (error) {
// console.error(`Error during ${method} request to ${url}: ${error.message}`);
throw error;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { readFileSync } from 'fs';
import { schema } from '@kbn/config-schema';
import { SslConfig, sslSchema } from '@kbn/server-http-tools';
import { SimpleAPIClient } from '../../agentless_service/agentless_api_client';
import { CspRouter } from '../../types';

export const defineGetAgentless = (router: CspRouter) =>
router.versioned
.get({
access: 'internal',
path: '/internal/cloud_security_posture/agentless',
options: {
tags: ['access:cloud-security-posture-read'],
},
// For dev tools https://github.com/elastic/kibana/issues/160801
enableQueryVersion: true,
})
.addVersion(
{
version: '1',
validate: {
request: {
query: schema.object({ url: schema.string() }),
},
},
},
async (context, request, response) => {
const cspContext = await context.csp;
try {
const tlsConfig = new SslConfig(
sslSchema.validate({
enabled: true,
// generate locally with https://serverfault.com/a/224127
certificate: 'config/certs/node.crt',
key: 'config/certs/node.key',
clientAuthentication: 'required',
})
);

const simpleApiClient = new SimpleAPIClient(request.query.url, 'user', 'pass', {
cert: tlsConfig.certificate,
key: tlsConfig.key,
});
// test with dev tools
// GET kbn:/internal/cloud_security_posture/agentless?apiVersion=1&url=http://certauth.cryptomix.com
const data = await simpleApiClient.get('/json/');

return response.ok({
body: data,
});
} catch (err) {
cspContext.logger.error(
`Failed to use agentless client ${err}, ${process.cwd()}. ${readFileSync(
'config/certs/node.key'
).toString()}`
);
return response.customError({
body: { message: err.message },
statusCode: err.statusCode,
});
}
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { defineGetBenchmarksRoute } from './benchmarks/benchmarks';
import { defineGetCspStatusRoute } from './status/status';
import { defineFindCspRuleTemplateRoute } from './csp_rule_template/get_csp_rule_template';
import { defineGetDetectionEngineAlertsStatus } from './detection_engine/get_detection_engine_alerts_count_by_rule_tags';
import { defineGetAgentless } from './agentless/agentless';

/**
* 1. Registers routes
Expand All @@ -40,6 +41,7 @@ export async function setupRoutes({
defineGetCspStatusRoute(router);
defineFindCspRuleTemplateRoute(router);
defineGetDetectionEngineAlertsStatus(router);
defineGetAgentless(router);

core.http.registerRouteHandlerContext<CspRequestHandlerContext, typeof PLUGIN_ID>(
PLUGIN_ID,
Expand Down

0 comments on commit 9cfee43

Please sign in to comment.