in src/watchdog/__init__.py [0:0]
def check_and_create_private_key(base_path=STATE_FILE_DIR):
# Creating RSA private keys is slow, so we will create one private key and allow mounts to share it.
# This means, however, that we have to include a locking mechanism to ensure that the private key is
# atomically created, as mounts occurring in parallel may try to create the key simultaneously.
# The key should have been created during mounting, but the watchdog will recreate the private key if
# it is missing.
key = get_private_key_path()
@contextmanager
def open_lock_file():
lock_file = os.path.join(base_path, "efs-utils-lock")
f = os.open(lock_file, os.O_CREAT | os.O_DSYNC | os.O_EXCL | os.O_RDWR)
try:
lock_file_contents = "PID: %s" % os.getpid()
os.write(f, lock_file_contents.encode("utf-8"))
yield f
finally:
os.close(f)
os.remove(lock_file)
def do_with_lock(function):
while True:
try:
with open_lock_file():
return function()
except OSError as e:
if e.errno == errno.EEXIST:
logging.info(
"Failed to take out private key creation lock, sleeping %s (s)"
% DEFAULT_TIMEOUT
)
time.sleep(DEFAULT_TIMEOUT)
else:
raise
def generate_key():
if os.path.isfile(key):
return
cmd = (
"openssl genpkey -algorithm RSA -out %s -pkeyopt rsa_keygen_bits:3072" % key
)
subprocess_call(cmd, "Failed to create private key")
read_only_mode = 0o400
os.chmod(key, read_only_mode)
do_with_lock(generate_key)
return key