mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-21 06:37:36 -04:00
1.remove aws related code
This commit is contained in:
@@ -1,184 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Button, Menu, MenuItem, MenuTrigger, Popover } from 'react-aria-components';
|
||||
import { useFetcher } from 'react-router-dom';
|
||||
|
||||
import { type CloudProviderCredential, type CloudProviderName, getProviderDisplayName } from '../../../models/cloud-credential';
|
||||
import { usePlanData } from '../../hooks/use-plan';
|
||||
import { useRootLoaderData } from '../../routes/root';
|
||||
import { Icon } from '../icon';
|
||||
import { showModal } from '../modals';
|
||||
import { AskModal } from '../modals/ask-modal';
|
||||
import { CloudCredentialModal } from '../modals/cloud-credential-modal/cloud-credential-modal';
|
||||
import { UpgradeNotice } from '../upgrade-notices';
|
||||
import { NumberSetting } from './number-setting';
|
||||
|
||||
interface createCredentialItemType {
|
||||
name: string;
|
||||
id: CloudProviderName;
|
||||
}
|
||||
const createCredentialItemList: createCredentialItemType[] = [
|
||||
{
|
||||
id: 'aws',
|
||||
name: getProviderDisplayName('aws'),
|
||||
},
|
||||
// TODO only support aws for now
|
||||
// {
|
||||
// id: 'azure',
|
||||
// name: getProviderDisplayName('azure'),
|
||||
// },
|
||||
// {
|
||||
// id: 'gcp',
|
||||
// name: getProviderDisplayName('gcp'),
|
||||
// },
|
||||
];
|
||||
const buttonClassName = 'disabled:opacity-50 h-7 aspect-square aria-pressed:bg-[--hl-sm] rounded-sm text-[--color-font] hover:bg-[--hl-xs] transition-all text-sm py-1 px-2';
|
||||
|
||||
export const CloudServiceCredentialList = () => {
|
||||
const { isOwner, isEnterprisePlan } = usePlanData();
|
||||
const { cloudCredentials } = useRootLoaderData();
|
||||
const [modalState, setModalState] = useState<{ show: boolean; provider: CloudProviderName; credential?: CloudProviderCredential }>();
|
||||
const deleteCredentialFetcher = useFetcher();
|
||||
|
||||
const handleDeleteItem = (id: string, name: string) => {
|
||||
showModal(AskModal, {
|
||||
title: 'Delete Cloud Credential?',
|
||||
message: `Are you sure to delete ${name}?`,
|
||||
onDone: async (isYes: boolean) => {
|
||||
if (isYes) {
|
||||
deleteCredentialFetcher.submit({}, {
|
||||
action: `/cloud-credential/${id}/delete`,
|
||||
method: 'delete',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const hideModal = () => {
|
||||
setModalState(prevState => {
|
||||
const newState = {
|
||||
show: false,
|
||||
provider: prevState!.provider,
|
||||
credentials: undefined,
|
||||
};
|
||||
return newState;
|
||||
});
|
||||
};
|
||||
|
||||
if (!isEnterprisePlan) {
|
||||
return (
|
||||
<UpgradeNotice
|
||||
isOwner={isOwner}
|
||||
featureName='Cloud Credentials feature'
|
||||
newPlan='enterprise'
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className='flex justify-between items-end'>
|
||||
<h2 className='font-bold text-lg bg-[--color-bg] z-10'>Service Provider Credential List</h2>
|
||||
<MenuTrigger>
|
||||
<Button
|
||||
aria-label="Create in project"
|
||||
className="flex items-center justify-center px-4 py-2 gap-2 h-full bg-[--hl-xxs] aria-pressed:bg-[--hl-sm] rounded-sm text-[--color-font] hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all text-sm"
|
||||
>
|
||||
<Icon icon="plus-circle" /> Add Credential
|
||||
</Button>
|
||||
<Popover
|
||||
className="min-w-max"
|
||||
placement='bottom right'
|
||||
>
|
||||
<Menu
|
||||
aria-label="Create in project actions"
|
||||
selectionMode="single"
|
||||
onAction={key => setModalState({ show: true, provider: key as CloudProviderName })}
|
||||
items={createCredentialItemList}
|
||||
className="border select-none text-sm min-w-max border-solid border-[--hl-sm] shadow-lg bg-[--color-bg] py-2 rounded-md overflow-y-auto max-h-[85vh] focus:outline-none"
|
||||
>
|
||||
{item => (
|
||||
<MenuItem
|
||||
key={item.id}
|
||||
id={item.id}
|
||||
className="flex gap-2 px-[--padding-md] aria-selected:font-bold items-center text-[--color-font] h-[--line-height-xxs] w-full text-md whitespace-nowrap bg-transparent hover:bg-[--hl-sm] disabled:cursor-not-allowed focus:bg-[--hl-xs] focus:outline-none transition-colors"
|
||||
aria-label={item.name}
|
||||
>
|
||||
<span>{item.name}</span>
|
||||
</MenuItem>
|
||||
)}
|
||||
</Menu>
|
||||
</Popover>
|
||||
</MenuTrigger>
|
||||
</div>
|
||||
{cloudCredentials.length === 0 ?
|
||||
<div className="text-center faint italic pad">No cloud servicie provider credentials found</div> :
|
||||
<table className="table--fancy table--striped table--valign-middle margin-top margin-bottom">
|
||||
<thead>
|
||||
<tr>
|
||||
<th className='normal-case'>Name</th>
|
||||
<th className='normal-case'>Service Provider</th>
|
||||
<th className='normal-case'>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{cloudCredentials.map(cloudCred => {
|
||||
const { _id, name, provider } = cloudCred;
|
||||
return (
|
||||
<tr key={_id}>
|
||||
<td >
|
||||
{name}
|
||||
</td>
|
||||
<td className='w-36'>
|
||||
{getProviderDisplayName(provider!)}
|
||||
</td>
|
||||
<td className='w-52 whitespace-nowrap'>
|
||||
<div className='flex gap-2'>
|
||||
<Button
|
||||
className={`${buttonClassName} w-16`}
|
||||
onPress={() => setModalState({ show: true, provider: provider!, credential: cloudCred })}
|
||||
>
|
||||
<Icon icon="edit" /> Edit
|
||||
</Button>
|
||||
<Button
|
||||
className={`${buttonClassName} w-20`}
|
||||
onPress={() => handleDeleteItem(_id, name)}
|
||||
>
|
||||
<Icon icon="trash" /> Delete
|
||||
</Button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
<div>
|
||||
<h2 className='font-bold pt-5 pb-2 text-lg bg-[--color-bg] z-10'>Cloud Secret Config</h2>
|
||||
<div className="form-row items-end justify-between">
|
||||
<NumberSetting
|
||||
label="Secret Cache Duration(min)"
|
||||
setting="vaultSecretCacheDuration"
|
||||
help="Enter the amount of time in minutes external vault secrets are cached in Insomnia. Enter 0 to disable cache. Click the Reset Cache button to clear all cache."
|
||||
min={0}
|
||||
max={720}
|
||||
/>
|
||||
<button
|
||||
className="w-32 flex items-center gap-2 border border-solid border-[--hl-lg] px-[--padding-md] h-[--line-height-xs] rounded-[--radius-md] hover:bg-[--hl-xs] pointer mb-[--padding-sm] ml-[--padding-sm]"
|
||||
onClick={() => window.main.cloudService.clearCache()}
|
||||
>
|
||||
Reset Cache
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{modalState && modalState.show &&
|
||||
<CloudCredentialModal
|
||||
provider={modalState.provider}
|
||||
providerCredential={modalState.credential}
|
||||
onClose={hideModal}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,132 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import type { AWSSecretConfig } from '../../../../main/ipc/cloud-service-integration/types';
|
||||
import type { NunjucksParsedTag } from '../../../../templating/utils';
|
||||
import { HelpTooltip } from '../../help-tooltip';
|
||||
|
||||
export interface AWSSecretManagerFormProps {
|
||||
formData: AWSSecretConfig;
|
||||
onChange: (newConfig: AWSSecretConfig) => void;
|
||||
activeTagData: NunjucksParsedTag;
|
||||
}
|
||||
const secretTypeOptions = [
|
||||
{
|
||||
key: 'plaintext',
|
||||
label: 'Plaintext',
|
||||
},
|
||||
{
|
||||
key: 'kv',
|
||||
label: 'Key/Value',
|
||||
},
|
||||
];
|
||||
|
||||
export const AWSSecretManagerForm = (props: AWSSecretManagerFormProps) => {
|
||||
const { formData, onChange } = props;
|
||||
const {
|
||||
SecretId,
|
||||
SecretType,
|
||||
VersionId = '',
|
||||
VersionStage = '',
|
||||
SecretKey = '',
|
||||
} = formData;
|
||||
const [showSecretKeyInput, setShowSecretKeyInput] = useState(SecretType === 'kv');
|
||||
const handleOnChange = (name: keyof AWSSecretConfig) => {
|
||||
const formElement = document.getElementById('aws-secret-manager-form') as HTMLFormElement;
|
||||
if (formElement) {
|
||||
const formData = new FormData(formElement);
|
||||
const newConfig = Object.fromEntries(formData.entries());
|
||||
if (name === 'SecretType') {
|
||||
const secretTypeValue = newConfig['SecretType'];
|
||||
setShowSecretKeyInput(secretTypeValue === 'kv');
|
||||
if (secretTypeValue === 'plaintext') {
|
||||
newConfig['SecretKey'] = '';
|
||||
}
|
||||
};
|
||||
onChange(newConfig as unknown as AWSSecretConfig);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<form id='aws-secret-manager-form'>
|
||||
<div className="form-row">
|
||||
<div className="form-control">
|
||||
<label>
|
||||
Secret Name Or ARN
|
||||
<HelpTooltip className="space-left">
|
||||
The ARN or name of the secret to retrieve. To retrieve a secret from another account, you must use an ARN.
|
||||
</HelpTooltip>
|
||||
<input
|
||||
name='SecretId'
|
||||
defaultValue={SecretId}
|
||||
onChange={() => handleOnChange('SecretId')}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<div className="form-control">
|
||||
<label>
|
||||
Version Id
|
||||
<HelpTooltip className="space-left">
|
||||
Optional unique identifier of the version of the secret to retrieve.
|
||||
</HelpTooltip>
|
||||
<input
|
||||
name='VersionId'
|
||||
defaultValue={VersionId}
|
||||
onChange={() => handleOnChange('VersionId')}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<div className="form-control">
|
||||
<label>
|
||||
Version Stage
|
||||
<HelpTooltip className="space-left">
|
||||
Optional staging label of the version of the secret to retrieve.
|
||||
</HelpTooltip>
|
||||
<input
|
||||
name='VersionStage'
|
||||
defaultValue={VersionStage}
|
||||
onChange={() => handleOnChange('VersionStage')}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-row">
|
||||
<div className="form-control">
|
||||
<label>
|
||||
Secret Type
|
||||
<select
|
||||
name='SecretType'
|
||||
defaultValue={SecretType || 'plaintext'}
|
||||
onChange={() => handleOnChange('SecretType')}
|
||||
>
|
||||
{secretTypeOptions.map(option => (
|
||||
<option key={option.key} value={option.key}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
{showSecretKeyInput &&
|
||||
<div className="form-row">
|
||||
<div className="form-control">
|
||||
<label>
|
||||
Secret Key
|
||||
<HelpTooltip className="space-left">
|
||||
The Secret Key of the retrived key/value secrets.
|
||||
</HelpTooltip>
|
||||
<input
|
||||
name='SecretKey'
|
||||
defaultValue={SecretKey}
|
||||
onChange={() => handleOnChange('SecretKey')}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@@ -1,60 +0,0 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Button } from 'react-aria-components';
|
||||
|
||||
import { debounce } from '../../../../common/misc';
|
||||
import type { AWSSecretConfig } from '../../../../main/ipc/cloud-service-integration/types';
|
||||
import { type CloudProviderCredential, type CloudProviderName, type } from '../../../../models/cloud-credential';
|
||||
import { Icon } from '../../icon';
|
||||
import { CloudCredentialModal } from '../../modals/cloud-credential-modal/cloud-credential-modal';
|
||||
import type { ArgConfigFormProps } from '../tag-editor-arg-sub-form';
|
||||
import { AWSSecretManagerForm } from './aws-secret-manager-form';
|
||||
|
||||
export const ExternalVaultForm = (props: ArgConfigFormProps) => {
|
||||
const { onChange, configValue, activeTagData, docs } = props;
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const formData = JSON.parse(configValue) as AWSSecretConfig;
|
||||
const provider = activeTagData.args[0].value as CloudProviderName;
|
||||
const selectedCredentialId = activeTagData.args[1].value;
|
||||
const cloudCredentialDocs = docs[type] as CloudProviderCredential[] || [];
|
||||
const selectedCredentialDoc = cloudCredentialDocs.find(d => d._id === selectedCredentialId);
|
||||
|
||||
const handleFormChange = debounce((newConfig: AWSSecretConfig) => {
|
||||
const newFormValue = JSON.stringify(newConfig);
|
||||
onChange(newFormValue);
|
||||
}, 1000);
|
||||
let SubForm;
|
||||
|
||||
switch (provider) {
|
||||
case 'aws':
|
||||
SubForm = <AWSSecretManagerForm
|
||||
formData={formData}
|
||||
onChange={handleFormChange}
|
||||
activeTagData={activeTagData}
|
||||
/>;
|
||||
break;
|
||||
default:
|
||||
SubForm = null;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{selectedCredentialDoc &&
|
||||
<Button
|
||||
className="px-2 py-1 mb-[--padding-sm] h-full flex items-center justify-center gap-2 aria-pressed:bg-[--hl-sm] text-[--color-info] text-xs hover:bg-[--hl-xs] focus:ring-inset ring-1 ring-transparent focus:ring-[--hl-md] transition-all"
|
||||
style={{ marginTop: 'calc(var(--padding-sm) * -1)' }}
|
||||
onPress={() => setShowModal(true)}
|
||||
>
|
||||
<Icon icon="edit" /> Edit Credential
|
||||
</Button>
|
||||
}
|
||||
{SubForm}
|
||||
{showModal &&
|
||||
<CloudCredentialModal
|
||||
provider={provider}
|
||||
providerCredential={selectedCredentialDoc}
|
||||
onClose={() => setShowModal(false)}
|
||||
/>
|
||||
}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -7,11 +7,6 @@ import os from 'os';
|
||||
import { CookieJar } from 'tough-cookie';
|
||||
import * as uuid from 'uuid';
|
||||
|
||||
import type { RenderPurpose } from '../../../common/render';
|
||||
import type { AWSSecretConfig } from '../../../main/ipc/cloud-service-integration/types';
|
||||
import * as models from '../../../models';
|
||||
import type { CloudProviderCredential, CloudProviderName } from '../../../models/cloud-credential';
|
||||
import { vaultEnvironmentMaskValue } from '../../../models/environment';
|
||||
import type { Request, RequestParameter } from '../../../models/request';
|
||||
import type { Response } from '../../../models/response';
|
||||
import type { TemplateTag } from '../../../plugins';
|
||||
@@ -21,100 +16,6 @@ import { buildQueryStringFromParams, joinUrlAndQueryString, smartEncodeUrl } fro
|
||||
import { fakerFunctions } from './faker-functions';
|
||||
|
||||
const localTemplatePlugins: { templateTag: PluginTemplateTag }[] = [
|
||||
{
|
||||
templateTag: {
|
||||
name: 'vault',
|
||||
displayName: 'External Vault',
|
||||
description: 'Link secret from external vault',
|
||||
// external vault is an enterprise feature
|
||||
needsEnterprisePlan: true,
|
||||
args: [
|
||||
{
|
||||
displayName: 'Vault Service Provider',
|
||||
type: 'enum',
|
||||
options: [
|
||||
{ displayName: 'AWS Secrets Manager', value: 'aws' },
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Credential For Vault Service Provider',
|
||||
type: 'model',
|
||||
modelFilter: (credentialModel, args) => {
|
||||
const providerNameFromArg = args[0].value;
|
||||
const { provider } = credentialModel as CloudProviderCredential;
|
||||
return providerNameFromArg === provider;
|
||||
},
|
||||
model: 'CloudCredential',
|
||||
},
|
||||
{
|
||||
type: 'string',
|
||||
defaultValue: '{}',
|
||||
requireSubForm: true,
|
||||
},
|
||||
],
|
||||
async run(context, provider: CloudProviderName, credentialId: string, configStr: string) {
|
||||
if (!provider) {
|
||||
throw new Error('Vault service provider is required');
|
||||
}
|
||||
if (!credentialId) {
|
||||
throw new Error('Credential is required');
|
||||
};
|
||||
const providerCredential = await models.cloudCrendential.getById(credentialId);
|
||||
if (!providerCredential) {
|
||||
throw new Error('No Cloud Credential found');
|
||||
}
|
||||
const renderContext = context.renderPurpose as RenderPurpose;
|
||||
// Get secret from external vaults when send request or in tag-preview, otherwise return defautl mask value
|
||||
if (renderContext === 'preview' || renderContext === 'send') {
|
||||
let secretConfig = {};
|
||||
try {
|
||||
secretConfig = JSON.parse(configStr);
|
||||
} catch (error) {
|
||||
throw new Error('Invalid vault secret config');
|
||||
}
|
||||
if (provider === 'aws') {
|
||||
const {
|
||||
SecretId, VersionId, VersionStage, SecretKey,
|
||||
SecretType = 'plaintext',
|
||||
} = secretConfig as AWSSecretConfig;
|
||||
if (!SecretId) {
|
||||
throw new Error('Secret Name or ARN is required');
|
||||
}
|
||||
const getSecretOption = {
|
||||
provider,
|
||||
secretId: SecretId,
|
||||
config: {
|
||||
VersionId, VersionStage,
|
||||
},
|
||||
credentials: providerCredential.credentials,
|
||||
};
|
||||
const secretResult = await window.main.cloudService.getSecret(getSecretOption);
|
||||
const { success, error, result } = secretResult;
|
||||
if (success && result) {
|
||||
const { SecretString } = result!;
|
||||
let parsedJSON;
|
||||
if (SecretType === 'plaintext' || !SecretKey) {
|
||||
return SecretString;
|
||||
} else {
|
||||
try {
|
||||
parsedJSON = JSON.parse(SecretString || '{}');
|
||||
} catch (error) {
|
||||
throw new Error(`Secret value ${SecretString} can not parsed to key/value pair, please change Secret Type to plaintext`);
|
||||
}
|
||||
if (SecretKey in parsedJSON) {
|
||||
return parsedJSON[SecretKey];
|
||||
}
|
||||
throw new Error(`Secret key ${SecretKey} does not exist in key/value secret ${SecretString}`);
|
||||
}
|
||||
} else {
|
||||
throw new Error(error?.errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
return vaultEnvironmentMaskValue;
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
templateTag: {
|
||||
name: 'faker',
|
||||
|
||||
Reference in New Issue
Block a user