Skip to content

Commit

Permalink
Initial check-in for smaller part of AWS change, only including setti…
Browse files Browse the repository at this point in the history
…ng modal for add cloud service provider crendentials
  • Loading branch information
cwangsmv committed Jan 24, 2025
1 parent 8f8445c commit 2bf192f
Show file tree
Hide file tree
Showing 26 changed files with 5,899 additions and 3,334 deletions.
8,308 changes: 4,977 additions & 3,331 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/insomnia/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
"dependencies": {
"@apideck/better-ajv-errors": "^0.3.6",
"@apidevtools/swagger-parser": "10.1.0",
"@aws-sdk/client-secrets-manager": "^3.686.0",
"@aws-sdk/client-sts": "^3.686.0",
"@bufbuild/protobuf": "^1.8.0",
"@connectrpc/connect": "^1.4.0",
"@connectrpc/connect-node": "^1.4.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/insomnia/src/main.development.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import log, { initializeLogging } from './common/log';
import { SegmentEvent, trackSegmentEvent } from './main/analytics';
import { registerInsomniaProtocols } from './main/api.protocol';
import { backupIfNewerVersionAvailable } from './main/backup';
import { registerCloudServiceHandlers } from './main/ipc/cloud-service-integration/cloud-service';
import { ipcMainOn, ipcMainOnce, registerElectronHandlers } from './main/ipc/electron';
import { registergRPCHandlers } from './main/ipc/grpc';
import { registerMainHandlers } from './main/ipc/main';
Expand Down Expand Up @@ -64,6 +65,7 @@ app.on('ready', async () => {
registergRPCHandlers();
registerWebSocketHandlers();
registerCurlHandlers();
registerCloudServiceHandlers();

/**
* There's no option that prevents Electron from fetching spellcheck dictionaries from Chromium's CDN and passing a non-resolving URL is the only known way to prevent it from fetching.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { GetCallerIdentityCommand, type GetCallerIdentityCommandOutput, STSClient, STSServiceException } from '@aws-sdk/client-sts';

import type { AWSTemporaryCredential, CloudProviderName } from '../../../models/cloud-credential';
import type { AWSSecretConfig, CloudServiceResult, ICloudService } from './types';

export type AWSGetSecretConfig = Omit<AWSSecretConfig, 'SecretId' | 'SecretType' | 'SecretKey'>;
export const providerName: CloudProviderName = 'aws';
export class AWSService implements ICloudService {
_credential: AWSTemporaryCredential;

constructor(credential: AWSTemporaryCredential) {
this._credential = credential;
}

async authenticate(): Promise<CloudServiceResult<GetCallerIdentityCommandOutput>> {
const { region, accessKeyId, secretAccessKey, sessionToken } = this._credential;
const stsClient = new STSClient({
region,
credentials: {
accessKeyId, secretAccessKey, sessionToken,
},
});

try {
const response = await stsClient.send(new GetCallerIdentityCommand({}));
return {
success: true,
result: response,
};
} catch (error) {
const errorDetail = {
errorCode: error.code || 'UnknownError',
errorMessage: error.message || 'Failed to authenticate with AWS. An unknown error occurred',
};
if (error instanceof STSServiceException) {
errorDetail.errorCode = error.name || errorDetail.errorCode;
errorDetail.errorMessage = error.message || errorDetail.errorMessage;
}
return {
success: false,
result: null,
error: errorDetail,
};
}
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { AWSTemporaryCredential, BaseCloudCredential, CloudProviderName } from '../../../models/cloud-credential';
import { ipcMainHandle } from '../electron';
import { type AWSGetSecretConfig, AWSService } from './aws-service';

export interface cloudServiceBridgeAPI {
authenticate: typeof cspAuthentication;
}
export interface CloudServiceAuthOption {
provider: CloudProviderName;
credentials: BaseCloudCredential['credentials'];
}
export interface CloudServiceSecretOption<T extends {}> extends CloudServiceAuthOption {
secretId: string;
config: T;
}
export type CloudServiceGetSecretConfig = AWSGetSecretConfig;

export function registerCloudServiceHandlers() {
ipcMainHandle('cloudService.authenticate', (_event, options) => cspAuthentication(options));
}

// factory pattern to create cloud service class based on its provider name
class ServiceFactory {
static createCloudService(name: CloudProviderName, credential: BaseCloudCredential['credentials']) {
switch (name) {
case 'aws':
return new AWSService(credential as AWSTemporaryCredential);
default:
throw new Error('Invalid cloud service provider name');
}
}
};

// authenticate with cloud service provider
const cspAuthentication = (options: CloudServiceAuthOption) => {
const { provider, credentials } = options;
const cloudService = ServiceFactory.createCloudService(provider, credentials);
return cloudService.authenticate();
};
23 changes: 23 additions & 0 deletions packages/insomnia/src/main/ipc/cloud-service-integration/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export interface CloudServiceError {
errorCode: string;
errorMessage: string;
}
export interface CloudServiceResult<T extends Record<string, any>> {
success: boolean;
result?: T | null;
error?: CloudServiceError;
}
export interface ICloudService {
authenticate(...args: any[]): Promise<any>;
}

export type AWSSecretType = 'kv' | 'plaintext';
export interface AWSSecretConfig {
SecretId: string;
VersionId?: string;
VersionStage?: string;
SecretType: AWSSecretType;
SecretKey?: string;
};

export type ExternalVaultConfig = AWSSecretConfig;
3 changes: 2 additions & 1 deletion packages/insomnia/src/main/ipc/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export type HandleChannels =
| 'webSocket.open'
| 'webSocket.readyState'
| 'writeFile'
| 'extractJsonFileFromPostmanDataDumpArchive';
| 'extractJsonFileFromPostmanDataDumpArchive'
| 'cloudService.authenticate';

export const ipcMainHandle = (
channel: HandleChannels,
Expand Down
2 changes: 2 additions & 0 deletions packages/insomnia/src/main/ipc/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type { CurlBridgeAPI } from '../network/curl';
import { cancelCurlRequest, curlRequest } from '../network/libcurl-promise';
import { addExecutionStep, completeExecutionStep, getExecution, startExecution, type TimingStep, updateLatestStepName } from '../network/request-timing';
import type { WebSocketBridgeAPI } from '../network/websocket';
import type { cloudServiceBridgeAPI } from './cloud-service-integration/cloud-service';
import { ipcMainHandle, ipcMainOn, ipcMainOnce, type RendererOnChannels } from './electron';
import extractPostmanDataDumpHandler from './extractPostmanDataDump';
import type { gRPCBridgeAPI } from './grpc';
Expand All @@ -37,6 +38,7 @@ export interface RendererToMainBridgeAPI {
webSocket: WebSocketBridgeAPI;
grpc: gRPCBridgeAPI;
curl: CurlBridgeAPI;
cloudService: cloudServiceBridgeAPI;
trackSegmentEvent: (options: { event: string; properties?: Record<string, unknown> }) => void;
trackPageView: (options: { name: string }) => void;
showContextMenu: (options: { key: string; nunjucksTag?: { template: string; range: MarkerRange } }) => void;
Expand Down
84 changes: 84 additions & 0 deletions packages/insomnia/src/models/cloud-credential.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { database as db } from '../common/database';
import type { BaseModel } from './index';

export type CloudProviderName = 'aws' | 'azure' | 'gcp';
export enum AWSCredentialType {
temp = 'temporary'
}
export interface AWSTemporaryCredential {
type: AWSCredentialType.temp;
accessKeyId: string;
secretAccessKey: string;
sessionToken: string;
region: string;
}
interface IBaseCloudCredential {
name: string;
provider: CloudProviderName;
}
export interface AWSCloudCredential extends IBaseCloudCredential {
name: string;
provider: 'aws';
credentials: AWSTemporaryCredential;
}
export type BaseCloudCredential = AWSCloudCredential;
export type CloudProviderCredential = BaseModel & BaseCloudCredential;

export const name = 'Cloud Credential';
export const type = 'CloudCredential';
export const prefix = 'cloudCred';
export const canDuplicate = false;
export const canSync = false;

export const isCloudCredential = (model: Pick<BaseModel, 'type'>): model is CloudProviderCredential => (
model.type === type
);

export function getProviderDisplayName(provider: CloudProviderName) {
switch (provider) {
case 'aws':
return 'AWS';
case 'azure':
return 'Azure';
case 'gcp':
return 'GCP';
default:
return '';
}
};

export function init(): Partial<BaseCloudCredential> {
return {
name: '',
provider: undefined,
credentials: undefined,
};
}

export function migrate(doc: BaseCloudCredential) {
return doc;
}

export function create(patch: Partial<CloudProviderCredential> = {}) {
return db.docCreate<CloudProviderCredential>(type, patch);
}

export async function getById(id: string) {
return db.getWhere<CloudProviderCredential>(type, { _id: id });
}

export function update(credential: CloudProviderCredential, patch: Partial<CloudProviderCredential>) {
return db.docUpdate<CloudProviderCredential>(credential, patch);
}

export function remove(credential: CloudProviderCredential) {
return db.remove(credential);
}

export function getByName(name: string, provider: CloudProviderName) {
return db.find<CloudProviderCredential>(type, { name, provider });
}

export function all() {
return db.all<CloudProviderCredential>(type);
}
3 changes: 3 additions & 0 deletions packages/insomnia/src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { generateId } from '../common/misc';
import * as _apiSpec from './api-spec';
import * as _caCertificate from './ca-certificate';
import * as _clientCertificate from './client-certificate';
import * as _cloudCredential from './cloud-credential';
import * as _cookieJar from './cookie-jar';
import * as _environment from './environment';
import * as _gitRepository from './git-repository';
Expand Down Expand Up @@ -99,6 +100,7 @@ export const workspace = _workspace;
export const workspaceMeta = _workspaceMeta;
export * as organization from './organization';
export const userSession = _userSession;
export const cloudCrendential = _cloudCredential;

export function all() {
// NOTE: This list should be from most to least specific (ie. parents above children)
Expand Down Expand Up @@ -138,6 +140,7 @@ export function all() {
webSocketRequest,
webSocketResponse,
userSession,
cloudCrendential,
] as const;
}

Expand Down
6 changes: 6 additions & 0 deletions packages/insomnia/src/preload.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { contextBridge, ipcRenderer, webUtils as _webUtils } from 'electron';

import type { cloudServiceBridgeAPI } from './main/ipc/cloud-service-integration/cloud-service';
import type { gRPCBridgeAPI } from './main/ipc/grpc';
import type { CurlBridgeAPI } from './main/network/curl';
import type { WebSocketBridgeAPI } from './main/network/websocket';
Expand Down Expand Up @@ -40,6 +41,10 @@ const grpc: gRPCBridgeAPI = {
loadMethods: options => ipcRenderer.invoke('grpc.loadMethods', options),
loadMethodsFromReflection: options => ipcRenderer.invoke('grpc.loadMethodsFromReflection', options),
};

const cloudService: cloudServiceBridgeAPI = {
authenticate: options => ipcRenderer.invoke('cloudService.authenticate', options),
};
const main: Window['main'] = {
startExecution: options => ipcRenderer.send('startExecution', options),
addExecutionStep: options => ipcRenderer.send('addExecutionStep', options),
Expand Down Expand Up @@ -67,6 +72,7 @@ const main: Window['main'] = {
webSocket,
grpc,
curl,
cloudService,
trackSegmentEvent: options => ipcRenderer.send('trackSegmentEvent', options),
trackPageView: options => ipcRenderer.send('trackPageView', options),
showContextMenu: options => ipcRenderer.send('show-context-menu', options),
Expand Down
13 changes: 13 additions & 0 deletions packages/insomnia/src/ui/components/assets/svgr/IcnAzureLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* eslint-disable react/no-unknown-property */
import React, { memo, type SVGProps } from 'react';
export const SvgIcnAzureLogo = memo<SVGProps<SVGSVGElement>>(props => (
<svg viewBox="-0.4500000000000005 0.38 800.8891043012813 754.2299999999999" width="1em" height="1em" role="img" {...props}>
<linearGradient id="a" gradientUnits="userSpaceOnUse" x1="353.1" x2="107.1" y1="56.3" y2="783"><stop offset="0" stop-color="#114a8b" /><stop offset="1" stop-color="#0669bc" /></linearGradient>
<linearGradient id="b" gradientUnits="userSpaceOnUse" x1="429.8" x2="372.9" y1="394.9" y2="414.2"><stop offset="0" stop-opacity=".3" /><stop offset=".1" stop-opacity=".2" /><stop offset=".3" stop-opacity=".1" /><stop offset=".6" stop-opacity=".1" /><stop offset="1" stop-opacity="0" /></linearGradient>
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="398.4" x2="668.4" y1="35.1" y2="754.4"><stop offset="0" stop-color="#3ccbf4" /><stop offset="1" stop-color="#2892df" /></linearGradient>
<path d="M266.71.4h236.71L257.69 728.9a37.8 37.8 0 0 1-5.42 10.38c-2.33 3.16-5.14 5.93-8.33 8.22s-6.71 4.07-10.45 5.27-7.64 1.82-11.56 1.82H37.71c-5.98 0-11.88-1.42-17.2-4.16A37.636 37.636 0 0 1 7.1 738.87a37.762 37.762 0 0 1-6.66-16.41c-.89-5.92-.35-11.97 1.56-17.64L230.94 26.07c1.25-3.72 3.08-7.22 5.42-10.38 2.33-3.16 5.15-5.93 8.33-8.22 3.19-2.29 6.71-4.07 10.45-5.27S262.78.38 266.7.38v.01z" fill="url(#a)" />
<path d="M703.07 754.59H490.52c-2.37 0-4.74-.22-7.08-.67-2.33-.44-4.62-1.1-6.83-1.97s-4.33-1.95-6.34-3.21a38.188 38.188 0 0 1-5.63-4.34l-241.2-225.26a17.423 17.423 0 0 1-5.1-8.88 17.383 17.383 0 0 1 7.17-18.21c2.89-1.96 6.3-3.01 9.79-3.01h375.36l92.39 265.56z" fill="#0078d4" />
<path d="M504.27.4l-165.7 488.69 270.74-.06 92.87 265.56H490.43c-2.19-.02-4.38-.22-6.54-.61s-4.28-.96-6.34-1.72a38.484 38.484 0 0 1-11.36-6.51L303.37 593.79l-45.58 134.42c-1.18 3.36-2.8 6.55-4.82 9.48a40.479 40.479 0 0 1-16.05 13.67 40.03 40.03 0 0 1-10.13 3.23H37.82c-6.04.02-12-1.42-17.37-4.2A37.664 37.664 0 0 1 .43 722a37.77 37.77 0 0 1 1.87-17.79L230.87 26.58c1.19-3.79 2.98-7.36 5.3-10.58 2.31-3.22 5.13-6.06 8.33-8.4s6.76-4.16 10.53-5.38S262.75.38 266.72.4h237.56z" fill="url(#b)" />
<path d="M797.99 704.82a37.847 37.847 0 0 1 1.57 17.64 37.867 37.867 0 0 1-6.65 16.41 37.691 37.691 0 0 1-30.61 15.72H498.48c5.98 0 11.88-1.43 17.21-4.16 5.32-2.73 9.92-6.7 13.41-11.56s5.77-10.49 6.66-16.41.35-11.97-1.56-17.64L305.25 26.05a37.713 37.713 0 0 0-13.73-18.58c-3.18-2.29-6.7-4.06-10.43-5.26S273.46.4 269.55.4h263.81c3.92 0 7.81.61 11.55 1.81 3.73 1.2 7.25 2.98 10.44 5.26 3.18 2.29 5.99 5.06 8.32 8.21s4.15 6.65 5.41 10.37l228.95 678.77z" fill="url(#c)" />
</svg>
));
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React, { memo, type SVGProps } from 'react';
export const SvgIcnGCPLogo = memo<SVGProps<SVGSVGElement>>(props => (
<svg viewBox="0 0 256 206" width="1em" height="1em" role="img" {...props}>
<path d="m170.2517 56.8186 22.253-22.253 1.483-9.37c-40.551-36.873-105.012-32.692-141.567 8.724-10.154 11.503-17.687 25.844-21.704 40.653l7.97-1.123 44.505-7.339 3.436-3.514c19.797-21.742 53.27-24.667 76.128-6.168z" fill="#ea4335" />
<path d="m224.2048 73.9182c-5.115-18.836-15.616-35.769-30.217-48.722l-31.232 31.232c13.188 10.776 20.701 27.01 20.379 44.037v5.544c15.351 0 27.797 12.445 27.797 27.796 0 15.352-12.446 27.485-27.797 27.485h-55.671l-5.466 5.934v33.34l5.466 5.231h55.671c39.93.311 72.552-31.494 72.863-71.424.188-24.203-11.745-46.893-31.793-60.453" fill="#4285f4" />
<path d="m71.8704 205.7957h55.593v-44.506h-55.593c-3.961-.001-7.797-.852-11.399-2.498l-7.887 2.42-22.409 22.253-1.952 7.574c12.567 9.489 27.9 14.825 43.647 14.757" fill="#34a853" /><path d="m71.8704 61.4255c-39.931.238-72.107 32.802-71.869 72.732.133 22.298 10.547 43.288 28.222 56.881l32.248-32.247c-13.991-6.321-20.208-22.786-13.887-36.776 6.32-13.99 22.786-20.207 36.775-13.887 6.165 2.785 11.102 7.723 13.887 13.887l32.248-32.247c-13.721-17.937-35.041-28.424-57.624-28.343" fill="#fbbc05" />
</svg>
));
Loading

0 comments on commit 2bf192f

Please sign in to comment.