mirror of
https://github.com/zulip/zulip.git
synced 2025-11-13 18:36:36 +00:00
scripts: Make generate_secrets.py idempotent.
Now, generate_secrets.py will never overwrite existing secrets. In addition to being a safer model in generate, this fixes 2 significant issues: (1) It makes it much easier to preserve secrets like Oauth tokens in a development environment (previously, provision would destroy them). (2) It makes it possible to automatically add new secrets as part of the upgrade process. In particular, this is useful for the zulip_org_id settings. Fixes #4797.
This commit is contained in:
@@ -61,14 +61,7 @@ def get_old_conf(output_filename):
|
|||||||
secrets_file = six.moves.configparser.RawConfigParser() # type: ignore # https://github.com/python/typeshed/issues/307
|
secrets_file = six.moves.configparser.RawConfigParser() # type: ignore # https://github.com/python/typeshed/issues/307
|
||||||
secrets_file.read(output_filename)
|
secrets_file.read(output_filename)
|
||||||
|
|
||||||
def get_secret(key):
|
return dict(secrets_file.items("secrets"))
|
||||||
# type: (str) -> Optional[Text]
|
|
||||||
if secrets_file.has_option('secrets', key):
|
|
||||||
return secrets_file.get('secrets', key)
|
|
||||||
return None
|
|
||||||
|
|
||||||
fields = AUTOGENERATED_SETTINGS + ['secret_key', 'camo_key']
|
|
||||||
return {name: get_secret(name) for name in fields}
|
|
||||||
|
|
||||||
def generate_secrets(development=False):
|
def generate_secrets(development=False):
|
||||||
# type: (bool) -> None
|
# type: (bool) -> None
|
||||||
@@ -76,38 +69,49 @@ def generate_secrets(development=False):
|
|||||||
OUTPUT_SETTINGS_FILENAME = "zproject/dev-secrets.conf"
|
OUTPUT_SETTINGS_FILENAME = "zproject/dev-secrets.conf"
|
||||||
else:
|
else:
|
||||||
OUTPUT_SETTINGS_FILENAME = "/etc/zulip/zulip-secrets.conf"
|
OUTPUT_SETTINGS_FILENAME = "/etc/zulip/zulip-secrets.conf"
|
||||||
|
current_conf = get_old_conf(OUTPUT_SETTINGS_FILENAME)
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
if len(current_conf) == 0:
|
||||||
lines = [u'[secrets]\n']
|
lines = [u'[secrets]\n']
|
||||||
|
|
||||||
def config_line(var, value):
|
def need_secret(name):
|
||||||
# type: (Text, Text) -> Text
|
# type: (Text) -> bool
|
||||||
return "%s = %s\n" % (var, value)
|
return name not in current_conf
|
||||||
|
|
||||||
|
def add_secret(name, value):
|
||||||
|
# type: (Text, Text) -> None
|
||||||
|
lines.append("%s = %s\n" % (name, value))
|
||||||
|
current_conf[name] = value
|
||||||
|
|
||||||
old_conf = get_old_conf(OUTPUT_SETTINGS_FILENAME)
|
|
||||||
for name in AUTOGENERATED_SETTINGS:
|
for name in AUTOGENERATED_SETTINGS:
|
||||||
lines.append(config_line(name, old_conf.get(name, generate_random_token(64))))
|
if need_secret(name):
|
||||||
|
add_secret(name, generate_random_token(64))
|
||||||
|
|
||||||
secret_key = old_conf.get('secret_key', generate_django_secretkey())
|
if need_secret('secret_key'):
|
||||||
lines.append(config_line('secret_key', secret_key))
|
add_secret('secret_key', generate_django_secretkey())
|
||||||
|
|
||||||
camo_key = old_conf.get('camo_key', get_random_string(64))
|
if need_secret('camo_key'):
|
||||||
lines.append(config_line('camo_key', camo_key))
|
add_secret('camo_key', get_random_string(64))
|
||||||
|
|
||||||
zulip_org_key = old_conf.get('zulip_org_key', get_random_string(64))
|
if need_secret('zulip_org_key'):
|
||||||
lines.append(config_line('zulip_org_key', zulip_org_key))
|
add_secret('zulip_org_key', get_random_string(64))
|
||||||
|
if need_secret('zulip_org_id'):
|
||||||
zulip_org_id = old_conf.get('zulip_org_id', str(uuid.uuid4()))
|
add_secret('zulip_org_id', str(uuid.uuid4()))
|
||||||
lines.append(config_line('zulip_org_id', zulip_org_id))
|
|
||||||
|
|
||||||
if not development:
|
if not development:
|
||||||
# Write the Camo config file directly
|
# Write the Camo config file directly
|
||||||
generate_camo_config_file(camo_key)
|
generate_camo_config_file(current_conf['camo_key'])
|
||||||
|
|
||||||
out = open(OUTPUT_SETTINGS_FILENAME, 'w')
|
if len(lines) == 0:
|
||||||
|
print("generate_secrets: No new secrets to generate.")
|
||||||
|
return
|
||||||
|
|
||||||
|
out = open(OUTPUT_SETTINGS_FILENAME, 'a')
|
||||||
out.write(force_str("".join(lines)))
|
out.write(force_str("".join(lines)))
|
||||||
out.close()
|
out.close()
|
||||||
|
|
||||||
print("Generated %s with auto-generated secrets!" % (OUTPUT_SETTINGS_FILENAME,))
|
print("Generated new secrets in %s." % (OUTPUT_SETTINGS_FILENAME,))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user