Skip to content

Commit 9aa7e68

Browse files
authored
Implement file-based cloud authentication workaround (#1686)
Replace environment variable approach with temporary file solution: - Create secure.yml with cloud-specific password in /tmp - Copy existing clouds.yaml/yml to /tmp for openstack-image-manager access - Execute command with working directory changed to /tmp - Ensure cleanup of temporary files and directory restoration This workaround addresses limitations with environment variable injection for cloud profile authentication. AI-assisted: Claude Code Signed-off-by: Christian Berendt <[email protected]>
1 parent 8f40f8c commit 9aa7e68

File tree

1 file changed

+86
-44
lines changed

1 file changed

+86
-44
lines changed

osism/tasks/openstack.py

Lines changed: 86 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from celery import Celery
44
import os
5+
import shutil
56
import tempfile
67
import yaml
78
from loguru import logger
@@ -254,60 +255,101 @@ def image_manager(
254255
):
255256
command = "/usr/local/bin/openstack-image-manager"
256257

257-
# Prepare environment variables
258-
env = {}
258+
# Prepare temporary directory and files for cloud configuration
259+
temp_files_to_cleanup = []
260+
original_cwd = os.getcwd()
259261

260-
# Load and set OS_PASSWORD if cloud parameter is provided
261-
if cloud:
262-
password = get_cloud_password(cloud)
263-
if password:
264-
env["OS_PASSWORD"] = password
265-
else:
266-
logger.warning(
267-
f"Could not load password for cloud '{cloud}', continuing without OS_PASSWORD"
268-
)
269-
270-
if configs:
271-
with tempfile.TemporaryDirectory() as temp_dir:
272-
for config in configs:
273-
with tempfile.NamedTemporaryFile(
274-
mode="w+", suffix=".yml", dir=temp_dir, delete=False
275-
) as temp_file:
276-
temp_file.write(config)
277-
278-
sanitized_args = [
279-
arg for arg in arguments if not arg.startswith("--images=")
280-
]
262+
try:
263+
# Load and prepare cloud configuration if cloud parameter is provided
264+
if cloud:
265+
password = get_cloud_password(cloud)
266+
if password:
267+
# Create secure.yml in /tmp
268+
secure_yml_path = "/tmp/secure.yml"
269+
secure_yml_content = {
270+
"clouds": {cloud: {"auth": {"password": password}}}
271+
}
272+
273+
with open(secure_yml_path, "w") as f:
274+
yaml.dump(secure_yml_content, f)
275+
temp_files_to_cleanup.append(secure_yml_path)
276+
277+
# Try both .yaml and .yml extensions
278+
if os.path.exists("/etc/openstack/clouds.yaml"):
279+
shutil.copy2("/etc/openstack/clouds.yaml", "/tmp/clouds.yaml")
280+
temp_files_to_cleanup.append("/tmp/clouds.yaml")
281+
elif os.path.exists("/etc/openstack/clouds.yml"):
282+
shutil.copy2("/etc/openstack/clouds.yml", "/tmp/clouds.yml")
283+
temp_files_to_cleanup.append("/tmp/clouds.yml")
284+
else:
285+
logger.warning(
286+
"Could not find /etc/openstack/clouds.yaml or clouds.yml"
287+
)
288+
289+
# Change working directory to /tmp
290+
os.chdir("/tmp")
291+
else:
292+
logger.warning(
293+
f"Could not load password for cloud '{cloud}', continuing without cloud configuration"
294+
)
281295

282-
try:
283-
images_index = sanitized_args.index("--images")
284-
sanitized_args.pop(images_index)
285-
sanitized_args.pop(images_index)
286-
except ValueError:
287-
pass
288-
sanitized_args.extend(["--images", temp_dir])
296+
if configs:
297+
with tempfile.TemporaryDirectory() as temp_dir:
298+
for config in configs:
299+
with tempfile.NamedTemporaryFile(
300+
mode="w+", suffix=".yml", dir=temp_dir, delete=False
301+
) as temp_file:
302+
temp_file.write(config)
303+
304+
sanitized_args = [
305+
arg for arg in arguments if not arg.startswith("--images=")
306+
]
307+
308+
try:
309+
images_index = sanitized_args.index("--images")
310+
sanitized_args.pop(images_index)
311+
sanitized_args.pop(images_index)
312+
except ValueError:
313+
pass
314+
sanitized_args.extend(["--images", temp_dir])
315+
rc = run_command(
316+
self.request.id,
317+
command,
318+
{},
319+
*sanitized_args,
320+
publish=publish,
321+
locking=locking,
322+
auto_release_time=auto_release_time,
323+
ignore_env=ignore_env,
324+
)
325+
return rc
326+
else:
289327
rc = run_command(
290328
self.request.id,
291329
command,
292-
env,
293-
*sanitized_args,
330+
{},
331+
*arguments,
294332
publish=publish,
295333
locking=locking,
296334
auto_release_time=auto_release_time,
297335
ignore_env=ignore_env,
298336
)
299-
return rc
300-
else:
301-
return run_command(
302-
self.request.id,
303-
command,
304-
env,
305-
*arguments,
306-
publish=publish,
307-
locking=locking,
308-
auto_release_time=auto_release_time,
309-
ignore_env=ignore_env,
310-
)
337+
return rc
338+
339+
finally:
340+
# Clean up temporary files and restore working directory
341+
try:
342+
os.chdir(original_cwd)
343+
except Exception as exc:
344+
logger.warning(f"Could not restore original working directory: {exc}")
345+
346+
for temp_file in temp_files_to_cleanup:
347+
try:
348+
if os.path.exists(temp_file):
349+
os.remove(temp_file)
350+
logger.debug(f"Cleaned up temporary file: {temp_file}")
351+
except Exception as exc:
352+
logger.warning(f"Could not remove temporary file {temp_file}: {exc}")
311353

312354

313355
@app.task(bind=True, name="osism.tasks.openstack.flavor_manager")

0 commit comments

Comments
 (0)