blob: dec80da3e803509cefd4756405fe900a71f14822 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2016 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
Copybara854996b2021-09-07 19:36:02 +00004
5"""A set of functions that provide persistence for secret keys.
6
7These keys are used in generating XSRF tokens, calling the CAPTCHA API,
8and validating that inbound emails are replies to notifications that
9we sent.
10
11Unlike other data stored in Monorail, this is kept in the GAE
12datastore rather than SQL because (1) it never needs to be used in
13combination with other SQL data, and (2) we may want to replicate
14issue content for various off-line reporting functionality, but we
15will never want to do that with these keys. A copy is also kept in
16memcache for faster access.
17
18When no secrets are found, a new Secrets entity is created and initialized
19with randomly generated values for XSRF and email keys.
20
21If these secret values ever need to change:
22(1) Make the change on the Google Cloud Console in the Cloud Datastore tab.
23(2) Flush memcache.
24"""
25from __future__ import print_function
26from __future__ import division
27from __future__ import absolute_import
28
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010029import six
Copybara854996b2021-09-07 19:36:02 +000030
31from google.appengine.api import memcache
32from google.appengine.ext import ndb
33
Copybara854996b2021-09-07 19:36:02 +000034from framework import framework_helpers
35
36
37GLOBAL_KEY = 'secrets_singleton_key'
38
39
40class Secrets(ndb.Model):
41 """Model for representing secret keys."""
42 # Keys we use to generate tokens.
43 xsrf_key = ndb.StringProperty(required=True)
44 email_key = ndb.StringProperty(required=True)
45 pagination_key = ndb.StringProperty(required=True)
46
47
48def MakeSecrets():
49 """Make a new Secrets model with random values for keys."""
50 secrets = Secrets(id=GLOBAL_KEY)
51 secrets.xsrf_key = framework_helpers.MakeRandomKey()
52 secrets.email_key = framework_helpers.MakeRandomKey()
53 secrets.pagination_key = framework_helpers.MakeRandomKey()
54 return secrets
55
56
57def GetSecrets():
58 """Get secret keys from memcache or datastore. Or, make new ones."""
59 secrets = memcache.get(GLOBAL_KEY)
60 if secrets:
61 return secrets
62
63 secrets = Secrets.get_by_id(GLOBAL_KEY)
64 if not secrets:
65 secrets = MakeSecrets()
66 secrets.put()
67
68 memcache.set(GLOBAL_KEY, secrets)
69 return secrets
70
71
72def GetXSRFKey():
73 """Return a secret key string used to generate XSRF tokens."""
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010074 return six.ensure_binary(GetSecrets().xsrf_key)
Copybara854996b2021-09-07 19:36:02 +000075
76
77def GetEmailKey():
78 """Return a secret key string used to generate email tokens."""
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010079 return six.ensure_binary(GetSecrets().email_key)
Copybara854996b2021-09-07 19:36:02 +000080
81
82def GetPaginationKey():
83 """Return a secret key string used to generate pagination tokens."""
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010084 return six.ensure_binary(GetSecrets().pagination_key)