Coverage for turvallisuusneuvonta/csaf/document.py: 94.85%
87 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-05 19:27:17 +00:00
« prev ^ index » next coverage.py v7.4.1, created at 2024-02-05 19:27:17 +00:00
1"""CSAF Document meta information model."""
3from __future__ import annotations
5from datetime import datetime
6from enum import Enum
7from typing import Annotated, List, Optional, no_type_check
9from pydantic import AnyUrl, BaseModel, Field, RootModel, field_validator
11from turvallisuusneuvonta.csaf.definitions import Acknowledgments, Lang, Notes, References, Version
14class Revision(BaseModel):
15 """
16 Contains all the information elements required to track the evolution of a CSAF document.
17 """
19 date: Annotated[
20 datetime,
21 Field(description='The date of the revision entry', title='Date of the revision'),
22 ]
23 number: Version
24 summary: Annotated[
25 str,
26 Field(
27 description='Holds a single non-empty string representing a short description of the changes.',
28 examples=['Initial version.'],
29 min_length=1,
30 title='Summary of the revision',
31 ),
32 ]
35class Tracking(BaseModel):
36 """
37 Is a container designated to hold all management attributes necessary to track a CSAF document as a whole.
38 """
40 aliases: Annotated[
41 Optional[List[Alias]],
42 Field(
43 description='Contains a list of alternate names for the same document.',
44 title='Aliases',
45 ),
46 ] = None
47 current_release_date: Annotated[
48 datetime,
49 Field(
50 description='The date when the current revision of this document was released',
51 title='Current release date',
52 ),
53 ]
54 generator: Annotated[
55 Optional[Generator],
56 Field(
57 description='Is a container to hold all elements related to the generation of the document.'
58 ' These items will reference when the document was actually created,'
59 ' including the date it was generated and the entity that generated it.',
60 title='Document generator',
61 ),
62 ] = None
63 id: Annotated[
64 str,
65 Field(
66 description='The ID is a simple label that provides for a wide range of numbering values, types,'
67 ' and schemes. Its value SHOULD be assigned and maintained by the original document'
68 ' issuing authority.',
69 examples=[
70 'Example Company - 2019-YH3234',
71 'RHBA-2019:0024',
72 'cisco-sa-20190513-secureboot',
73 ],
74 min_length=1,
75 title='Unique identifier for the document',
76 ),
77 ]
78 initial_release_date: Annotated[
79 datetime,
80 Field(
81 description='The date when this document was first published.',
82 title='Initial release date',
83 ),
84 ]
85 revision_history: Annotated[
86 List[Revision],
87 Field(
88 description='Holds one revision item for each version of the CSAF document, including the initial one.',
89 min_length=1,
90 title='Revision history',
91 ),
92 ]
93 status: Annotated[
94 DocumentStatus,
95 Field(
96 description='Defines the draft status of the document.',
97 title='Document status',
98 ),
99 ]
100 version: Version
102 @classmethod
103 @no_type_check
104 @field_validator('aliases', 'revision_history')
105 def check_len(cls, v):
106 if not v:
107 raise ValueError('mandatory element present but empty')
108 return v
111class AggregateSeverity(BaseModel):
112 """
113 Is a vehicle that is provided by the document producer to convey the urgency and criticality with which the one or
114 more vulnerabilities reported should be addressed. It is a document-level metric and applied to the document as a
115 whole — not any specific vulnerability. The range of values in this field is defined according to the document
116 producer's policies and procedures.
117 """
119 namespace: Annotated[
120 Optional[AnyUrl],
121 Field(
122 description='Points to the namespace so referenced.',
123 title='Namespace of aggregate severity',
124 ),
125 ] = None
126 text: Annotated[
127 str,
128 Field(
129 description='Provides a severity which is independent of - and in addition to - any other standard metric'
130 ' for determining the impact or severity of a given vulnerability (such as CVSS).',
131 examples=['Critical', 'Important', 'Moderate'],
132 min_length=1,
133 title='Text of aggregate severity',
134 ),
135 ]
138class CsafVersion(Enum):
139 """
140 Gives the version of the CSAF specification which the document was generated for.
141 """
143 version_2_0 = '2.0'
146class Label(Enum):
147 """
148 Provides the TLP label of the document.
149 """
151 AMBER = 'AMBER'
152 GREEN = 'GREEN'
153 RED = 'RED'
154 WHITE = 'WHITE'
157class TrafficLightProtocol(BaseModel):
158 """
159 Provides details about the TLP classification of the document.
160 """
162 label: Annotated[
163 Label,
164 Field(description='Provides the TLP label of the document.', title='Label of TLP'),
165 ]
166 url: Annotated[
167 Optional[AnyUrl],
168 Field(
169 description='Provides a URL where to find the textual description of the TLP version which is used in this'
170 ' document. Default is the URL to the definition by FIRST.',
171 examples=[
172 'https://www.us-cert.gov/tlp',
173 'https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Kritis/Merkblatt_TLP.pdf',
174 ],
175 title='URL of TLP version',
176 ),
177 ] = AnyUrl(url='https://www.first.org/tlp/')
180class Distribution(BaseModel):
181 """
182 Describe any constraints on how this document might be shared.
183 """
185 text: Annotated[
186 Optional[str],
187 Field(
188 description='Provides a textual description of additional constraints.',
189 examples=[
190 'Copyright 2021, Example Company, All Rights Reserved.',
191 'Distribute freely.',
192 'Share only on a need-to-know-basis only.',
193 ],
194 min_length=1,
195 title='Textual description',
196 ),
197 ] = None
198 tlp: Annotated[
199 Optional[TrafficLightProtocol],
200 Field(
201 description='Provides details about the TLP classification of the document.',
202 title='Traffic Light Protocol (TLP)',
203 ),
204 ] = None
207class PublisherCategory(Enum):
208 """
209 Provides information about the category of publisher releasing the document.
210 """
212 coordinator = 'coordinator'
213 discoverer = 'discoverer'
214 other = 'other'
215 translator = 'translator'
216 user = 'user'
217 vendor = 'vendor'
220class Publisher(BaseModel):
221 """
222 Provides information about the publisher of the document.
223 """
225 category: Annotated[
226 PublisherCategory,
227 Field(
228 description='Provides information about the category of publisher releasing the document.',
229 title='Category of publisher',
230 ),
231 ]
232 contact_details: Annotated[
233 Optional[str],
234 Field(
235 description='Information on how to contact the publisher, possibly including details such as web sites,'
236 ' email addresses, phone numbers, and postal mail addresses.',
237 examples=[
238 'Example Company can be reached at [email protected], or via our website'
239 ' at https://www.example.com/contact.'
240 ],
241 min_length=1,
242 title='Contact details',
243 ),
244 ] = None
245 issuing_authority: Annotated[
246 Optional[str],
247 Field(
248 description='Provides information about the authority of the issuing party to release the document,'
249 " in particular, the party's constituency and responsibilities or other obligations.",
250 min_length=1,
251 title='Issuing authority',
252 ),
253 ] = None
254 name: Annotated[
255 str,
256 Field(
257 description='Contains the name of the issuing party.',
258 examples=['BSI', 'Cisco PSIRT', 'Siemens ProductCERT'],
259 min_length=1,
260 title='Name of publisher',
261 ),
262 ]
263 namespace: Annotated[
264 AnyUrl,
265 Field(
266 description='Contains a URL which is under control of the issuing party and can be used as a globally'
267 ' unique identifier for that issuing party.',
268 examples=['https://csaf.io', 'https://www.example.com'],
269 title='Namespace of publisher',
270 ),
271 ]
274class Alias(
275 RootModel[
276 Annotated[
277 str,
278 Field(
279 description='Specifies a non-empty string that represents a distinct optional alternative ID used to'
280 ' refer to the document.',
281 examples=['CVE-2019-12345'],
282 min_length=1,
283 title='Alternate name',
284 ),
285 ]
286 ]
287):
288 pass
291class Engine(BaseModel):
292 """
293 Contains information about the engine that generated the CSAF document.
294 """
296 name: Annotated[
297 str,
298 Field(
299 description='Represents the name of the engine that generated the CSAF document.',
300 examples=['Red Hat rhsa-to-cvrf', 'Secvisogram', 'TVCE'],
301 min_length=1,
302 title='Engine name',
303 ),
304 ]
305 version: Annotated[
306 Optional[str],
307 Field(
308 description='Contains the version of the engine that generated the CSAF document.',
309 examples=['0.6.0', '1.0.0-beta+exp.sha.a1c44f85', '2'],
310 min_length=1,
311 title='Engine version',
312 ),
313 ] = None
316class Generator(BaseModel):
317 """
318 Is a container to hold all elements related to the generation of the document. These items will reference when
319 the document was actually created, including the date it was generated and the entity that generated it.
320 """
322 date: Annotated[
323 Optional[datetime],
324 Field(
325 description='This SHOULD be the current date that the document was generated. Because documents are'
326 ' often generated internally by a document producer and exist for a nonzero amount of time'
327 ' before being released, this field MAY be different from the Initial Release Date and'
328 ' Current Release Date.',
329 title='Date of document generation',
330 ),
331 ] = None
332 engine: Annotated[
333 Engine,
334 Field(
335 description='Contains information about the engine that generated the CSAF document.',
336 title='Engine of document generation',
337 ),
338 ]
341class DocumentStatus(Enum):
342 """
343 Defines the draft status of the document.
344 """
346 draft = 'draft'
347 final = 'final'
348 interim = 'interim'
351class RelationshipCategory(Enum):
352 """
353 Defines the category of relationship for the referenced component.
354 """
356 default_component_of = 'default_component_of'
357 external_component_of = 'external_component_of'
358 installed_on = 'installed_on'
359 installed_with = 'installed_with'
360 optional_component_of = 'optional_component_of'
363class Document(BaseModel):
364 """
365 Captures the meta-data about this document describing a particular set of security advisories.
366 """
368 acknowledgments: Annotated[
369 Optional[Acknowledgments],
370 Field(
371 description='Contains a list of acknowledgment elements associated with the whole document.',
372 title='Document acknowledgments',
373 ),
374 ] = None
375 aggregate_severity: Annotated[
376 Optional[AggregateSeverity],
377 Field(
378 description='Is a vehicle that is provided by the document producer to convey the urgency and'
379 ' criticality with which the one or more vulnerabilities reported should be addressed.'
380 ' It is a document-level metric and applied to the document as a whole'
381 ' — not any specific vulnerability. The range of values in this field is defined according'
382 " to the document producer's policies and procedures.",
383 title='Aggregate severity',
384 ),
385 ] = None
386 category: Annotated[
387 str,
388 Field(
389 description='Defines a short canonical name, chosen by the document producer, which will inform the end'
390 ' user as to the category of document.',
391 examples=[
392 'Example Company Security Notice',
393 'generic_csaf',
394 'security_advisory',
395 'vex',
396 ],
397 min_length=1,
398 title='Document category',
399 ),
400 ]
401 csaf_version: Annotated[
402 CsafVersion,
403 Field(
404 description='Gives the version of the CSAF specification which the document was generated for.',
405 title='CSAF version',
406 ),
407 ]
408 distribution: Annotated[
409 Optional[Distribution],
410 Field(
411 description='Describe any constraints on how this document might be shared.',
412 title='Rules for sharing document',
413 ),
414 ] = None
415 lang: Annotated[
416 Optional[Lang],
417 Field(
418 description='Identifies the language used by this document, corresponding to IETF BCP 47 / RFC 5646.',
419 title='Document language',
420 ),
421 ] = None
422 notes: Annotated[
423 Optional[Notes],
424 Field(
425 description='Holds notes associated with the whole document.',
426 title='Document notes',
427 ),
428 ] = None
429 publisher: Annotated[
430 Publisher,
431 Field(
432 description='Provides information about the publisher of the document.',
433 title='Publisher',
434 ),
435 ]
436 references: Annotated[
437 Optional[References],
438 Field(
439 description='Holds a list of references associated with the whole document.',
440 title='Document references',
441 ),
442 ] = None
443 source_lang: Annotated[
444 Optional[Lang],
445 Field(
446 description='If this copy of the document is a translation then the value of this property describes'
447 ' from which language this document was translated.',
448 title='Source language',
449 ),
450 ] = None
451 title: Annotated[
452 str,
453 Field(
454 description='This SHOULD be a canonical name for the document, and sufficiently unique to distinguish'
455 ' it from similar documents.',
456 examples=[
457 'Cisco IPv6 Crafted Packet Denial of Service Vulnerability',
458 'Example Company Cross-Site-Scripting Vulnerability in Example Generator',
459 ],
460 min_length=1,
461 title='Title of this document',
462 ),
463 ]
464 tracking: Annotated[
465 Tracking,
466 Field(
467 description='Is a container designated to hold all management attributes necessary to track a'
468 ' CSAF document as a whole.',
469 title='Tracking',
470 ),
471 ]
474Tracking.model_rebuild()