in src/mount_efs/__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.
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:
check_and_remove_lock_file(lock_file, f)
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:
# errno.ENOENT: No such file or directory, errno.EBADF: Bad file descriptor
if e.errno == errno.ENOENT or e.errno == errno.EBADF:
logging.debug(
"lock file does not exist or Bad file descriptor, The file is already removed nothing to do."
)
else:
raise Exception(
"Could not remove lock file unexpected exception: %s", e
)
def generate_key():
if os.path.isfile(key):
# If the openssl genpkey command is interrupted or isn't successful,
# it will leave behind an empty file.
if os.path.getsize(key) == 0:
logging.warning("Purging empty private key file")
os.remove(key)
else:
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