@@ -15,6 +15,130 @@ import {
1515 generateInputId ,
1616} from './simplified_package_policy_helper' ;
1717
18+ /**
19+ * Minimal multi-template package fixture covering both shapes of the
20+ * deployment-mode annotation that drove https://github.com/elastic/kibana/issues/268930:
21+ *
22+ * - `otel`: a normal template with no `deployment_modes` annotation. Implicitly
23+ * allowed in both default and agentless modes.
24+ * - `apache-agentless`: a template marked agentless-only at the template level
25+ * (`deployment_modes.default.enabled = false`). Its `aws/s3` input is also
26+ * annotated `deployment_modes: ['agentless']` for good measure.
27+ * - `mixed`: a template with no template-level annotation but a per-input
28+ * annotation: `httpjson` is unannotated (allowed everywhere), `cel` is
29+ * annotated `deployment_modes: ['agentless']`.
30+ */
31+ const multiTemplatePkgInfo = {
32+ name : 'good_v3' ,
33+ title : 'Good v3' ,
34+ version : '1.0.0' ,
35+ description : 'Test package with multiple policy templates' ,
36+ type : 'integration' ,
37+ format_version : '3.0.0' ,
38+ owner : { github : 'elastic/fleet' } ,
39+ policy_templates : [
40+ {
41+ name : 'otel' ,
42+ title : 'OTel template' ,
43+ description : 'Default-allowed template' ,
44+ inputs : [ { type : 'otelcol' , title : 'OTel collector' , description : '' } ] ,
45+ multiple : true ,
46+ } ,
47+ {
48+ name : 'apache-agentless' ,
49+ title : 'Apache agentless template' ,
50+ description : 'Agentless-only template' ,
51+ deployment_modes : {
52+ agentless : { enabled : true } ,
53+ default : { enabled : false } ,
54+ } ,
55+ inputs : [
56+ {
57+ type : 'aws/s3' ,
58+ title : 'AWS S3' ,
59+ description : '' ,
60+ deployment_modes : [ 'agentless' ] ,
61+ } ,
62+ ] ,
63+ multiple : false ,
64+ } ,
65+ {
66+ name : 'mixed' ,
67+ title : 'Mixed template' ,
68+ description : 'Template with default-allowed and agentless-only inputs' ,
69+ inputs : [
70+ { type : 'httpjson' , title : 'HTTP JSON' , description : '' } ,
71+ {
72+ type : 'cel' ,
73+ title : 'CEL' ,
74+ description : '' ,
75+ deployment_modes : [ 'agentless' ] ,
76+ } ,
77+ ] ,
78+ multiple : true ,
79+ } ,
80+ ] ,
81+ data_streams : [
82+ {
83+ type : 'logs' ,
84+ dataset : 'good_v3.otel_logs' ,
85+ title : 'OTel logs' ,
86+ release : 'ga' ,
87+ package : 'good_v3' ,
88+ ingest_pipeline : 'default' ,
89+ path : 'otel_logs' ,
90+ streams : [
91+ {
92+ input : 'otelcol' ,
93+ title : 'OTel logs stream' ,
94+ description : '' ,
95+ vars : [ ] ,
96+ template_path : '' ,
97+ } ,
98+ ] ,
99+ } ,
100+ {
101+ type : 'logs' ,
102+ dataset : 'good_v3.s3_logs' ,
103+ title : 'S3 logs' ,
104+ release : 'ga' ,
105+ package : 'good_v3' ,
106+ ingest_pipeline : 'default' ,
107+ path : 's3_logs' ,
108+ streams : [
109+ {
110+ input : 'aws/s3' ,
111+ title : 'S3 logs stream' ,
112+ description : '' ,
113+ vars : [ ] ,
114+ template_path : '' ,
115+ } ,
116+ ] ,
117+ } ,
118+ {
119+ type : 'logs' ,
120+ dataset : 'good_v3.cel_logs' ,
121+ title : 'CEL logs' ,
122+ release : 'ga' ,
123+ package : 'good_v3' ,
124+ ingest_pipeline : 'default' ,
125+ path : 'cel_logs' ,
126+ streams : [
127+ {
128+ input : 'cel' ,
129+ title : 'CEL logs stream' ,
130+ description : '' ,
131+ vars : [ ] ,
132+ template_path : '' ,
133+ } ,
134+ ] ,
135+ } ,
136+ ] ,
137+ latestVersion : '1.0.0' ,
138+ keepPoliciesUpToDate : false ,
139+ status : 'not_installed' ,
140+ } as unknown as PackageInfo ;
141+
18142function getEnabledInputsAndStreams ( newPackagePolicy : NewPackagePolicy ) {
19143 return newPackagePolicy . inputs
20144 . filter ( ( input ) => input . enabled )
@@ -250,4 +374,120 @@ describe('toPackagePolicy', () => {
250374 expect ( ( simplified as any ) . var_group_selections ) . toEqual ( varGroupSelections ) ;
251375 } ) ;
252376 } ) ;
377+
378+ /**
379+ * Regression tests for https://github.com/elastic/kibana/issues/268930.
380+ *
381+ * When a multi-policy-template package is used with the simplified API and
382+ * the resulting policy targets the default deployment mode, inputs that the
383+ * package spec marks as not allowed in default mode (either via a
384+ * template-level `deployment_modes.default.enabled = false` flag or a
385+ * per-input `deployment_modes: ['agentless']` annotation) must come out as
386+ * `enabled: false` so that `validateDeploymentModesForInputs` does not
387+ * reject the policy with a 400.
388+ *
389+ * Agentless mode is intentionally not subject to this filtering: that flow
390+ * already routes through an explicit `policy_template` and would not benefit.
391+ */
392+ describe ( 'default-mode filtering for multi-template packages' , ( ) => {
393+ it ( 'disables inputs from agentless-only templates when no inputs are listed' , ( ) => {
394+ const res = simplifiedPackagePolicytoNewPackagePolicy (
395+ {
396+ name : 'good-v3-defaults' ,
397+ namespace : 'default' ,
398+ policy_ids : [ 'policy123' ] ,
399+ } ,
400+ multiTemplatePkgInfo
401+ ) ;
402+
403+ const apacheInput = res . inputs . find ( ( input ) => input . policy_template === 'apache-agentless' ) ;
404+ expect ( apacheInput ) . toBeDefined ( ) ;
405+ expect ( apacheInput ?. enabled ) . toBe ( false ) ;
406+ } ) ;
407+
408+ it ( 'disables agentless-only inputs inside otherwise default-allowed templates' , ( ) => {
409+ const res = simplifiedPackagePolicytoNewPackagePolicy (
410+ {
411+ name : 'good-v3-defaults' ,
412+ namespace : 'default' ,
413+ policy_ids : [ 'policy123' ] ,
414+ } ,
415+ multiTemplatePkgInfo
416+ ) ;
417+
418+ const celInput = res . inputs . find (
419+ ( input ) => input . policy_template === 'mixed' && input . type === 'cel'
420+ ) ;
421+ const httpjsonInput = res . inputs . find (
422+ ( input ) => input . policy_template === 'mixed' && input . type === 'httpjson'
423+ ) ;
424+
425+ expect ( celInput ?. enabled ) . toBe ( false ) ;
426+ expect ( httpjsonInput ?. enabled ) . toBe ( true ) ;
427+ } ) ;
428+
429+ it ( 'keeps inputs without deployment_modes annotations enabled in default mode' , ( ) => {
430+ const res = simplifiedPackagePolicytoNewPackagePolicy (
431+ {
432+ name : 'good-v3-defaults' ,
433+ namespace : 'default' ,
434+ policy_ids : [ 'policy123' ] ,
435+ } ,
436+ multiTemplatePkgInfo
437+ ) ;
438+
439+ const otelInput = res . inputs . find ( ( input ) => input . policy_template === 'otel' ) ;
440+ expect ( otelInput ?. enabled ) . toBe ( true ) ;
441+ } ) ;
442+
443+ it ( 'disables streams of inputs filtered out by default-mode policy' , ( ) => {
444+ const res = simplifiedPackagePolicytoNewPackagePolicy (
445+ {
446+ name : 'good-v3-defaults' ,
447+ namespace : 'default' ,
448+ policy_ids : [ 'policy123' ] ,
449+ } ,
450+ multiTemplatePkgInfo
451+ ) ;
452+
453+ const apacheInput = res . inputs . find ( ( input ) => input . policy_template === 'apache-agentless' ) ;
454+ expect ( apacheInput ?. streams . length ) . toBeGreaterThan ( 0 ) ;
455+ expect ( apacheInput ?. streams . every ( ( stream ) => stream . enabled === false ) ) . toBe ( true ) ;
456+ } ) ;
457+
458+ it ( 'does not affect agentless policies (symmetric behavior intentionally omitted)' , ( ) => {
459+ const res = simplifiedPackagePolicytoNewPackagePolicy (
460+ {
461+ name : 'good-v3-agentless' ,
462+ namespace : 'default' ,
463+ policy_ids : [ 'policy123' ] ,
464+ supports_agentless : true ,
465+ } ,
466+ multiTemplatePkgInfo
467+ ) ;
468+
469+ const apacheInput = res . inputs . find ( ( input ) => input . policy_template === 'apache-agentless' ) ;
470+ const celInput = res . inputs . find (
471+ ( input ) => input . policy_template === 'mixed' && input . type === 'cel'
472+ ) ;
473+ expect ( apacheInput ?. enabled ) . toBe ( true ) ;
474+ expect ( celInput ?. enabled ) . toBe ( true ) ;
475+ } ) ;
476+
477+ it ( 'is a no-op for packages without deployment_modes annotations' , ( ) => {
478+ const res = simplifiedPackagePolicytoNewPackagePolicy (
479+ {
480+ name : 'nginx-1' ,
481+ namespace : 'default' ,
482+ policy_ids : [ 'policy123' ] ,
483+ } ,
484+ nginxPackageInfo as unknown as PackageInfo
485+ ) ;
486+
487+ expect ( getEnabledInputsAndStreams ( res ) ) . toEqual ( {
488+ 'nginx-logfile' : [ 'nginx.access' , 'nginx.error' ] ,
489+ 'nginx-nginx/metrics' : [ 'nginx.stubstatus' ] ,
490+ } ) ;
491+ } ) ;
492+ } ) ;
253493} ) ;
0 commit comments