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