History

Share secret-backed credential values (#454)

Rhys Sullivan committed 6 months ago

Commit 9639a681 parent 899a99e17 files · +768 −954Browse files

Showing the changes to packages/plugins/openapi/src (3 of 17 files). Show all

Unified · Split

3 files
  1. packages/plugins/openapi/src/api/group.ts +1 −9
  2. packages/plugins/openapi/src/sdk/plugin.ts +18 −25
  3. packages/plugins/openapi/src/sdk/types.ts +6 −16
packages/plugins/openapi/src/api/group.ts+1−9
@@ -1,6 +1,6 @@
1import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform";1import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform";
2import { Schema } from "effect";2import { Schema } from "effect";
3import { ScopeId } from "@executor/sdk";3import { ScopeId, SecretBackedValue } from "@executor/sdk";
4import { InternalError } from "@executor/api";4import { InternalError } from "@executor/api";
5 5
6import { OpenApiParseError, OpenApiExtractionError, OpenApiOAuthError } from "../sdk/errors";6import { OpenApiParseError, OpenApiExtractionError, OpenApiOAuthError } from "../sdk/errors";
@@ -21,14 +21,6 @@ const scopeIdParam = HttpApiSchema.param("scopeId", ScopeId); · 14 unmodified lines
21const namespaceParam = HttpApiSchema.param("namespace", Schema.String);21const namespaceParam = HttpApiSchema.param("namespace", Schema.String);
22const sourceScopeIdParam = HttpApiSchema.param("sourceScopeId", ScopeId);22const sourceScopeIdParam = HttpApiSchema.param("sourceScopeId", ScopeId);
23 23
24const SecretBackedValue = Schema.Union(
25 Schema.String,
26 Schema.Struct({
27 secretId: Schema.String,
28 prefix: Schema.optional(Schema.String),
29 }),
30);
31
32const SpecFetchCredentialsPayload = Schema.Struct({24const SpecFetchCredentialsPayload = Schema.Struct({
33 headers: Schema.optional(Schema.Record({ key: Schema.String, value: SecretBackedValue })),25 headers: Schema.optional(Schema.Record({ key: Schema.String, value: SecretBackedValue })),
34 queryParams: Schema.optional(Schema.Record({ key: Schema.String, value: SecretBackedValue })),26 queryParams: Schema.optional(Schema.Record({ key: Schema.String, value: SecretBackedValue })),
packages/plugins/openapi/src/sdk/plugin.ts+18−25
@@ -8,6 +8,7 @@ import { · 7 unmodified lines
8 SecretId,8 SecretId,
9 SourceDetectionResult,9 SourceDetectionResult,
10 definePlugin,10 definePlugin,
11 resolveSecretBackedMap,
11 type PluginCtx,12 type PluginCtx,
12 type StorageFailure,13 type StorageFailure,
13 type ToolAnnotations,14 type ToolAnnotations,
@@ -471,39 +472,31 @@ const resolveConfiguredHeaders = ( · 457 unmodified lines
471 return resolved;472 return resolved;
472 });473 });
473 474
474const resolveHeaderValue = (475const resolveHeaderValues = (
475 ctx: PluginCtx<OpenapiStore>,476 ctx: PluginCtx<OpenapiStore>,
476 name: string,477 values: Record<string, HeaderValue> | undefined,
477 value: HeaderValue,478): Effect.Effect<Record<string, string>, OpenApiOAuthError | StorageFailure> =>
478): Effect.Effect<string, OpenApiOAuthError | StorageFailure> => {479 resolveSecretBackedMap({
479 if (typeof value === "string") return Effect.succeed(value);480 values,
480 return ctx.secrets.get(value.secretId).pipe(481 getSecret: ctx.secrets.get,
481 Effect.mapError((err) =>482 onMissing: (name) =>
483 new OpenApiOAuthError({
484 message: `Secret not found for "${name}"`,
485 }),
486 onError: (err, name) =>
482 "_tag" in err && err._tag === "SecretOwnedByConnectionError"487 "_tag" in err && err._tag === "SecretOwnedByConnectionError"
483 ? new OpenApiOAuthError({488 ? new OpenApiOAuthError({
484 message: `Secret not found for "${name}"`,489 message: `Secret not found for "${name}"`,
485 })490 })
486 : err,491 : err,
492 }).pipe(
493 Effect.mapError((err) =>
494 "_tag" in err && err._tag === "SecretOwnedByConnectionError"
495 ? new OpenApiOAuthError({ message: "Secret resolution failed" })
496 : err,
487 ),497 ),
488 Effect.flatMap((secret) =>498 Effect.map((resolved) => resolved ?? {}),
489 secret === null
490 ? Effect.fail(
491 new OpenApiOAuthError({
492 message: `Secret not found for "${name}"`,
493 }),
494 )
495 : Effect.succeed(value.prefix ? `${value.prefix}${secret}` : secret),
496 ),
497 );499 );
498};
499
500const resolveHeaderValues = (
501 ctx: PluginCtx<OpenapiStore>,
502 values: Record<string, HeaderValue> | undefined,
503): Effect.Effect<Record<string, string>, OpenApiOAuthError | StorageFailure> =>
504 Effect.forEach(Object.entries(values ?? {}), ([name, value]) =>
505 Effect.map(resolveHeaderValue(ctx, name, value), (resolved) => [name, resolved] as const),
506 ).pipe(Effect.map((entries) => Object.fromEntries(entries)));
507 500
508const resolveOAuthConnectionId = (501const resolveOAuthConnectionId = (
509 ctx: PluginCtx<OpenapiStore>,502 ctx: PluginCtx<OpenapiStore>,
packages/plugins/openapi/src/sdk/types.ts+6−16
@@ -1,5 +1,5 @@
1import { Schema } from "effect";1import { Schema } from "effect";
2import { ConnectionId, ScopeId, SecretId } from "@executor/sdk";2import { ConnectionId, ScopeId, SecretBackedValue, SecretId } from "@executor/sdk";
3 3
4// ---------------------------------------------------------------------------4// ---------------------------------------------------------------------------
5// Branded IDs5// Branded IDs
@@ -61,10 +61,9 @@ export class EncodingObject extends Schema.Class<EncodingObject>("EncodingObject · 55 unmodified lines
61export class MediaBinding extends Schema.Class<MediaBinding>("MediaBinding")({61export class MediaBinding extends Schema.Class<MediaBinding>("MediaBinding")({
62 contentType: Schema.String,62 contentType: Schema.String,
63 schema: Schema.optionalWith(Schema.Unknown, { as: "Option" }),63 schema: Schema.optionalWith(Schema.Unknown, { as: "Option" }),
64 encoding: Schema.optionalWith(64 encoding: Schema.optionalWith(Schema.Record({ key: Schema.String, value: EncodingObject }), {
65 Schema.Record({ key: Schema.String, value: EncodingObject }),65 as: "Option",
66 { as: "Option" },66 }),
67 ),
68}) {}67}) {}
69 68
70export class OperationRequestBody extends Schema.Class<OperationRequestBody>(69export class OperationRequestBody extends Schema.Class<OperationRequestBody>(
@@ -137,13 +136,7 @@ export class OperationBinding extends Schema.Class<OperationBinding>("OperationB · 66 unmodified lines
137 * A header value — either a static string or a reference to a secret.136 * A header value — either a static string or a reference to a secret.
138 * Stored as JSON-serializable data.137 * Stored as JSON-serializable data.
139 */138 */
140export const HeaderValue = Schema.Union(139export const HeaderValue = SecretBackedValue;
141 Schema.String,
142 Schema.Struct({
143 secretId: Schema.String,
144 prefix: Schema.optional(Schema.String),
145 }),
146);
147export type HeaderValue = typeof HeaderValue.Type;140export type HeaderValue = typeof HeaderValue.Type;
148 141
149export class ConfiguredHeaderBinding extends Schema.Class<ConfiguredHeaderBinding>(142export class ConfiguredHeaderBinding extends Schema.Class<ConfiguredHeaderBinding>(
@@ -154,10 +147,7 @@ export class ConfiguredHeaderBinding extends Schema.Class<ConfiguredHeaderBindin · 4 unmodified lines
154 prefix: Schema.optional(Schema.String),147 prefix: Schema.optional(Schema.String),
155}) {}148}) {}
156 149
157export const ConfiguredHeaderValue = Schema.Union(150export const ConfiguredHeaderValue = Schema.Union(Schema.String, ConfiguredHeaderBinding);
158 Schema.String,
159 ConfiguredHeaderBinding,
160);
161export type ConfiguredHeaderValue = typeof ConfiguredHeaderValue.Type;151export type ConfiguredHeaderValue = typeof ConfiguredHeaderValue.Type;
162 152
163export const OpenApiSourceBindingValue = Schema.Union(153export const OpenApiSourceBindingValue = Schema.Union(

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t