Bumping manifests a=b2g-bump
[gecko.git] / build / pgo / genpgocert.py
blobc58bcd40d6963d6d370a2d44cf1d9608d545c114
1 #!/usr/bin/env python
2 # This Source Code Form is subject to the terms of the Mozilla Public
3 # License, v. 2.0. If a copy of the MPL was not distributed with this
4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
6 # This script exists to generate the Certificate Authority and server
7 # certificates used for SSL testing in Mochitest. The already generated
8 # certs are located at $topsrcdir/build/pgo/certs/ .
10 import mozinfo
11 import os
12 import random
13 import re
14 import shutil
15 import subprocess
16 import sys
17 import tempfile
19 from mozbuild.base import MozbuildObject
20 from mozfile import NamedTemporaryFile
21 from mozprofile.permissions import ServerLocations
23 dbFiles = [
24 re.compile("^cert[0-9]+\.db$"),
25 re.compile("^key[0-9]+\.db$"),
26 re.compile("^secmod\.db$")
29 def unlinkDbFiles(path):
30 for root, dirs, files in os.walk(path):
31 for name in files:
32 for dbFile in dbFiles:
33 if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
34 os.unlink(os.path.join(root, name))
36 def dbFilesExist(path):
37 for root, dirs, files in os.walk(path):
38 for name in files:
39 for dbFile in dbFiles:
40 if dbFile.match(name) and os.path.exists(os.path.join(root, name)):
41 return True
42 return False
45 def runUtil(util, args, inputdata = None):
46 env = os.environ.copy()
47 if mozinfo.os == "linux":
48 pathvar = "LD_LIBRARY_PATH"
49 app_path = os.path.dirname(util)
50 if pathvar in env:
51 env[pathvar] = "%s%s%s" % (app_path, os.pathsep, env[pathvar])
52 else:
53 env[pathvar] = app_path
54 proc = subprocess.Popen([util] + args, env=env,
55 stdin=subprocess.PIPE if inputdata else None)
56 proc.communicate(inputdata)
57 return proc.returncode
60 def createRandomFile(randomFile):
61 for count in xrange(0, 2048):
62 randomFile.write(chr(random.randint(0, 255)))
65 def createCertificateAuthority(build, srcDir):
66 certutil = build.get_binary_path(what="certutil")
67 pk12util = build.get_binary_path(what="pk12util")
69 #TODO: mozfile.TemporaryDirectory
70 tempDbDir = tempfile.mkdtemp()
71 with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
72 pgoCAModulePathSrc = os.path.join(srcDir, "pgoca.p12")
73 pgoCAPathSrc = os.path.join(srcDir, "pgoca.ca")
75 pwfile.write("\n")
77 # Create temporary certification database for CA generation
78 status = runUtil(certutil, ["-N", "-d", tempDbDir, "-f", pwfile.name])
79 if status:
80 return status
82 createRandomFile(rndfile)
83 status = runUtil(certutil, ["-S", "-d", tempDbDir, "-s", "CN=Temporary Certificate Authority, O=Mozilla Testing, OU=Profile Guided Optimization", "-t", "C,,", "-x", "-m", "1", "-v", "120", "-n", "pgo temporary ca", "-2", "-f", pwfile.name, "-z", rndfile.name], "Y\n0\nN\n")
84 if status:
85 return status
87 status = runUtil(certutil, ["-L", "-d", tempDbDir, "-n", "pgo temporary ca", "-a", "-o", pgoCAPathSrc, "-f", pwfile.name])
88 if status:
89 return status
91 status = runUtil(pk12util, ["-o", pgoCAModulePathSrc, "-n", "pgo temporary ca", "-d", tempDbDir, "-w", pwfile.name, "-k", pwfile.name])
92 if status:
93 return status
95 shutil.rmtree(tempDbDir)
96 return 0
99 def createSSLServerCertificate(build, srcDir):
100 certutil = build.get_binary_path(what="certutil")
101 pk12util = build.get_binary_path(what="pk12util")
103 with NamedTemporaryFile() as pwfile, NamedTemporaryFile() as rndfile:
104 pgoCAPath = os.path.join(srcDir, "pgoca.p12")
106 pwfile.write("\n")
108 if not dbFilesExist(srcDir):
109 # Make sure all DB files from src are really deleted
110 unlinkDbFiles(srcDir)
112 # Create certification database for ssltunnel
113 status = runUtil(certutil, ["-N", "-d", srcDir, "-f", pwfile.name])
114 if status:
115 return status
117 status = runUtil(pk12util, ["-i", pgoCAPath, "-w", pwfile.name, "-d", srcDir, "-k", pwfile.name])
118 if status:
119 return status
121 # Generate automatic certificate
122 locations = ServerLocations(os.path.join(build.topsrcdir,
123 "build", "pgo",
124 "server-locations.txt"))
125 iterator = iter(locations)
127 # Skips the first entry, I don't know why: bug 879740
128 iterator.next()
130 locationsParam = ""
131 firstLocation = ""
132 for loc in iterator:
133 if loc.scheme == "https" and "nocert" not in loc.options:
134 customCertOption = False
135 customCertRE = re.compile("^cert=(?:\w+)")
136 for option in loc.options:
137 match = customCertRE.match(option)
138 if match:
139 customCertOption = True
140 break
142 if not customCertOption:
143 if len(locationsParam) > 0:
144 locationsParam += ","
145 locationsParam += loc.host
147 if firstLocation == "":
148 firstLocation = loc.host
150 if not firstLocation:
151 print "Nothing to generate, no automatic secure hosts specified"
152 else:
153 createRandomFile(rndfile)
155 runUtil(certutil, ["-D", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
156 # Ignore the result, the certificate may not be present when new database is being built
158 status = runUtil(certutil, ["-S", "-s", "CN=%s" % firstLocation, "-t", "Pu,,", "-c", "pgo temporary ca", "-m", "2", "-8", locationsParam, "-v", "120", "-n", "pgo server certificate", "-d", srcDir, "-z", rndfile.name, "-f", pwfile.name])
159 if status:
160 return status
162 return 0
164 if len(sys.argv) == 1:
165 print "Specify --gen-server or --gen-ca"
166 sys.exit(1)
168 build = MozbuildObject.from_environment()
169 certdir = os.path.join(build.topsrcdir, "build", "pgo", "certs")
170 if sys.argv[1] == "--gen-server":
171 certificateStatus = createSSLServerCertificate(build, certdir)
172 if certificateStatus:
173 print "TEST-UNEXPECTED-FAIL | SSL Server Certificate generation"
175 sys.exit(certificateStatus)
177 if sys.argv[1] == "--gen-ca":
178 certificateStatus = createCertificateAuthority(build, certdir)
179 if certificateStatus:
180 print "TEST-UNEXPECTED-FAIL | Certificate Authority generation"
181 else:
182 print "\n\n"
183 print "==================================================="
184 print " IMPORTANT:"
185 print " To use this new certificate authority in tests"
186 print " run 'make' at testing/mochitest"
187 print "==================================================="
189 sys.exit(certificateStatus)
191 print "Invalid option specified"
192 sys.exit(1)