make-sample-certs.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #!/usr/bin/env python3
  2. # Copyright 2022, gRPC Authors All rights reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import os
  16. import subprocess
  17. import datetime
  18. TEMPLATE = """\
  19. /*
  20. * Copyright {year}, gRPC Authors All rights reserved.
  21. *
  22. * Licensed under the Apache License, Version 2.0 (the "License");
  23. * you may not use this file except in compliance with the License.
  24. * You may obtain a copy of the License at
  25. *
  26. * http://www.apache.org/licenses/LICENSE-2.0
  27. *
  28. * Unless required by applicable law or agreed to in writing, software
  29. * distributed under the License is distributed on an "AS IS" BASIS,
  30. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  31. * See the License for the specific language governing permissions and
  32. * limitations under the License.
  33. */
  34. //-----------------------------------------------------------------------------
  35. // THIS FILE WAS GENERATED WITH make-sample-certs.py
  36. //
  37. // DO NOT UPDATE MANUALLY
  38. //-----------------------------------------------------------------------------
  39. #if canImport(NIOSSL)
  40. import struct Foundation.Date
  41. import NIOSSL
  42. /// Wraps `NIOSSLCertificate` to provide the certificate common name and expiry date.
  43. public struct SampleCertificate {{
  44. public var certificate: NIOSSLCertificate
  45. public var commonName: String
  46. public var notAfter: Date
  47. public static let ca = SampleCertificate(
  48. certificate: try! NIOSSLCertificate(bytes: .init(caCert.utf8), format: .pem),
  49. commonName: "some-ca",
  50. notAfter: Date(timeIntervalSince1970: {timestamp})
  51. )
  52. public static let otherCA = SampleCertificate(
  53. certificate: try! NIOSSLCertificate(bytes: .init(otherCACert.utf8), format: .pem),
  54. commonName: "some-other-ca",
  55. notAfter: Date(timeIntervalSince1970: {timestamp})
  56. )
  57. public static let server = SampleCertificate(
  58. certificate: try! NIOSSLCertificate(bytes: .init(serverCert.utf8), format: .pem),
  59. commonName: "localhost",
  60. notAfter: Date(timeIntervalSince1970: {timestamp})
  61. )
  62. public static let exampleServer = SampleCertificate(
  63. certificate: try! NIOSSLCertificate(bytes: .init(exampleServerCert.utf8), format: .pem),
  64. commonName: "example.com",
  65. notAfter: Date(timeIntervalSince1970: {timestamp})
  66. )
  67. public static let serverSignedByOtherCA = SampleCertificate(
  68. certificate: try! NIOSSLCertificate(bytes: .init(serverSignedByOtherCACert.utf8), format: .pem),
  69. commonName: "localhost",
  70. notAfter: Date(timeIntervalSince1970: {timestamp})
  71. )
  72. public static let client = SampleCertificate(
  73. certificate: try! NIOSSLCertificate(bytes: .init(clientCert.utf8), format: .pem),
  74. commonName: "localhost",
  75. notAfter: Date(timeIntervalSince1970: {timestamp})
  76. )
  77. public static let clientSignedByOtherCA = SampleCertificate(
  78. certificate: try! NIOSSLCertificate(bytes: .init(clientSignedByOtherCACert.utf8), format: .pem),
  79. commonName: "localhost",
  80. notAfter: Date(timeIntervalSince1970: {timestamp})
  81. )
  82. public static let exampleServerWithExplicitCurve = SampleCertificate(
  83. certificate: try! NIOSSLCertificate(bytes: .init(serverExplicitCurveCert.utf8), format: .pem),
  84. commonName: "localhost",
  85. notAfter: Date(timeIntervalSince1970: {timestamp})
  86. )
  87. }}
  88. extension SampleCertificate {{
  89. /// Returns whether the certificate has expired.
  90. public var isExpired: Bool {{
  91. return self.notAfter < Date()
  92. }}
  93. }}
  94. /// Provides convenience methods to make `NIOSSLPrivateKey`s for corresponding `GRPCSwiftCertificate`s.
  95. public struct SamplePrivateKey {{
  96. private init() {{}}
  97. public static let server = try! NIOSSLPrivateKey(bytes: .init(serverKey.utf8), format: .pem)
  98. public static let exampleServer = try! NIOSSLPrivateKey(
  99. bytes: .init(exampleServerKey.utf8),
  100. format: .pem
  101. )
  102. public static let client = try! NIOSSLPrivateKey(bytes: .init(clientKey.utf8), format: .pem)
  103. public static let exampleServerWithExplicitCurve = try! NIOSSLPrivateKey(
  104. bytes: .init(serverExplicitCurveKey.utf8),
  105. format: .pem
  106. )
  107. }}
  108. // MARK: - Certificates and private keys
  109. private let caCert = \"""
  110. {ca_cert}
  111. \"""
  112. private let otherCACert = \"""
  113. {other_ca_cert}
  114. \"""
  115. private let serverCert = \"""
  116. {server_cert}
  117. \"""
  118. private let serverSignedByOtherCACert = \"""
  119. {server_signed_by_other_ca_cert}
  120. \"""
  121. private let serverKey = \"""
  122. {server_key}
  123. \"""
  124. private let exampleServerCert = \"""
  125. {example_server_cert}
  126. \"""
  127. private let exampleServerKey = \"""
  128. {example_server_key}
  129. \"""
  130. private let clientCert = \"""
  131. {client_cert}
  132. \"""
  133. private let clientSignedByOtherCACert = \"""
  134. {client_signed_by_other_ca_cert}
  135. \"""
  136. private let clientKey = \"""
  137. {client_key}
  138. \"""
  139. private let serverExplicitCurveCert = \"""
  140. {server_explicit_curve_cert}
  141. \"""
  142. private let serverExplicitCurveKey = \"""
  143. {server_explicit_curve_key}
  144. \"""
  145. #endif // canImport(NIOSSL)
  146. """
  147. def load_file(root, name):
  148. with open(os.path.join(root, name)) as fh:
  149. return fh.read().strip()
  150. def extract_key(ec_key_and_params):
  151. lines = []
  152. include_line = True
  153. for line in ec_key_and_params.split("\n"):
  154. if line == "-----BEGIN EC PARAMETERS-----":
  155. include_line = False
  156. elif line == "-----BEGIN EC PRIVATE KEY-----":
  157. include_line = True
  158. if include_line:
  159. lines.append(line)
  160. return "\n".join(lines).strip()
  161. if __name__ == "__main__":
  162. now = datetime.datetime.now()
  163. # makecert uses an expiry of 365 days.
  164. delta = datetime.timedelta(days=365)
  165. # Seconds since epoch
  166. not_after = (now + delta).strftime("%s")
  167. # Expect to be called from the root of the checkout.
  168. root = os.path.abspath(os.curdir)
  169. executable = os.path.join(root, "scripts", "makecert")
  170. try:
  171. subprocess.check_call(executable)
  172. except FileNotFoundError:
  173. print("Please run the script from the root of the repository")
  174. exit(1)
  175. kwargs = {
  176. "year": now.year,
  177. "timestamp": not_after,
  178. "ca_cert": load_file(root, "ca.crt"),
  179. "other_ca_cert": load_file(root, "other-ca.crt"),
  180. "server_cert": load_file(root, "server-localhost.crt"),
  181. "server_signed_by_other_ca_cert": load_file(root, "server-localhost-other-ca.crt"),
  182. "server_key": load_file(root, "server-localhost.key"),
  183. "example_server_cert": load_file(root, "server-example.com.crt"),
  184. "example_server_key": load_file(root, "server-example.com.key"),
  185. "client_cert": load_file(root, "client.crt"),
  186. "client_signed_by_other_ca_cert": load_file(root, "client-other-ca.crt"),
  187. "client_key": load_file(root, "client.key"),
  188. "server_explicit_curve_cert": load_file(root, "server-explicit-ec.crt"),
  189. "server_explicit_curve_key": extract_key(load_file(root,
  190. "server-explicit-ec.key"))
  191. }
  192. formatted = TEMPLATE.format(**kwargs)
  193. with open("Sources/GRPCSampleData/GRPCSwiftCertificate.swift", "w") as fh:
  194. fh.write(formatted)