| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2016 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2016 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Utility for generating experimental API tokens | 6 """Utility for generating experimental API tokens |
| 7 | 7 |
| 8 usage: generate_token.py [-h] [--key-file KEY_FILE] | 8 usage: generate_token.py [-h] [--key-file KEY_FILE] |
| 9 [--expire-days EXPIRE_DAYS | | 9 [--expire-days EXPIRE_DAYS | |
| 10 --expire-timestamp EXPIRE_TIMESTAMP] | 10 --expire-timestamp EXPIRE_TIMESTAMP] |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 import ed25519 | 28 import ed25519 |
| 29 | 29 |
| 30 | 30 |
| 31 # Matches a valid DNS name label (alphanumeric plus hyphens, except at the ends, | 31 # Matches a valid DNS name label (alphanumeric plus hyphens, except at the ends, |
| 32 # no longer than 63 ASCII characters) | 32 # no longer than 63 ASCII characters) |
| 33 DNS_LABEL_REGEX = re.compile(r"^(?!-)[a-z\d-]{1,63}(?<!-)$", re.IGNORECASE) | 33 DNS_LABEL_REGEX = re.compile(r"^(?!-)[a-z\d-]{1,63}(?<!-)$", re.IGNORECASE) |
| 34 | 34 |
| 35 # This script generates Version 2 tokens. | 35 # This script generates Version 2 tokens. |
| 36 VERSION = "\x02" | 36 VERSION = "\x02" |
| 37 | 37 |
| 38 # Default key file, relative to script_dir. |
| 39 DEFAULT_KEY_FILE = 'eftest.key' |
| 40 |
| 38 def HostnameFromArg(arg): | 41 def HostnameFromArg(arg): |
| 39 """Determines whether a string represents a valid hostname. | 42 """Determines whether a string represents a valid hostname. |
| 40 | 43 |
| 41 Returns the canonical hostname if its argument is valid, or None otherwise. | 44 Returns the canonical hostname if its argument is valid, or None otherwise. |
| 42 """ | 45 """ |
| 43 if not arg or len(arg) > 255: | 46 if not arg or len(arg) > 255: |
| 44 return None | 47 return None |
| 45 if arg[-1] == ".": | 48 if arg[-1] == ".": |
| 46 arg = arg[:-1] | 49 arg = arg[:-1] |
| 47 if "." not in arg and arg != "localhost": | 50 if "." not in arg and arg != "localhost": |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 91 return version + struct.pack(">I",len(data)) + data | 94 return version + struct.pack(">I",len(data)) + data |
| 92 | 95 |
| 93 def Sign(private_key, data): | 96 def Sign(private_key, data): |
| 94 return ed25519.signature(data, private_key[:32], private_key[32:]) | 97 return ed25519.signature(data, private_key[:32], private_key[32:]) |
| 95 | 98 |
| 96 def FormatToken(version, signature, data): | 99 def FormatToken(version, signature, data): |
| 97 return base64.b64encode(version + signature + | 100 return base64.b64encode(version + signature + |
| 98 struct.pack(">I",len(data)) + data) | 101 struct.pack(">I",len(data)) + data) |
| 99 | 102 |
| 100 def main(): | 103 def main(): |
| 104 default_key_file_absolute = os.path.join(script_dir, DEFAULT_KEY_FILE) |
| 105 |
| 101 parser = argparse.ArgumentParser( | 106 parser = argparse.ArgumentParser( |
| 102 description="Generate tokens for enabling experimental APIs") | 107 description="Generate tokens for enabling experimental APIs") |
| 103 parser.add_argument("origin", | 108 parser.add_argument("origin", |
| 104 help="Origin for which to enable the API. This can be " | 109 help="Origin for which to enable the API. This can be " |
| 105 "either a hostname (default scheme HTTPS, default " | 110 "either a hostname (default scheme HTTPS, default " |
| 106 "port 443) or a URL.", | 111 "port 443) or a URL.", |
| 107 type=OriginFromArg) | 112 type=OriginFromArg) |
| 108 parser.add_argument("trial_name", | 113 parser.add_argument("trial_name", |
| 109 help="Feature to enable. The current list of " | 114 help="Feature to enable. The current list of " |
| 110 "experimental feature trials can be found in " | 115 "experimental feature trials can be found in " |
| 111 "RuntimeFeatures.in") | 116 "RuntimeFeatures.in") |
| 112 parser.add_argument("--key-file", | 117 parser.add_argument("--key-file", |
| 113 help="Ed25519 private key file to sign the token with", | 118 help="Ed25519 private key file to sign the token with", |
| 114 default="eftest.key") | 119 default=default_key_file_absolute) |
| 115 expiry_group = parser.add_mutually_exclusive_group() | 120 expiry_group = parser.add_mutually_exclusive_group() |
| 116 expiry_group.add_argument("--expire-days", | 121 expiry_group.add_argument("--expire-days", |
| 117 help="Days from now when the token should exipire", | 122 help="Days from now when the token should exipire", |
| 118 type=int, | 123 type=int, |
| 119 default=42) | 124 default=42) |
| 120 expiry_group.add_argument("--expire-timestamp", | 125 expiry_group.add_argument("--expire-timestamp", |
| 121 help="Exact time (seconds since 1970-01-01 " | 126 help="Exact time (seconds since 1970-01-01 " |
| 122 "00:00:00 UTC) when the token should exipire", | 127 "00:00:00 UTC) when the token should exipire", |
| 123 type=int) | 128 type=int) |
| 124 | 129 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 154 print " Origin: %s" % args.origin | 159 print " Origin: %s" % args.origin |
| 155 print " Feature: %s" % args.trial_name | 160 print " Feature: %s" % args.trial_name |
| 156 print " Expiry: %d (%s UTC)" % (expiry, datetime.utcfromtimestamp(expiry)) | 161 print " Expiry: %d (%s UTC)" % (expiry, datetime.utcfromtimestamp(expiry)) |
| 157 print | 162 print |
| 158 | 163 |
| 159 # Output the properly-formatted token. | 164 # Output the properly-formatted token. |
| 160 print FormatToken(VERSION, signature, token_data) | 165 print FormatToken(VERSION, signature, token_data) |
| 161 | 166 |
| 162 if __name__ == "__main__": | 167 if __name__ == "__main__": |
| 163 main() | 168 main() |
| OLD | NEW |