forked from extern/bruno
Merge pull request #1155 from BrandonGillis/feat/custom-ca-certificate
feat: add custom CA Certificate preference
This commit is contained in:
commit
2608ec035e
packages
bruno-app/src
bruno-electron/src
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { useRef } from 'react';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import { useFormik } from 'formik';
|
import { useFormik } from 'formik';
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector, useDispatch } from 'react-redux';
|
||||||
@ -6,13 +6,21 @@ import { savePreferences } from 'providers/ReduxStore/slices/app';
|
|||||||
import StyledWrapper from './StyledWrapper';
|
import StyledWrapper from './StyledWrapper';
|
||||||
import * as Yup from 'yup';
|
import * as Yup from 'yup';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
|
import path from 'path';
|
||||||
|
import slash from 'utils/common/slash';
|
||||||
|
import { IconTrash } from '@tabler/icons';
|
||||||
|
|
||||||
const General = ({ close }) => {
|
const General = ({ close }) => {
|
||||||
const preferences = useSelector((state) => state.app.preferences);
|
const preferences = useSelector((state) => state.app.preferences);
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
const inputFileCaCertificateRef = useRef();
|
||||||
|
|
||||||
const preferencesSchema = Yup.object().shape({
|
const preferencesSchema = Yup.object().shape({
|
||||||
sslVerification: Yup.boolean(),
|
sslVerification: Yup.boolean(),
|
||||||
|
customCaCertificate: Yup.object({
|
||||||
|
enabled: Yup.boolean(),
|
||||||
|
filePath: Yup.string().nullable()
|
||||||
|
}),
|
||||||
storeCookies: Yup.boolean(),
|
storeCookies: Yup.boolean(),
|
||||||
sendCookies: Yup.boolean(),
|
sendCookies: Yup.boolean(),
|
||||||
timeout: Yup.mixed()
|
timeout: Yup.mixed()
|
||||||
@ -31,6 +39,10 @@ const General = ({ close }) => {
|
|||||||
const formik = useFormik({
|
const formik = useFormik({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
sslVerification: preferences.request.sslVerification,
|
sslVerification: preferences.request.sslVerification,
|
||||||
|
customCaCertificate: {
|
||||||
|
enabled: get(preferences, 'request.customCaCertificate.enabled', false),
|
||||||
|
filePath: get(preferences, 'request.customCaCertificate.filePath', null)
|
||||||
|
},
|
||||||
timeout: preferences.request.timeout,
|
timeout: preferences.request.timeout,
|
||||||
storeCookies: get(preferences, 'request.storeCookies', true),
|
storeCookies: get(preferences, 'request.storeCookies', true),
|
||||||
sendCookies: get(preferences, 'request.sendCookies', true)
|
sendCookies: get(preferences, 'request.sendCookies', true)
|
||||||
@ -52,6 +64,10 @@ const General = ({ close }) => {
|
|||||||
...preferences,
|
...preferences,
|
||||||
request: {
|
request: {
|
||||||
sslVerification: newPreferences.sslVerification,
|
sslVerification: newPreferences.sslVerification,
|
||||||
|
customCaCertificate: {
|
||||||
|
enabled: newPreferences.customCaCertificate.enabled,
|
||||||
|
filePath: newPreferences.customCaCertificate.filePath
|
||||||
|
},
|
||||||
timeout: newPreferences.timeout,
|
timeout: newPreferences.timeout,
|
||||||
storeCookies: newPreferences.storeCookies,
|
storeCookies: newPreferences.storeCookies,
|
||||||
sendCookies: newPreferences.sendCookies
|
sendCookies: newPreferences.sendCookies
|
||||||
@ -64,6 +80,14 @@ const General = ({ close }) => {
|
|||||||
.catch((err) => console.log(err) && toast.error('Failed to update preferences'));
|
.catch((err) => console.log(err) && toast.error('Failed to update preferences'));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addCaCertificate = (e) => {
|
||||||
|
formik.setFieldValue('customCaCertificate.filePath', e.target.files[0]?.path);
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteCaCertificate = () => {
|
||||||
|
formik.setFieldValue('customCaCertificate.filePath', null);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledWrapper>
|
<StyledWrapper>
|
||||||
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
<form className="bruno-form" onSubmit={formik.handleSubmit}>
|
||||||
@ -80,6 +104,60 @@ const General = ({ close }) => {
|
|||||||
SSL/TLS Certificate Verification
|
SSL/TLS Certificate Verification
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center mt-2">
|
||||||
|
<input
|
||||||
|
id="customCaCertificateEnabled"
|
||||||
|
type="checkbox"
|
||||||
|
name="customCaCertificate.enabled"
|
||||||
|
checked={formik.values.customCaCertificate.enabled}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
className="mousetrap mr-0"
|
||||||
|
/>
|
||||||
|
<label className="block ml-2 select-none" htmlFor="customCaCertificateEnabled">
|
||||||
|
Use custom CA Certificate
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{formik.values.customCaCertificate.filePath ? (
|
||||||
|
<div
|
||||||
|
className={`flex items-center mt-2 pl-6 ${formik.values.customCaCertificate.enabled ? '' : 'opacity-25'}`}
|
||||||
|
>
|
||||||
|
<span className="flex items-center border px-2 rounded-md">
|
||||||
|
{path.basename(slash(formik.values.customCaCertificate.filePath))}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
tabIndex="-1"
|
||||||
|
className="pl-1"
|
||||||
|
disabled={formik.values.customCaCertificate.enabled ? false : true}
|
||||||
|
onClick={deleteCaCertificate}
|
||||||
|
>
|
||||||
|
<IconTrash strokeWidth={1.5} size={14} />
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
className={`flex items-center mt-2 pl-6 ${formik.values.customCaCertificate.enabled ? '' : 'opacity-25'}`}
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
tabIndex="-1"
|
||||||
|
className="flex items-center border px-2 rounded-md"
|
||||||
|
disabled={formik.values.customCaCertificate.enabled ? false : true}
|
||||||
|
onClick={() => inputFileCaCertificateRef.current.click()}
|
||||||
|
>
|
||||||
|
select file
|
||||||
|
<input
|
||||||
|
id="caCertFilePath"
|
||||||
|
type="file"
|
||||||
|
name="customCaCertificate.filePath"
|
||||||
|
className="hidden"
|
||||||
|
ref={inputFileCaCertificateRef}
|
||||||
|
disabled={formik.values.customCaCertificate.enabled ? false : true}
|
||||||
|
onChange={addCaCertificate}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<div className="flex items-center mt-2">
|
<div className="flex items-center mt-2">
|
||||||
<input
|
<input
|
||||||
id="storeCookies"
|
id="storeCookies"
|
||||||
|
@ -11,6 +11,10 @@ const initialState = {
|
|||||||
preferences: {
|
preferences: {
|
||||||
request: {
|
request: {
|
||||||
sslVerification: true,
|
sslVerification: true,
|
||||||
|
customCaCertificate: {
|
||||||
|
enabled: false,
|
||||||
|
filePath: null
|
||||||
|
},
|
||||||
timeout: 0
|
timeout: 0
|
||||||
},
|
},
|
||||||
font: {
|
font: {
|
||||||
|
@ -86,11 +86,22 @@ const configureRequest = async (
|
|||||||
request.url = `http://${request.url}`;
|
request.url = `http://${request.url}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const httpsAgentRequestFields = {};
|
/**
|
||||||
|
* @see https://github.com/usebruno/bruno/issues/211 set keepAlive to true, this should fix socket hang up errors
|
||||||
|
* @see https://github.com/nodejs/node/pull/43522 keepAlive was changed to true globally on Node v19+
|
||||||
|
*/
|
||||||
|
const httpsAgentRequestFields = { keepAlive: true };
|
||||||
if (!preferencesUtil.shouldVerifyTls()) {
|
if (!preferencesUtil.shouldVerifyTls()) {
|
||||||
httpsAgentRequestFields['rejectUnauthorized'] = false;
|
httpsAgentRequestFields['rejectUnauthorized'] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preferencesUtil.shouldUseCustomCaCertificate()) {
|
||||||
|
const caCertFilePath = preferencesUtil.getCustomCaCertificateFilePath();
|
||||||
|
if (caCertFilePath) {
|
||||||
|
httpsAgentRequestFields['ca'] = fs.readFileSync(caCertFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const brunoConfig = getBrunoConfig(collectionUid);
|
const brunoConfig = getBrunoConfig(collectionUid);
|
||||||
const interpolationOptions = {
|
const interpolationOptions = {
|
||||||
envVars,
|
envVars,
|
||||||
|
@ -11,6 +11,10 @@ const { get } = require('lodash');
|
|||||||
const defaultPreferences = {
|
const defaultPreferences = {
|
||||||
request: {
|
request: {
|
||||||
sslVerification: true,
|
sslVerification: true,
|
||||||
|
customCaCertificate: {
|
||||||
|
enabled: false,
|
||||||
|
filePath: null
|
||||||
|
},
|
||||||
storeCookies: true,
|
storeCookies: true,
|
||||||
sendCookies: true,
|
sendCookies: true,
|
||||||
timeout: 0
|
timeout: 0
|
||||||
@ -35,6 +39,10 @@ const defaultPreferences = {
|
|||||||
const preferencesSchema = Yup.object().shape({
|
const preferencesSchema = Yup.object().shape({
|
||||||
request: Yup.object().shape({
|
request: Yup.object().shape({
|
||||||
sslVerification: Yup.boolean(),
|
sslVerification: Yup.boolean(),
|
||||||
|
customCaCertificate: Yup.object({
|
||||||
|
enabled: Yup.boolean(),
|
||||||
|
filePath: Yup.string().nullable()
|
||||||
|
}),
|
||||||
storeCookies: Yup.boolean(),
|
storeCookies: Yup.boolean(),
|
||||||
sendCookies: Yup.boolean(),
|
sendCookies: Yup.boolean(),
|
||||||
timeout: Yup.number()
|
timeout: Yup.number()
|
||||||
@ -100,6 +108,12 @@ const preferencesUtil = {
|
|||||||
shouldVerifyTls: () => {
|
shouldVerifyTls: () => {
|
||||||
return get(getPreferences(), 'request.sslVerification', true);
|
return get(getPreferences(), 'request.sslVerification', true);
|
||||||
},
|
},
|
||||||
|
shouldUseCustomCaCertificate: () => {
|
||||||
|
return get(getPreferences(), 'request.customCaCertificate.enabled', false);
|
||||||
|
},
|
||||||
|
getCustomCaCertificateFilePath: () => {
|
||||||
|
return get(getPreferences(), 'request.customCaCertificate.filePath', null);
|
||||||
|
},
|
||||||
getRequestTimeout: () => {
|
getRequestTimeout: () => {
|
||||||
return get(getPreferences(), 'request.timeout', 0);
|
return get(getPreferences(), 'request.timeout', 0);
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user