Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
ab3931d
new api connector
semd Dec 17, 2025
6ad1c19
test params form
semd Dec 17, 2025
49194ac
Merge remote-tracking branch 'upstream/main' into workflows/api_conne…
semd Dec 18, 2025
e0c80fb
Merge remote-tracking branch 'upstream/main' into workflows/api_conne…
semd Jan 8, 2026
293db76
api connector
semd Jan 12, 2026
010fdd2
introduce new http connector step
semd Jan 14, 2026
ca005d0
solve conflict
semd Jan 14, 2026
61e7393
fix types
semd Jan 14, 2026
c802a5f
fix isHttp type
semd Jan 14, 2026
8a97e42
Merge remote-tracking branch 'upstream/main' into workflows_http_conn…
semd Jan 16, 2026
3f2d452
fix tests
semd Jan 16, 2026
9c7b53b
new connector formalizations
semd Jan 16, 2026
325cb59
fix test
semd Jan 16, 2026
c8d72cc
fix more test
semd Jan 19, 2026
a184a54
fix test snapshot
semd Jan 19, 2026
bff3a33
fix jest test issue with eui assets logo
semd Jan 19, 2026
3216999
Merge remote-tracking branch 'upstream/main' into workflows_http_conn…
semd Jan 19, 2026
269f29c
Merge remote-tracking branch 'upstream/main' into workflows_http_conn…
semd Jan 21, 2026
f83eee5
remove timout param
semd Jan 21, 2026
b0642bd
Merge remote-tracking branch 'upstream/main' into workflows_http_conn…
semd Jan 21, 2026
90fd643
Merge remote-tracking branch 'refs/remotes/origin/workflows_http_conn…
semd Jan 21, 2026
daba7a4
fix tests
semd Jan 21, 2026
5567e0a
update snapshot
semd Jan 22, 2026
b49abea
solve conflict
semd Jan 22, 2026
5ded45c
Merge branch 'main' into workflows_http_connector
elasticmachine Jan 23, 2026
15b783b
Merge remote-tracking branch 'upstream/main' into workflows_http_conn…
semd Feb 2, 2026
2cc7ad2
Merge branch 'main' into workflows_http_connector
elasticmachine Feb 10, 2026
8441342
Merge remote-tracking branch 'upstream' into workflows_http_connector
semd Feb 11, 2026
d9c12ee
split regular action execute from system action execute
semd Feb 11, 2026
86f282c
improve SystemConnectorsMap tsDoc
semd Feb 11, 2026
5db1496
Merge remote-tracking branch 'refs/remotes/origin/workflows_http_conn…
semd Feb 11, 2026
7103c55
fix test
semd Feb 11, 2026
4b6bc88
solve conflicts
semd Feb 11, 2026
6f744c9
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 11, 2026
3fcc769
make params url to take precedence over config
semd Feb 11, 2026
8a799b9
Merge remote-tracking branch 'refs/remotes/origin/workflows_http_conn…
semd Feb 11, 2026
6013d6e
add keepAlive to httpAgent
semd Feb 12, 2026
a7fc502
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 12, 2026
bcf9e70
add ftr test for http connector
semd Feb 12, 2026
d01b0c8
add test for http connector
semd Feb 12, 2026
2c9136d
update http simulator
semd Feb 12, 2026
091e9ce
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Feb 12, 2026
d46dbbb
add keep-alive comment
semd Feb 16, 2026
e655bdd
conflict solved
semd Feb 16, 2026
280a1f0
Merge remote-tracking branch 'refs/remotes/origin/workflows_http_conn…
semd Feb 16, 2026
272496f
Merge branch 'main' into workflows_http_connector
elasticmachine Feb 19, 2026
c7b484d
solve conflicts
semd Feb 23, 2026
ace9f6d
Merge remote-tracking branch 'refs/remotes/origin/workflows_http_conn…
semd Feb 23, 2026
d1bc879
remove old impl
semd Feb 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -2885,6 +2885,11 @@ src/platform/packages/shared/kbn-connector-schemas/thehive @elastic/kibana-cases
/x-pack/platform/plugins/shared/stack_connectors/server/usage/inference @elastic/appex-ai-infra
/src/platform/packages/shared/kbn-connector-schemas/inference @elastic/appex-ai-infra @elastic/security-generative-ai @elastic/obs-ai-team

# HTTP
/x-pack/platform/plugins/shared/stack_connectors/public/connector_types/http @elastic/workflows-eng
/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/http @elastic/workflows-eng
/src/platform/packages/shared/kbn-connector-schemas/http @elastic/workflows-eng

# Token tracking
x-pack/platform/plugins/shared/actions/server/lib/token_tracking @elastic/security-generative-ai

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { i18n } from '@kbn/i18n';

export const CONNECTOR_ID = '.http';
export const CONNECTOR_ID_SYSTEM = '.http-system';

export const CONNECTOR_NAME = i18n.translate('connectors.http.title', {
defaultMessage: 'HTTP',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
export * from './constants';

export { ConfigSchema, ParamsSchema, HTTP_METHODS } from './schemas/latest';

export type {
ConnectorTypeConfigType,
ConnectorTypeSecretsType,
ActionParamsType,
HttpMethod,
} from './types/latest';
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { HttpStepImpl } from './http_step_impl';
export { ConfigSchema, HTTP_METHODS, ParamsSchema } from './v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import { z } from '@kbn/zod';
import { AuthConfiguration } from '../../common/auth';

export const HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'] as const;

export const HeadersSchema = z.record(z.string(), z.string());

export const ConfigSchema = z
.object({
url: z.string().url(),
headers: HeadersSchema.nullable().default(null),
hasAuth: AuthConfiguration.hasAuth,
authType: AuthConfiguration.authType,
certType: AuthConfiguration.certType,
ca: AuthConfiguration.ca,
verificationMode: AuthConfiguration.verificationMode,
accessTokenUrl: AuthConfiguration.accessTokenUrl,
clientId: AuthConfiguration.clientId,
scope: AuthConfiguration.scope,
additionalFields: AuthConfiguration.additionalFields,
})
.strict();

export const ParamsSchema = z
.object({
url: z.string().url().optional(),
path: z.string().optional(),
method: z.enum(HTTP_METHODS).default('GET'),
body: z.string().optional(),
query: z.record(z.string(), z.string()).optional(),
headers: z.record(z.string(), z.string()).optional(),
fetcher: z
.object({
skip_ssl_verification: z.boolean().optional(),
follow_redirects: z.boolean().optional(),
max_redirects: z.number().optional(),
keep_alive: z.boolean().optional(),
})
.optional(),
})
.strict();
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export type {
ConnectorTypeConfigType,
ConnectorTypeSecretsType,
ActionParamsType,
HttpMethod,
} from './v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
import type { z } from '@kbn/zod';
import type { SecretConfigurationSchema } from '../../common/auth';
import type { ConfigSchema, HTTP_METHODS, ParamsSchema } from '../schemas/v1';

// http method definition
export type HttpMethod = (typeof HTTP_METHODS)[number];

// config definition
export type ConnectorTypeConfigType = z.infer<typeof ConfigSchema>;

// secrets definition
export type ConnectorTypeSecretsType = z.infer<typeof SecretConfigurationSchema>;

// params definition
export type ActionParamsType = z.infer<typeof ParamsSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export { CONNECTOR_ID as D3SecurityConnectorTypeId } from './d3security';
export { CONNECTOR_ID as EmailConnectorTypeId } from './email';
export { CONNECTOR_ID as EsIndexConnectorTypeId } from './es_index';
export { CONNECTOR_ID as GeminiConnectorTypeId } from './gemini';
export { CONNECTOR_ID as HttpConnectorTypeId } from './http';
export { CONNECTOR_ID as InferenceConnectorTypeId } from './inference';
export { CONNECTOR_ID as JiraConnectorTypeId } from './jira';
export { CONNECTOR_ID as JiraServiceManagementConnectorTypeId } from './jira-service-management';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,11 @@ export const WORKFLOWS_UI_SHOW_EXECUTOR_SETTING_ID = 'workflows:ui:showExecutor:
* Feature flag ID for enabling / disabling the workflow execution stats bar UI
*/
export const WORKFLOW_EXECUTION_STATS_BAR_SETTING_ID = 'workflows:executionStatsBar:enabled';

/**
* Map of regular (saved object) connector types -> their system connector equivalents.
* Use this map to make the `connector-id` step config property optional for a given connector step type, allowing it to be executed via its linked system connector.
* Pre-requisite for this to work:
* - System connectors have empty config/secrets schemas. Make sure these system connectors are able to execute by receiving params alone.
*/
export const SystemConnectorsMap = new Map<string, string>([['.http', '.http-system']]);
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import type {
DataSetStep,
ElasticsearchStep,
ForEachStep,
HttpStep,
IfStep,
KibanaStep,
StepWithForeach,
Expand Down Expand Up @@ -50,7 +49,6 @@ import type {
ExitTimeoutZoneNode,
ExitTryBlockNode,
GraphNodeUnion,
HttpGraphNode,
KibanaGraphNode,
WaitGraphNode,
WorkflowGraphType,
Expand Down Expand Up @@ -142,10 +140,6 @@ function visitAbstractStep(currentStep: BaseStep, context: GraphBuildContext): W
return visitDataSetStep(currentStep as DataSetStep, context);
}

if ((currentStep as HttpStep).type === 'http') {
return visitHttpStep(currentStep as HttpStep, context);
}

if ((currentStep as ElasticsearchStep).type?.startsWith('elasticsearch.')) {
return visitElasticsearchStep(currentStep as ElasticsearchStep, context);
}
Expand Down Expand Up @@ -197,26 +191,6 @@ export function visitDataSetStep(
return graph;
}

export function visitHttpStep(
currentStep: HttpStep,
context: GraphBuildContext
): WorkflowGraphType {
const stepId = getStepId(currentStep, context);
const graph = createTypedGraph({ directed: true });
const httpNode: HttpGraphNode = {
id: getStepId(currentStep, context),
type: 'http',
stepId,
stepType: currentStep.type,
configuration: {
...currentStep,
},
};
graph.setNode(httpNode.id, httpNode);

return graph;
}

export function visitElasticsearchStep(
currentStep: ElasticsearchStep,
context: GraphBuildContext
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import type {
ConnectorStep,
ElasticsearchStep,
ForEachStep,
HttpStep,
IfStep,
KibanaStep,
WaitStep,
Expand All @@ -27,7 +26,6 @@ import type {
ExitConditionBranchNode,
ExitForeachNode,
ExitIfNode,
HttpGraphNode,
KibanaGraphNode,
WaitGraphNode,
} from '../../types';
Expand Down Expand Up @@ -149,80 +147,6 @@ describe('convertToWorkflowGraph', () => {
});
});

describe('http step', () => {
const workflowDefinition = {
steps: [
{
name: 'testAtomicStep1',
type: 'slack',
connectorId: 'slack',
with: {
message: 'Hello from atomic step 1',
},
} as ConnectorStep,
{
name: 'testHttpStep',
type: 'http',
with: {
url: 'https://api.example.com/test',
method: 'GET',
headers: {
Authorization: 'Bearer token',
},
timeout: '30s',
},
} as HttpStep,
{
name: 'testAtomicStep2',
type: 'slack',
connectorId: 'slack',
with: {
message: 'Hello from atomic step 2',
},
} as ConnectorStep,
],
} as Partial<WorkflowYaml>;

it('should return nodes for http step in correct topological order', () => {
const executionGraph = convertToWorkflowGraph(workflowDefinition as any);
const topSort = graphlib.alg.topsort(executionGraph);
expect(topSort).toHaveLength(3);
expect(topSort).toEqual(['testAtomicStep1', 'testHttpStep', 'testAtomicStep2']);
});

it('should return correct edges for http step graph', () => {
const executionGraph = convertToWorkflowGraph(workflowDefinition as any);
const edges = executionGraph.edges();
expect(edges).toEqual([
{ v: 'testAtomicStep1', w: 'testHttpStep' },
{ v: 'testHttpStep', w: 'testAtomicStep2' },
]);
});

it('should configure the http step correctly', () => {
const executionGraph = convertToWorkflowGraph(workflowDefinition as any);
const node = executionGraph.node('testHttpStep');
expect(node).toEqual({
id: 'testHttpStep',
type: 'http',
stepId: 'testHttpStep',
stepType: 'http',
configuration: {
name: 'testHttpStep',
type: 'http',
with: {
url: 'https://api.example.com/test',
method: 'GET',
headers: {
Authorization: 'Bearer token',
},
timeout: '30s',
},
},
} as HttpGraphNode);
});
});

describe('if step', () => {
const workflowDefinition = {
steps: [
Expand Down
3 changes: 0 additions & 3 deletions src/platform/packages/shared/kbn-workflows/graph/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ export type {
ExitContinueNode,
WaitGraphNodeSchema,
WaitGraphNode,
HttpGraphNode,
HttpGraphNodeSchema,
EnterTryBlockNode,
ExitTryBlockNode,
EnterNormalPathNode,
Expand All @@ -51,7 +49,6 @@ export {
isDataSet,
isElasticsearch,
isKibana,
isHttp,
isWait,
isEnterForeach,
isEnterIf,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import type {
AtomicGraphNode,
DataSetGraphNode,
ElasticsearchGraphNode,
HttpGraphNode,
KibanaGraphNode,
WaitGraphNode,
} from './nodes/base';
Expand Down Expand Up @@ -44,8 +43,6 @@ export const isElasticsearch = (node: GraphNodeUnion): node is ElasticsearchGrap
export const isKibana = (node: GraphNodeUnion): node is KibanaGraphNode =>
node.type.startsWith('kibana.');

export const isHttp = (node: GraphNodeUnion): node is HttpGraphNode => node.type === 'http';

export const isWait = (node: GraphNodeUnion): node is WaitGraphNode => node.type === 'wait';

export const isDataSet = (node: GraphNodeUnion): node is DataSetGraphNode =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ export type {
AtomicGraphNodeSchema,
DataSetGraphNode,
DataSetGraphNodeSchema,
HttpGraphNode,
HttpGraphNodeSchema,
WaitGraphNode,
WaitGraphNodeSchema,
ElasticsearchGraphNode,
Expand Down Expand Up @@ -71,7 +69,6 @@ export {
isDataSet,
isElasticsearch,
isKibana,
isHttp,
isWait,
isEnterForeach,
isEnterIf,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { z } from '@kbn/zod/v4';
import {
DataSetStepSchema,
ElasticsearchStepSchema,
HttpStepSchema,
KibanaStepSchema,
WaitStepSchema,
} from '../../../spec/schema';
Expand Down Expand Up @@ -44,13 +43,6 @@ export const DataSetGraphNodeSchema = GraphNodeSchema.extend({
});
export type DataSetGraphNode = z.infer<typeof DataSetGraphNodeSchema>;

export const HttpGraphNodeSchema = GraphNodeSchema.extend({
id: z.string(),
type: z.literal('http'),
configuration: HttpStepSchema,
});
export type HttpGraphNode = z.infer<typeof HttpGraphNodeSchema>;

export const ElasticsearchGraphNodeSchema = GraphNodeSchema.extend({
id: z.string(),
type: z.string().refine((val) => val.startsWith('elasticsearch.'), {
Expand Down
Loading
Loading