Skip to content

Commit 14a0a7e

Browse files
committed
Merge branch 'connectors-auth-code-grant' of github.com:elastic/kibana into issue-251047-use-profile-uid-task-exe_stack
2 parents 38ab147 + 1907ce9 commit 14a0a7e

33 files changed

Lines changed: 290 additions & 105 deletions

File tree

src/platform/packages/shared/kbn-connector-specs/src/lib/generate_secrets_schema_from_spec.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,26 @@ import type { ConnectorSpec } from '../connector_spec';
1212
import { getSchemaForAuthType } from '.';
1313

1414
interface GenerateOptions {
15-
isPfxEnabled: boolean;
15+
isPfxEnabled?: boolean;
16+
authorizationCodeEnabled?: boolean;
1617
}
1718

1819
export const generateSecretsSchemaFromSpec = (
1920
authSpec: ConnectorSpec['auth'],
20-
{ isPfxEnabled }: GenerateOptions = { isPfxEnabled: true }
21+
{ isPfxEnabled, authorizationCodeEnabled }: GenerateOptions = {
22+
isPfxEnabled: true,
23+
authorizationCodeEnabled: false,
24+
}
2125
) => {
2226
const secretSchemas: z.core.$ZodTypeDiscriminable[] = [];
2327
for (const authType of authSpec?.types || []) {
2428
const schema = getSchemaForAuthType(authType);
2529
if (schema.id === 'pfx_certificate' && !isPfxEnabled) {
2630
continue;
2731
}
32+
if (schema.id === 'oauth_authorization_code' && !authorizationCodeEnabled) {
33+
continue;
34+
}
2835
secretSchemas.push(schema.schema);
2936
}
3037
return secretSchemas.length > 0

src/platform/packages/shared/kbn-connector-specs/src/specs/notion/notion.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,7 @@ export const NotionConnector: ConnectorSpec = {
2323
},
2424

2525
auth: {
26-
types: [
27-
'bearer',
28-
{
29-
type: 'oauth_authorization_code',
30-
defaults: {
31-
authorizationUrl: 'https://api.notion.com/v1/oauth/authorize',
32-
tokenUrl: 'https://api.notion.com/v1/oauth/token',
33-
useBasicAuth: true, // Notion requires HTTP Basic Auth for client credentials
34-
},
35-
},
36-
],
26+
types: ['bearer'],
3727
headers: {
3828
'Notion-Version': '2025-09-03',
3929
},

x-pack/platform/plugins/shared/actions/public/plugin.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface ActionsPublicPluginSetup {
1616
): ValidatedEmail[];
1717
enabledEmailServices: string[];
1818
isWebhookSslWithPfxEnabled?: boolean;
19+
authorizationCodeEnabled?: boolean;
1920
}
2021

2122
export interface Config {
@@ -32,18 +33,25 @@ export interface Config {
3233
};
3334
};
3435
};
36+
auth: {
37+
oauth_authorization_code: {
38+
enabled: boolean;
39+
};
40+
};
3541
}
3642

3743
export class Plugin implements CorePlugin<ActionsPublicPluginSetup> {
3844
private readonly allowedEmailDomains: string[] | null = null;
3945
private readonly enabledEmailServices: string[];
4046
private readonly webhookSslWithPfxEnabled: boolean;
47+
private readonly authorizationCodeEnabled: boolean;
4148

4249
constructor(ctx: PluginInitializerContext<Config>) {
4350
const config = ctx.config.get();
4451
this.allowedEmailDomains = config.email?.domain_allowlist || null;
4552
this.enabledEmailServices = Array.from(new Set(config.email?.services?.enabled || ['*']));
4653
this.webhookSslWithPfxEnabled = config.webhook?.ssl.pfx.enabled ?? true;
54+
this.authorizationCodeEnabled = config.auth?.oauth_authorization_code.enabled ?? false;
4755
}
4856

4957
public setup(): ActionsPublicPluginSetup {
@@ -52,6 +60,7 @@ export class Plugin implements CorePlugin<ActionsPublicPluginSetup> {
5260
validateEmails(this.allowedEmailDomains, emails, options),
5361
enabledEmailServices: this.enabledEmailServices,
5462
isWebhookSslWithPfxEnabled: this.webhookSslWithPfxEnabled,
63+
authorizationCodeEnabled: this.authorizationCodeEnabled,
5564
};
5665
}
5766

x-pack/platform/plugins/shared/actions/server/actions_client/actions_client.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,11 @@ describe('create()', () => {
544544
authorize: { lookbackWindow: '1h', limit: 100 },
545545
callback: { lookbackWindow: '1h', limit: 100 },
546546
},
547+
auth: {
548+
oauth_authorization_code: {
549+
enabled: false,
550+
},
551+
},
547552
});
548553

549554
const localActionTypeRegistryParams = {

x-pack/platform/plugins/shared/actions/server/actions_client/actions_client.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export interface ConstructorOptions {
122122
spaces?: SpacesServiceSetup;
123123
isESOCanEncrypt: boolean;
124124
getCurrentUserProfileIdFromAPIKey?: (request: KibanaRequest) => Promise<string | undefined>;
125+
authorizationCodeEnabled?: boolean;
125126
}
126127

127128
export interface ActionsClientContext {
@@ -148,6 +149,7 @@ export interface ActionsClientContext {
148149
spaces?: SpacesServiceSetup;
149150
isESOCanEncrypt: boolean;
150151
getCurrentUserProfileIdFromAPIKey?: (request: KibanaRequest) => Promise<string | undefined>;
152+
authorizationCodeEnabled?: boolean;
151153
}
152154

153155
const noop = async (_request: KibanaRequest): Promise<string | undefined> => undefined;
@@ -177,6 +179,7 @@ export class ActionsClient {
177179
spaces,
178180
isESOCanEncrypt,
179181
getCurrentUserProfileIdFromAPIKey,
182+
authorizationCodeEnabled = false,
180183
}: ConstructorOptions) {
181184
this.context = {
182185
logger,
@@ -200,6 +203,7 @@ export class ActionsClient {
200203
spaces,
201204
isESOCanEncrypt,
202205
getCurrentUserProfileIdFromAPIKey: getCurrentUserProfileIdFromAPIKey ?? noop,
206+
authorizationCodeEnabled,
203207
};
204208
}
205209

@@ -439,6 +443,9 @@ export class ActionsClient {
439443
throw Boom.badRequest(`Failed to retrieve access token`);
440444
}
441445
} else if (type === 'authorization_code') {
446+
if (!this.context.authorizationCodeEnabled) {
447+
throw Boom.badRequest('OAuth authorization code flow is not enabled');
448+
}
442449
const tokenOpts = options as OAuthAuthorizationCodeParams;
443450
try {
444451
let authMode: AuthMode | undefined;

x-pack/platform/plugins/shared/actions/server/actions_config.mock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ const createActionsConfigMock = () => {
4747
getAwsSesConfig: jest.fn().mockReturnValue(null),
4848
getEnabledEmailServices: jest.fn().mockReturnValue(['*']),
4949
getMaxEmailBodyLength: jest.fn().mockReturnValue(DEFAULT_EMAIL_BODY_LENGTH),
50+
getActionsAuthTypeConfig: jest.fn().mockReturnValue({ authorizationCodeEnabled: false }),
5051
};
5152
return mocked;
5253
};

x-pack/platform/plugins/shared/actions/server/actions_config.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ const defaultActionsConfig: ActionsConfig = {
4646
authorize: { lookbackWindow: '1h', limit: 100 },
4747
callback: { lookbackWindow: '1h', limit: 100 },
4848
},
49+
auth: {
50+
oauth_authorization_code: {
51+
enabled: false,
52+
},
53+
},
4954
};
5055

5156
describe('ensureUriAllowed', () => {

x-pack/platform/plugins/shared/actions/server/actions_config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export interface ActionsConfigurationUtilities {
7575
getAwsSesConfig: () => AwsSesConfig;
7676
getEnabledEmailServices: () => string[];
7777
getMaxEmailBodyLength: () => number;
78+
getActionsAuthTypeConfig: () => { authorizationCodeEnabled: boolean };
7879
}
7980

8081
function allowListErrorMessage(field: AllowListingField, value: string) {
@@ -283,5 +284,11 @@ export function getActionsConfigurationUtilities(
283284
const nonNegativeLength = Math.max(0, configuredLength);
284285
return Math.min(nonNegativeLength, MAX_EMAIL_BODY_LENGTH);
285286
},
287+
getActionsAuthTypeConfig: () => {
288+
const authorizationCodeEnabled = config.auth?.oauth_authorization_code.enabled ?? false;
289+
return {
290+
authorizationCodeEnabled,
291+
};
292+
},
286293
};
287294
}

x-pack/platform/plugins/shared/actions/server/auth_types/register_auth_types.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,16 @@ import type { NormalizedAuthType } from '@kbn/connector-specs';
88
import { authTypeSpecs } from '@kbn/connector-specs';
99
import type { AuthTypeRegistry } from './auth_type_registry';
1010

11-
export function registerAuthTypes(registry: AuthTypeRegistry) {
11+
export function registerAuthTypes(
12+
registry: AuthTypeRegistry,
13+
{ authorizationCodeEnabled }: { authorizationCodeEnabled: boolean } = {
14+
authorizationCodeEnabled: false,
15+
}
16+
) {
1217
for (const spec of Object.values(authTypeSpecs)) {
18+
if (spec.id === 'oauth_authorization_code' && !authorizationCodeEnabled) {
19+
continue;
20+
}
1321
registry.register(spec as NormalizedAuthType);
1422
}
1523
}

x-pack/platform/plugins/shared/actions/server/config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,13 @@ export const configSchema = schema.object({
212212
})
213213
),
214214
rateLimiter: schema.maybe(rateLimiterSchema),
215+
auth: schema.maybe(
216+
schema.object({
217+
oauth_authorization_code: schema.object({
218+
enabled: schema.boolean({ defaultValue: false }),
219+
}),
220+
})
221+
),
215222
oAuthRateLimit: oAuthRateLimitSchema,
216223
});
217224

0 commit comments

Comments
 (0)