Skip to content

Commit 80eb4c9

Browse files
authored
Merge pull request #6 from fabric-testbed/5-updating-permissions-to-handle-invalid-fabric_rc
5 updating permissions to handle invalid fabric rc
2 parents 8505ee6 + 501ffce commit 80eb4c9

File tree

2 files changed

+101
-67
lines changed

2 files changed

+101
-67
lines changed

jupyternb/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__VERSION__ = "1.3.6"
1+
__VERSION__ = "1.3.7"
22
__version__ = __VERSION__

jupyternb/jupyter_startup.py

+100-66
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,28 @@ def __init__(self):
107107
if self.config_json_location is None:
108108
self.config_json_location = self.DEFAULT_FABRIC_CONFIG_JSON_LOCATION
109109

110-
def create_config_dir(self):
110+
def create_config_dir(self, dir_only: bool = True):
111+
"""
112+
Create a configuration directory and optionally populate environment files.
113+
114+
This method creates a directory specified by `self.config_location` and optionally populates
115+
environment files based on environment variables. It sets up necessary configurations for
116+
Fabric operations including credentials, keys, logging settings, and SSH configurations.
117+
118+
:param dir_only: If True (default), only create the directory without populating environment files.
119+
If False, populate environment files based on configured environment variables.
120+
:type dir_only: bool
121+
:raises Exception: If there is an error during directory creation or file writing.
122+
"""
111123
try:
124+
# Create the configuration directory
112125
os.mkdir(self.config_location)
126+
127+
# If dir_only is True, return after creating the directory
128+
if dir_only:
129+
return
130+
131+
# Define environment variables with default or placeholder values
113132
environment_vars = {
114133
self.FABRIC_CREDMGR_HOST: os.environ[self.FABRIC_CREDMGR_HOST],
115134
self.FABRIC_ORCHESTRATOR_HOST: os.environ[self.FABRIC_ORCHESTRATOR_HOST],
@@ -123,29 +142,38 @@ def create_config_dir(self):
123142
self.FABRIC_LOG_LEVEL: self.DEFAULT_FABRIC_LOG_LEVEL,
124143
self.FABRIC_LOG_FILE: self.DEFAULT_FABRIC_LOG_FILE
125144
}
145+
146+
# Prepare string to write to environment file
126147
string_to_write = ""
127148
for key, value in environment_vars.items():
128-
if '<' in value and '>':
129-
string_to_write += f"#export {key}={value}\n"
149+
if '<' in value and '>' in value:
150+
string_to_write += f"#export {key}={value}\n" # Placeholder value comment
130151
else:
131-
string_to_write += f"export {key}={value}\n"
152+
string_to_write += f"export {key}={value}\n" # Actual value
132153

154+
# Write environment file atomically
133155
with atomic_write(f'{self.config_location}/fabric_rc', overwrite=True) as f:
134156
f.write(string_to_write)
135157

136-
string_to_write = f"UserKnownHostsFile /dev/null\n" \
137-
f"StrictHostKeyChecking no\n" \
138-
f"ServerAliveInterval 120 \n" \
139-
f"Host bastion-?.fabric-testbed.net\n" \
140-
f"User <Update Bastion User Name>\n" \
141-
f"ForwardAgent yes\n" \
142-
f"Hostname %h\n" \
143-
f"IdentityFile {self.config_location}/{os.environ[self.FABRIC_BASTION_PRIVATE_KEY_NAME]}\n" \
144-
f"IdentitiesOnly yes\n" \
145-
f"Host * !bastion-?.fabric-testbed.net\n" \
146-
f"ProxyJump <Update Bastion User Name>@{os.environ[self.FABRIC_BASTION_HOST]}:22\n"
158+
# Prepare SSH configuration string
159+
ssh_config_string = (
160+
f"UserKnownHostsFile /dev/null\n"
161+
f"StrictHostKeyChecking no\n"
162+
f"ServerAliveInterval 120 \n"
163+
f"Host bastion-?.fabric-testbed.net\n"
164+
f"User <Update Bastion User Name>\n"
165+
f"ForwardAgent yes\n"
166+
f"Hostname %h\n"
167+
f"IdentityFile {self.config_location}/{os.environ[self.FABRIC_BASTION_PRIVATE_KEY_NAME]}\n"
168+
f"IdentitiesOnly yes\n"
169+
f"Host * !bastion-?.fabric-testbed.net\n"
170+
f"ProxyJump <Update Bastion User Name>@{os.environ[self.FABRIC_BASTION_HOST]}:22\n"
171+
)
172+
173+
# Write SSH configuration file atomically
147174
with atomic_write(f'{self.config_location}/ssh_config', overwrite=True) as f:
148-
f.write(string_to_write)
175+
f.write(ssh_config_string)
176+
149177
except Exception as e:
150178
print("Failed to create config directory and default environment file")
151179
print("Exception: " + str(e))
@@ -269,36 +297,40 @@ def update_permissions(self):
269297
"""
270298
if not os.path.exists(f"{self.config_location}/fabric_rc"):
271299
return
272-
# Open the file in read mode
273-
with open(f"{self.config_location}/fabric_rc", 'r') as file:
274-
# Read the content of the file
275-
content = file.read()
276-
277-
# Split the content into lines
278-
lines = content.splitlines()
279-
280-
# Process each line to extract the environment variable and its value
281-
for line in lines:
282-
# Ignore empty lines or lines starting with '#' (comments)
283-
if line.strip() == '' or line.strip().startswith('#'):
284-
continue
285-
286-
# Split each line into variable and value using the first occurrence of '='
287-
variable, value = line.split('=', 1)
288-
variable = variable.replace("export", "")
289-
290-
# Remove leading/trailing whitespaces from the variable and value
291-
variable = variable.strip()
292-
value = value.strip()
293-
294-
if variable in [self.FABRIC_BASTION_KEY_LOCATION, self.FABRIC_SLICE_PRIVATE_KEY_FILE]:
295-
if os.path.exists(value):
296-
os.chmod(value, 0o600)
297-
elif variable in [self.FABRIC_SLICE_PUBLIC_KEY_FILE]:
298-
if os.path.exists(value):
299-
os.chmod(value, 0o644)
300-
301-
def initialize(self):
300+
try:
301+
# Open the file in read mode
302+
with open(f"{self.config_location}/fabric_rc", 'r') as file:
303+
# Read the content of the file
304+
content = file.read()
305+
306+
# Split the content into lines
307+
lines = content.splitlines()
308+
309+
# Process each line to extract the environment variable and its value
310+
for line in lines:
311+
# Ignore empty lines or lines starting with '#' (comments)
312+
if line.strip() == '' or line.strip().startswith('#'):
313+
continue
314+
315+
# Split each line into variable and value using the first occurrence of '='
316+
variable, value = line.split('=', 1)
317+
variable = variable.replace("export", "")
318+
319+
# Remove leading/trailing whitespaces from the variable and value
320+
variable = variable.strip()
321+
value = value.strip()
322+
323+
if variable in [self.FABRIC_BASTION_KEY_LOCATION, self.FABRIC_SLICE_PRIVATE_KEY_FILE]:
324+
if os.path.exists(value):
325+
os.chmod(value, 0o600)
326+
elif variable in [self.FABRIC_SLICE_PUBLIC_KEY_FILE]:
327+
if os.path.exists(value):
328+
os.chmod(value, 0o644)
329+
except Exception as e:
330+
print(f"Exception occurred while updating permissions: {e}")
331+
traceback.print_exc()
332+
333+
def initialize(self, sliver_keys: bool = False):
302334
"""
303335
Initialize Jupyter Notebook Container
304336
"""
@@ -310,7 +342,7 @@ def initialize(self):
310342

311343
if not os.path.exists(self.config_location):
312344
print("Creating config directory and all files")
313-
self.create_config_dir()
345+
self.create_config_dir(dir_only=True)
314346

315347
if not os.path.exists(self.requirements_location):
316348
print("Creating default requirements.txt")
@@ -324,28 +356,30 @@ def initialize(self):
324356
self.download_notebooks()
325357

326358
# Create SSH Keys
327-
ssh_key = FABRICSSHKey.generate(comment="fabric@localhost", algorithm="rsa")
328-
with atomic_write(f'{self.DEFAULT_PRIVATE_SSH_KEY}', overwrite=True) as f:
329-
f.write(ssh_key.private_key)
330-
with atomic_write(f'{self.DEFAULT_PUBLIC_SSH_KEY}', overwrite=True) as f:
331-
f.write(f'{ssh_key.name} {ssh_key.public_key} {ssh_key.comment}')
332-
333-
# Default key in config directory
334-
default_slice_priv_key_config = f'{self.config_location}/{os.environ[self.FABRIC_SLICE_PRIVATE_KEY_NAME]}'
335-
default_slice_pub_key_config = f'{self.config_location}/{os.environ[self.FABRIC_SLICE_PUBLIC_KEY_NAME]}'
336-
337-
if not os.path.exists(default_slice_priv_key_config):
338-
with atomic_write(default_slice_priv_key_config, overwrite=True) as f:
359+
# This is now made optional as JH notebook takes care of key creation
360+
if sliver_keys:
361+
ssh_key = FABRICSSHKey.generate(comment="fabric@localhost", algorithm="rsa")
362+
with atomic_write(f'{self.DEFAULT_PRIVATE_SSH_KEY}', overwrite=True) as f:
339363
f.write(ssh_key.private_key)
340-
341-
if not os.path.exists(default_slice_pub_key_config):
342-
with atomic_write(default_slice_pub_key_config, overwrite=True) as f:
364+
with atomic_write(f'{self.DEFAULT_PUBLIC_SSH_KEY}', overwrite=True) as f:
343365
f.write(f'{ssh_key.name} {ssh_key.public_key} {ssh_key.comment}')
344366

345-
os.chmod(self.DEFAULT_PRIVATE_SSH_KEY, 0o600)
346-
os.chmod(self.DEFAULT_PUBLIC_SSH_KEY, 0o644)
347-
os.chmod(default_slice_priv_key_config, 0o600)
348-
os.chmod(default_slice_pub_key_config, 0o644)
367+
# Default key in config directory
368+
default_slice_priv_key_config = f'{self.config_location}/{os.environ[self.FABRIC_SLICE_PRIVATE_KEY_NAME]}'
369+
default_slice_pub_key_config = f'{self.config_location}/{os.environ[self.FABRIC_SLICE_PUBLIC_KEY_NAME]}'
370+
371+
if not os.path.exists(default_slice_priv_key_config):
372+
with atomic_write(default_slice_priv_key_config, overwrite=True) as f:
373+
f.write(ssh_key.private_key)
374+
375+
if not os.path.exists(default_slice_pub_key_config):
376+
with atomic_write(default_slice_pub_key_config, overwrite=True) as f:
377+
f.write(f'{ssh_key.name} {ssh_key.public_key} {ssh_key.comment}')
378+
379+
os.chmod(self.DEFAULT_PRIVATE_SSH_KEY, 0o600)
380+
os.chmod(self.DEFAULT_PUBLIC_SSH_KEY, 0o644)
381+
os.chmod(default_slice_priv_key_config, 0o600)
382+
os.chmod(default_slice_pub_key_config, 0o644)
349383

350384
self.update_permissions()
351385
self.custom_install_packages()

0 commit comments

Comments
 (0)