1515 */
1616package org .metaeffekt .core .inventory .processor .report .model .aeaa ;
1717
18+ import lombok .Getter ;
1819import org .json .JSONArray ;
1920import org .json .JSONObject ;
2021import org .metaeffekt .core .inventory .processor .model .AbstractModelBase ;
2122import org .metaeffekt .core .inventory .processor .model .AdvisoryMetaData ;
2223import org .metaeffekt .core .inventory .processor .model .Artifact ;
2324import org .metaeffekt .core .inventory .processor .model .VulnerabilityMetaData ;
2425import org .metaeffekt .core .inventory .processor .report .model .aeaa .advisory .AeaaAdvisoryEntry ;
26+ import org .metaeffekt .core .inventory .processor .report .model .aeaa .mitre .AeaaCapecEntry ;
27+ import org .metaeffekt .core .inventory .processor .report .model .aeaa .mitre .AeaaCweEntry ;
2528import org .metaeffekt .core .inventory .processor .report .model .aeaa .store .*;
2629import org .slf4j .Logger ;
2730import org .slf4j .LoggerFactory ;
@@ -46,21 +49,23 @@ public abstract class AeaaMatchableDetailsAmbDataClass<AMB extends AbstractModel
4649 add (AdvisoryMetaData .Attribute .REFERENCED_VULNERABILITIES .getKey ());
4750 add (VulnerabilityMetaData .Attribute .REFERENCED_VULNERABILITIES .getKey ());
4851 add (AdvisoryMetaData .Attribute .REFERENCED_OTHER .getKey ());
52+ add (VulnerabilityMetaData .Attribute .WEAKNESS .getKey ());
53+ add (VulnerabilityMetaData .Attribute .WEAKNESS_DATA .getKey ());
54+ add (VulnerabilityMetaData .Attribute .CAPEC_DATA .getKey ());
4955 add (VulnerabilityMetaData .Attribute .REFERENCED_OTHER .getKey ());
5056
5157 add (AeaaInventoryAttribute .RETAINED_VULNERABLE_SOFTWARE_CONFIGURATIONS .getKey ());
5258 }};
5359
5460 protected final static Set <String > CONVERSION_KEYS_MAP = new HashSet <String >(AeaaAmbDataClass .CONVERSION_KEYS_MAP ) {{
55- add ("source" );
56- add ("sourceImplementation" );
57- add ("dataFillingSources" );
58- add ("matchingSources" );
59- add ("referencedIds" );
60- add ("referencedSecurityAdvisories" );
61- add ("referencedVulnerabilities" );
62- add ("referencedOtherIds" );
63- add ("retainedVulnerableSoftwareConfigurations" );
61+ addAll (Arrays .asList (
62+ "source" , "sourceImplementation" ,
63+ "dataFillingSources" , "matchingSources" ,
64+ "referencedIds" , // legacy property
65+ "referencedSecurityAdvisories" , "referencedVulnerabilities" , "referencedOtherIds" ,
66+ "cwe" , "cweData" , "capecData" ,
67+ "retainedVulnerableSoftwareConfigurations"
68+ ));
6469 }};
6570
6671 protected final Map <AeaaVulnerabilityTypeIdentifier <?>, Set <String >> referencedVulnerabilities = new HashMap <>();
@@ -80,8 +85,77 @@ public abstract class AeaaMatchableDetailsAmbDataClass<AMB extends AbstractModel
8085 */
8186 protected final Map <String , Set <Artifact >> affectedArtifacts = new HashMap <>();
8287
88+ @ Getter
89+ protected final List <AeaaCweEntry > weaknesses = new ArrayList <>();
90+ @ Getter
91+ protected final List <AeaaCapecEntry > attackPatterns = new ArrayList <>();
92+
8393 public abstract AeaaContentIdentifierStore .AeaaContentIdentifier getSourceIdentifier ();
8494
95+ public void addWeakness (String id ) {
96+ if (StringUtils .hasText (id )) this .addWeakness (new AeaaCweEntry (id ));
97+ }
98+
99+ public void addWeakness (Collection <String > ids ) {
100+ ids .forEach (this ::addWeakness );
101+ }
102+
103+ public Set <String > getWeaknessIds () {
104+ return getWeaknesses ().stream ().map (AeaaCweEntry ::getId ).collect (Collectors .toSet ());
105+ }
106+
107+ public void addWeakness (AeaaCweEntry weakness ) {
108+ if (weakness == null ) return ;
109+
110+ final AeaaCweEntry knownWeakness = findWeakness (weakness .getId ());
111+ if (knownWeakness == null ) {
112+ weaknesses .add (weakness );
113+ } else {
114+ if (StringUtils .isEmpty (knownWeakness .getName ())) {
115+ weaknesses .remove (knownWeakness );
116+ weaknesses .add (weakness );
117+ }
118+ }
119+
120+ this .addOtherReferencedId (AeaaOtherTypeStore .CWE , weakness .getId ());
121+ }
122+
123+ public AeaaCweEntry findWeakness (String id ) {
124+ return this .weaknesses .stream ()
125+ .filter (c -> c .getId ().equals (id ))
126+ .findFirst ().orElse (null );
127+ }
128+
129+ public void addAttackPattern (String id ) {
130+ if (StringUtils .hasText (id )) this .addAttackPattern (new AeaaCapecEntry (id ));
131+ }
132+
133+ public void addAttackPattern (AeaaCapecEntry attackPattern ) {
134+ if (attackPattern == null ) return ;
135+
136+ final AeaaCapecEntry knownAttackPattern = findAttackPattern (attackPattern .getId ());
137+ if (knownAttackPattern == null ) {
138+ attackPatterns .add (attackPattern );
139+ } else {
140+ if (StringUtils .isEmpty (knownAttackPattern .getName ())) {
141+ attackPatterns .remove (knownAttackPattern );
142+ attackPatterns .add (attackPattern );
143+ }
144+ }
145+
146+ this .addOtherReferencedId (AeaaOtherTypeStore .CAPEC , attackPattern .getId ());
147+ }
148+
149+ public Set <String > getAttackPatternIds () {
150+ return getAttackPatterns ().stream ().map (AeaaCapecEntry ::getId ).collect (Collectors .toSet ());
151+ }
152+
153+ public AeaaCapecEntry findAttackPattern (String id ) {
154+ return this .attackPatterns .stream ()
155+ .filter (c -> c .getId ().equals (id ))
156+ .findFirst ().orElse (null );
157+ }
158+
85159 public DC addMatchingSource (AeaaDataSourceIndicator matchingSource ) {
86160 try {
87161 this .matchingSources .add (matchingSource );
@@ -189,18 +263,7 @@ public DC removeAffectsArtifact(String key, Artifact artifact) {
189263 return (DC ) this ;
190264 }
191265
192- public Map <AeaaVulnerabilityTypeIdentifier <?>, Set <String >> getReferencedVulnerabilities () {
193- return referencedVulnerabilities ;
194- }
195-
196- public Map <AeaaAdvisoryTypeIdentifier <?>, Set <String >> getReferencedSecurityAdvisories () {
197- return referencedSecurityAdvisories ;
198- }
199-
200- public Map <AeaaOtherTypeIdentifier , Set <String >> getReferencedOtherIds () {
201- return referencedOtherIds ;
202- }
203- // START: MANAGE REFERENCED SECURITY ADVISORIES
266+ // START: MANAGE REFERENCED SECURITY ADVISORIES
204267
205268 public void addReferencedSecurityAdvisory (AeaaAdvisoryTypeIdentifier <?> source , String id ) {
206269 if (source == null || id == null ) {
@@ -339,6 +402,36 @@ public void removeOtherReferencedId(AeaaOtherTypeIdentifier source, String id) {
339402
340403 // END: MANAGE OTHER REFERENCED
341404
405+ public Map <AeaaVulnerabilityTypeIdentifier <?>, Set <String >> getReferencedVulnerabilities () {
406+ return referencedVulnerabilities ;
407+ }
408+
409+ public Map <AeaaAdvisoryTypeIdentifier <?>, Set <String >> getReferencedSecurityAdvisories () {
410+ return referencedSecurityAdvisories ;
411+ }
412+
413+ public Map <AeaaOtherTypeIdentifier , Set <String >> getReferencedOtherIds () {
414+ return referencedOtherIds ;
415+ }
416+
417+ public Set <String > getReferencedSecurityAdvisories (AeaaAdvisoryTypeIdentifier <?> source ) {
418+ synchronized (this .referencedSecurityAdvisories ) {
419+ return this .referencedSecurityAdvisories .getOrDefault (source , Collections .emptySet ());
420+ }
421+ }
422+
423+ public Set <String > getReferencedVulnerabilities (AeaaVulnerabilityTypeIdentifier <?> source ) {
424+ synchronized (this .referencedVulnerabilities ) {
425+ return this .referencedVulnerabilities .getOrDefault (source , Collections .emptySet ());
426+ }
427+ }
428+
429+ public Set <String > getReferencedOtherIds (AeaaOtherTypeIdentifier source ) {
430+ synchronized (this .referencedOtherIds ) {
431+ return this .referencedOtherIds .getOrDefault (source , Collections .emptySet ());
432+ }
433+ }
434+
342435 /* DATA TYPE CONVERSION METHODS */
343436
344437 @ Override
@@ -392,6 +485,26 @@ public void appendFromBaseModel(AMB amb) {
392485 .distinct ()
393486 .forEach (this ::addDataSourceFromSourceString );
394487 }
488+
489+ if (StringUtils .hasText (amb .get (VulnerabilityMetaData .Attribute .WEAKNESS_DATA ))) {
490+ for (AeaaCweEntry entry : AeaaCweEntry .fromJson (new JSONArray (amb .get (VulnerabilityMetaData .Attribute .WEAKNESS_DATA )))) {
491+ this .addWeakness (entry );
492+ }
493+ } else if (StringUtils .hasText (amb .get (VulnerabilityMetaData .Attribute .WEAKNESS ))) {
494+ this .addWeakness (Arrays .asList (amb .get (VulnerabilityMetaData .Attribute .WEAKNESS ).split (", ?" )));
495+ }
496+ for (String id : this .getReferencedOtherIds (AeaaOtherTypeStore .CWE )) {
497+ this .addWeakness (id );
498+ }
499+
500+ if (StringUtils .hasText (amb .get (VulnerabilityMetaData .Attribute .CAPEC_DATA ))) {
501+ for (AeaaCapecEntry entry : AeaaCapecEntry .fromJson (new JSONArray (amb .get (VulnerabilityMetaData .Attribute .CAPEC_DATA )))) {
502+ this .addAttackPattern (entry );
503+ }
504+ }
505+ for (String id : this .getReferencedOtherIds (AeaaOtherTypeStore .CAPEC )) {
506+ this .addAttackPattern (id );
507+ }
395508 }
396509
397510 @ Override
@@ -410,6 +523,23 @@ public void appendToBaseModel(AMB modelBase) {
410523 modelBase .set (AdvisoryMetaData .Attribute .REFERENCED_SECURITY_ADVISORIES .getKey (), null );
411524 }
412525
526+ if (!this .weaknesses .isEmpty ()) {
527+ modelBase .set (VulnerabilityMetaData .Attribute .WEAKNESS , String .join (", " , this .getWeaknessIds ()));
528+ } else {
529+ modelBase .set (VulnerabilityMetaData .Attribute .WEAKNESS , null );
530+ }
531+ if (!this .weaknesses .isEmpty ()) {
532+ modelBase .set (VulnerabilityMetaData .Attribute .WEAKNESS_DATA , new JSONArray (this .weaknesses .stream ().map (AeaaCweEntry ::toJson ).collect (Collectors .toList ())).toString ());
533+ } else {
534+ modelBase .set (VulnerabilityMetaData .Attribute .WEAKNESS_DATA , null );
535+ }
536+
537+ if (!this .attackPatterns .isEmpty ()) {
538+ modelBase .set (VulnerabilityMetaData .Attribute .CAPEC_DATA , new JSONArray (this .attackPatterns .stream ().map (AeaaCapecEntry ::toJson ).collect (Collectors .toList ())).toString ());
539+ } else {
540+ modelBase .set (VulnerabilityMetaData .Attribute .CAPEC_DATA , null );
541+ }
542+
413543 if (!this .referencedOtherIds .isEmpty ()) {
414544 modelBase .set (AdvisoryMetaData .Attribute .REFERENCED_OTHER .getKey (), AeaaContentIdentifierStore .toJson (this .referencedOtherIds ).toString ());
415545 } else {
@@ -468,6 +598,8 @@ public void appendFromDataClass(DC dataClass) {
468598
469599 this .addReferencedVulnerabilities (dataClass .getReferencedVulnerabilities ());
470600 this .addReferencedSecurityAdvisories (dataClass .getReferencedSecurityAdvisories ());
601+ dataClass .getWeaknesses ().forEach (this ::addWeakness );
602+ dataClass .getAttackPatterns ().forEach (this ::addAttackPattern );
471603 this .addOtherReferencedIds (dataClass .getReferencedOtherIds ());
472604
473605 this .matchingSources .addAll (dataClass .getMatchingSources ());
@@ -486,6 +618,22 @@ public void appendFromMap(Map<String, Object> input) {
486618 this .addReferencedSecurityAdvisories (AeaaAdvisoryTypeStore .get ().fromListMultipleReferencedIds ((List <Map <String , Object >>) input .get ("referencedSecurityAdvisories" )));
487619 }
488620
621+ for (String weakness : (Collection <String >) input .getOrDefault ("cwe" , Collections .EMPTY_SET )) {
622+ this .addWeakness (weakness );
623+ }
624+
625+ if (input .containsKey ("cweData" ) && input .get ("cweData" ) instanceof List ) {
626+ for (AeaaCweEntry entry : AeaaCweEntry .fromJson (new JSONArray ((List ) input .get ("cweData" )))) {
627+ this .addWeakness (entry );
628+ }
629+ }
630+
631+ if (input .get ("capecData" ) != null && input .get ("capecData" ) instanceof List ) {
632+ for (AeaaCapecEntry entry : AeaaCapecEntry .fromJson (new JSONArray ((List ) input .get ("capecData" )))) {
633+ this .addAttackPattern (entry );
634+ }
635+ }
636+
489637 if (input .containsKey ("referencedOtherIds" ) && input .get ("referencedOtherIds" ) instanceof List ) {
490638 this .addOtherReferencedIds (AeaaOtherTypeStore .get ().fromListMultipleReferencedIds ((List <Map <String , Object >>) input .get ("referencedOtherIds" )));
491639 }
@@ -525,6 +673,10 @@ public void appendToJson(JSONObject json) {
525673 if (!this .referencedSecurityAdvisories .isEmpty ()) {
526674 json .put ("referencedSecurityAdvisories" , AeaaContentIdentifierStore .toJson (this .referencedSecurityAdvisories ));
527675 }
676+
677+ json .put ("cweData" , new JSONArray (this .weaknesses .stream ().map (AeaaCweEntry ::toJson ).collect (Collectors .toList ())));
678+ json .put ("capecData" , new JSONArray (this .attackPatterns .stream ().map (AeaaCapecEntry ::toJson ).collect (Collectors .toList ())));
679+
528680 if (!this .referencedOtherIds .isEmpty ()) {
529681 json .put ("referencedOtherIds" , AeaaContentIdentifierStore .toJson (this .referencedOtherIds ));
530682 }
0 commit comments