Coverage for turvallisuusneuvonta/csaf/document.py: 97.78%

88 statements  

« prev     ^ index     » next       coverage.py v7.0.3, created at 2023-01-07 19:14 +0100

1from __future__ import annotations 

2 

3"""CSAF Document meta information model.""" 

4from datetime import datetime 

5from enum import Enum 

6from typing import Annotated, List, Optional, no_type_check 

7 

8from pydantic import AnyUrl, BaseModel, Field, validator 

9 

10from turvallisuusneuvonta.csaf.definitions import Acknowledgments, Lang, Notes, References, Version 

11 

12 

13class Revision(BaseModel): 

14 """ 

15 Contains all the information elements required to track the evolution of a CSAF document. 

16 """ 

17 

18 date: Annotated[ 

19 datetime, 

20 Field(description='The date of the revision entry', title='Date of the revision'), 

21 ] 

22 number: Version 

23 summary: Annotated[ 

24 str, 

25 Field( 

26 description='Holds a single non-empty string representing a short description of the changes.', 

27 examples=['Initial version.'], 

28 min_length=1, 

29 title='Summary of the revision', 

30 ), 

31 ] 

32 

33 

34class Tracking(BaseModel): 

35 """ 

36 Is a container designated to hold all management attributes necessary to track a CSAF document as a whole. 

37 """ 

38 

39 aliases: Annotated[ 

40 Optional[List[Alias]], 

41 Field( 

42 description='Contains a list of alternate names for the same document.', 

43 min_items=1, 

44 title='Aliases', 

45 ), 

46 ] 

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 ] 

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_items=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 

101 

102 @no_type_check 

103 @validator('revision_history') 

104 @classmethod 

105 def check_len(cls, v): 

106 if not v: 106 ↛ 107line 106 didn't jump to line 107, because the condition on line 106 was never true

107 raise ValueError('mandatory element present but empty') 

108 return v 

109 

110 

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 """ 

118 

119 namespace: Annotated[ 

120 Optional[AnyUrl], 

121 Field( 

122 description='Points to the namespace so referenced.', 

123 title='Namespace of aggregate severity', 

124 ), 

125 ] 

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 ] 

136 

137 

138class CsafVersion(Enum): 

139 """ 

140 Gives the version of the CSAF specification which the document was generated for. 

141 """ 

142 

143 version_2_0 = '2.0' 

144 

145 

146class Label(Enum): 

147 """ 

148 Provides the TLP label of the document. 

149 """ 

150 

151 AMBER = 'AMBER' 

152 GREEN = 'GREEN' 

153 RED = 'RED' 

154 WHITE = 'WHITE' 

155 

156 

157class TrafficLightProtocol(BaseModel): 

158 """ 

159 Provides details about the TLP classification of the document. 

160 """ 

161 

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/', host='www.first.org', scheme='https') 

178 

179 

180class Distribution(BaseModel): 

181 """ 

182 Describe any constraints on how this document might be shared. 

183 """ 

184 

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 ] 

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 ] 

205 

206 

207class PublisherCategory(Enum): 

208 """ 

209 Provides information about the category of publisher releasing the document. 

210 """ 

211 

212 coordinator = 'coordinator' 

213 discoverer = 'discoverer' 

214 other = 'other' 

215 translator = 'translator' 

216 user = 'user' 

217 vendor = 'vendor' 

218 

219 

220class Publisher(BaseModel): 

221 """ 

222 Provides information about the publisher of the document. 

223 """ 

224 

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 ] 

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 ] 

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 ] 

272 

273 

274class Alias(BaseModel): 

275 __root__: Annotated[ 

276 str, 

277 Field( 

278 description='Specifies a non-empty string that represents a distinct optional alternative ID used to' 

279 ' refer to the document.', 

280 examples=['CVE-2019-12345'], 

281 min_length=1, 

282 title='Alternate name', 

283 ), 

284 ] 

285 

286 

287class Engine(BaseModel): 

288 """ 

289 Contains information about the engine that generated the CSAF document. 

290 """ 

291 

292 name: Annotated[ 

293 str, 

294 Field( 

295 description='Represents the name of the engine that generated the CSAF document.', 

296 examples=['Red Hat rhsa-to-cvrf', 'Secvisogram', 'TVCE'], 

297 min_length=1, 

298 title='Engine name', 

299 ), 

300 ] 

301 version: Annotated[ 

302 Optional[str], 

303 Field( 

304 description='Contains the version of the engine that generated the CSAF document.', 

305 examples=['0.6.0', '1.0.0-beta+exp.sha.a1c44f85', '2'], 

306 min_length=1, 

307 title='Engine version', 

308 ), 

309 ] 

310 

311 

312class Generator(BaseModel): 

313 """ 

314 Is a container to hold all elements related to the generation of the document. These items will reference when 

315 the document was actually created, including the date it was generated and the entity that generated it. 

316 """ 

317 

318 date: Annotated[ 

319 Optional[datetime], 

320 Field( 

321 description='This SHOULD be the current date that the document was generated. Because documents are' 

322 ' often generated internally by a document producer and exist for a nonzero amount of time' 

323 ' before being released, this field MAY be different from the Initial Release Date and' 

324 ' Current Release Date.', 

325 title='Date of document generation', 

326 ), 

327 ] 

328 engine: Annotated[ 

329 Engine, 

330 Field( 

331 description='Contains information about the engine that generated the CSAF document.', 

332 title='Engine of document generation', 

333 ), 

334 ] 

335 

336 

337class DocumentStatus(Enum): 

338 """ 

339 Defines the draft status of the document. 

340 """ 

341 

342 draft = 'draft' 

343 final = 'final' 

344 interim = 'interim' 

345 

346 

347class RelationshipCategory(Enum): 

348 """ 

349 Defines the category of relationship for the referenced component. 

350 """ 

351 

352 default_component_of = 'default_component_of' 

353 external_component_of = 'external_component_of' 

354 installed_on = 'installed_on' 

355 installed_with = 'installed_with' 

356 optional_component_of = 'optional_component_of' 

357 

358 

359class Document(BaseModel): 

360 """ 

361 Captures the meta-data about this document describing a particular set of security advisories. 

362 """ 

363 

364 acknowledgments: Annotated[ 

365 Optional[Acknowledgments], 

366 Field( 

367 description='Contains a list of acknowledgment elements associated with the whole document.', 

368 title='Document acknowledgments', 

369 ), 

370 ] 

371 aggregate_severity: Annotated[ 

372 Optional[AggregateSeverity], 

373 Field( 

374 description='Is a vehicle that is provided by the document producer to convey the urgency and' 

375 ' criticality with which the one or more vulnerabilities reported should be addressed.' 

376 ' It is a document-level metric and applied to the document as a whole' 

377 ' — not any specific vulnerability. The range of values in this field is defined according' 

378 " to the document producer's policies and procedures.", 

379 title='Aggregate severity', 

380 ), 

381 ] 

382 category: Annotated[ 

383 str, 

384 Field( 

385 description='Defines a short canonical name, chosen by the document producer, which will inform the end' 

386 ' user as to the category of document.', 

387 examples=[ 

388 'Example Company Security Notice', 

389 'generic_csaf', 

390 'security_advisory', 

391 'vex', 

392 ], 

393 min_length=1, 

394 title='Document category', 

395 ), 

396 ] 

397 csaf_version: Annotated[ 

398 CsafVersion, 

399 Field( 

400 description='Gives the version of the CSAF specification which the document was generated for.', 

401 title='CSAF version', 

402 ), 

403 ] 

404 distribution: Annotated[ 

405 Optional[Distribution], 

406 Field( 

407 description='Describe any constraints on how this document might be shared.', 

408 title='Rules for sharing document', 

409 ), 

410 ] 

411 lang: Annotated[ 

412 Optional[Lang], 

413 Field( 

414 description='Identifies the language used by this document, corresponding to IETF BCP 47 / RFC 5646.', 

415 title='Document language', 

416 ), 

417 ] 

418 notes: Annotated[ 

419 Optional[Notes], 

420 Field( 

421 description='Holds notes associated with the whole document.', 

422 title='Document notes', 

423 ), 

424 ] 

425 publisher: Annotated[ 

426 Publisher, 

427 Field( 

428 description='Provides information about the publisher of the document.', 

429 title='Publisher', 

430 ), 

431 ] 

432 references: Annotated[ 

433 Optional[References], 

434 Field( 

435 description='Holds a list of references associated with the whole document.', 

436 title='Document references', 

437 ), 

438 ] 

439 source_lang: Annotated[ 

440 Optional[Lang], 

441 Field( 

442 description='If this copy of the document is a translation then the value of this property describes' 

443 ' from which language this document was translated.', 

444 title='Source language', 

445 ), 

446 ] 

447 title: Annotated[ 

448 str, 

449 Field( 

450 description='This SHOULD be a canonical name for the document, and sufficiently unique to distinguish' 

451 ' it from similar documents.', 

452 examples=[ 

453 'Cisco IPv6 Crafted Packet Denial of Service Vulnerability', 

454 'Example Company Cross-Site-Scripting Vulnerability in Example Generator', 

455 ], 

456 min_length=1, 

457 title='Title of this document', 

458 ), 

459 ] 

460 tracking: Annotated[ 

461 Tracking, 

462 Field( 

463 description='Is a container designated to hold all management attributes necessary to track a' 

464 ' CSAF document as a whole.', 

465 title='Tracking', 

466 ), 

467 ] 

468 

469 

470Tracking.update_forward_refs()