-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgen-yang-module.py
232 lines (181 loc) · 7.72 KB
/
gen-yang-module.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
import re
import csv
import requests
import textwrap
import requests_cache
from io import StringIO
from datetime import datetime
# Metadata for the one YANG module produced by this script
MODULES = [
{
"csv_url": "https://www.iana.org/assignments/tls-parameters/tls-parameters-4.csv",
"spaced_name": "cipher-suite",
"hypenated_name": "cipher-suite",
"prefix": "tlscsa",
}
]
def create_module_begin(module, f):
# Define template for all four modules
PREAMBLE_TEMPLATE="""
module iana-tls-HNAME-algs {
yang-version 1.1;
namespace "urn:ietf:params:xml:ns:yang:iana-tls-HNAME-algs";
prefix PREFIX;
organization
"Internet Assigned Numbers Authority (IANA)";
contact
"Postal: ICANN
12025 Waterfront Drive, Suite 300
Los Angeles, CA 90094-2536
United States of America
Tel: +1 310 301 5800
Email: [email protected]";
description
"This module defines enumerations for the Cipher Suite
algorithms defined in the 'TLS Cipher Suites' sub-registry
of the 'Transport Layer Security (TLS) Parameters' registry
maintained by IANA.
Copyright (c) YEAR IETF Trust and the persons identified as
authors of the code. All rights reserved.
Redistribution and use in source and binary forms, with
or without modification, is permitted pursuant to, and
subject to the license terms contained in, the Revised
BSD License set forth in Section 4.c of the IETF Trust's
Legal Provisions Relating to IETF Documents
(https://trustee.ietf.org/license-info).
The initial version of this YANG module is part of RFC FFFF
(https://www.rfc-editor.org/info/rfcFFFF); see the RFC
itself for full legal notices.
All versions of this module are published by IANA at
https://www.iana.org/assignments/yang-parameters.";
revision DATE {
description
"This initial version of the module was created using
the script defined in RFC FFFF to reflect the contents
of the SNAME algorithms registry maintained by IANA.";
reference
"RFC FFFF: YANG Groupings for TLS Clients and TLS Servers";
}
typedef tls-HNAME-algorithm {
type enumeration {
"""
# Replacements
rep = {
"DATE": datetime.today().strftime('%Y-%m-%d'),
"YEAR": datetime.today().strftime('%Y'),
"SNAME": module["spaced_name"],
"HNAME": module["hypenated_name"],
"PREFIX": module["prefix"]
}
# Do the replacement
rep = dict((re.escape(k), v) for k, v in rep.items())
pattern = re.compile("|".join(rep.keys()))
text = pattern.sub(lambda m: rep[re.escape(m.group(0))], PREAMBLE_TEMPLATE)
# Write preamble into the file
f.write(text)
def create_module_body(module, f):
# Fetch the current CSV file from IANA
r = requests.get(module["csv_url"])
assert r.status_code == 200, "Could not get " + module["csv_url"]
# Parse each CSV line
with StringIO(r.text) as csv_file:
csv_reader = csv.DictReader(csv_file)
for row in csv_reader:
# Skip reserved algs
if row["Description"].startswith("Unassigned"):
continue
# Skip unassigned algs
if row["Description"].startswith("Reserved"):
continue
# Ensure this is the TLS line
assert row["Description"].startswith("TLS_"), "Unrecognized description: '" + row["Description"] + "'"
# Set the 'refs' and 'titles' lists
if row["Reference"] == "":
pass # skip when the Reference field is empty
else:
# There may be more than one ref
refs = row["Reference"][1:-1] # remove the '[' and ']' chars
refs = refs.split("][")
titles = []
for ref in refs:
# Ascertain the ref's title
if ref.startswith("RFC"):
# Fetch the current BIBTEX entry
bibtex_url="https://datatracker.ietf.org/doc/"+ ref.lower() + "/bibtex/"
r = requests.get(bibtex_url)
assert r.status_code == 200, "Could not GET " + bibtex_url
# Append to 'titles' value from the "title" line
for item in r.text.split("\n"):
if "title =" in item:
title = re.sub('.*{{(.*)}}.*', r'\g<1>', item)
if title.startswith("ECDHE\_PSK"):
title = re.sub("ECDHE\\\\_PSK", "ECDHE_PSK", title)
titles.append(re.sub('.*{{(.*)}}.*', r'\g<1>', title))
break
else:
raise Exception("RFC title not found")
# Insert a space: "RFCXXXX" --> "RFC XXXX"
index = refs.index(ref)
refs[index] = "RFC " + ref[3:]
elif ref == "IESG Action 2018-08-16":
# Rewrite the ref value
index = refs.index(ref)
refs[index] = "IESG Action"
# Let title be something descriptive
titles.append("IESG Action 2018-08-16")
elif ref == "draft-irtf-cfrg-aegis-aead-08":
# Manually set the draft's title
titles.append("The AEGIS Family of Authenticated Encryption Algorithms")
elif ref:
raise Exception(f'ref "{ref}" not found')
else:
raise Exception(f'ref missing: {row}')
# Write out the enum
f.write(f' enum {row["Description"]} {{\n');
if row["Recommended"] == 'N':
f.write(f' status deprecated;\n')
f.write(f' description\n')
description = f' "Enumeration for the \'{row["Description"]}\' algorithm.";'
description = textwrap.fill(description, width=69, subsequent_indent=" ")
f.write(f'{description}\n')
f.write(' reference\n')
f.write(' "')
if row["Reference"] == "":
f.write('Missing in IANA registry.')
else:
ref_len = len(refs)
for i in range(ref_len):
ref = refs[i]
f.write(f'{ref}:\n')
title = " " + titles[i]
if i == ref_len - 1:
title += '";'
title = textwrap.fill(title, width=69, subsequent_indent=" ")
f.write(f'{title}')
if i != ref_len - 1:
f.write('\n ')
f.write('\n')
f.write(' }\n')
def create_module_end(module, f):
# Close out the enumeration, typedef, and module
f.write(" }\n")
f.write(" description\n")
f.write(f' "An enumeration for TLS {module["spaced_name"]} algorithms.";\n')
f.write(" }\n")
f.write('\n')
f.write('}\n')
def create_module(module):
# Install cache for 8x speedup
requests_cache.install_cache()
# Ascertain yang module's name
yang_module_name = "iana-tls-" + module["hypenated_name"] + "-algs.yang"
# Create yang module file
with open(yang_module_name, "w") as f:
create_module_begin(module, f)
create_module_body(module, f)
create_module_end(module, f)
def main():
for module in MODULES:
create_module(module)
if __name__ == "__main__":
main()