Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable support for Vault secrets in Manifester #38

Merged
merged 2 commits into from
May 31, 2024

Conversation

synkd
Copy link
Collaborator

@synkd synkd commented Apr 26, 2024

A CI test failure in SatelliteQE/robottelo#14633 revealed that Manifester was unable to interpolate secrets stored in HashiCorp Vault. This PR adds support for Vault secrets based on Robottelo's implementation of Vault integration.

A CI test failure in SatelliteQE/robottelo#14633
revealed that Manifester was unable to interpolate secrets stored in
HashiCorp Vault. This PR adds support for Vault secrets based on
Robottelo's implementation of Vault integration.
@synkd synkd added the DRAFT Work in progress label Apr 26, 2024
@synkd synkd requested review from JacobCallahan and jyejare April 26, 2024 19:49
@@ -60,8 +60,13 @@ def delete(allocations, all_, remove_manifest_file):
uuid=allocation.get("uuid")
)
if remove_manifest_file:
manifester_directory = (
Path(os.environ["MANIFESTER_DIRECTORY"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might want to slap on a resolve here

Suggested change
Path(os.environ["MANIFESTER_DIRECTORY"])
Path(os.environ["MANIFESTER_DIRECTORY"]).resolve()

Comment on lines +254 to +260
manifester_directory = Path()

if "MANIFESTER_DIRECTORY" in os.environ:
envar_location = Path(os.environ["MANIFESTER_DIRECTORY"])
if envar_location.is_dir():
manifester_directory = envar_location
self.env_path = manifester_directory.joinpath(env_file)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These would likely be best done in a common place, like the settings module

Copy link
Collaborator Author

@synkd synkd May 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JacobCallahan This actually is done in the settings module, but I revisited this today and remembered why I had repeated it here: vault_login.py throws an error when trying to retrieve settings values if the user is not already logged in to Vault. If I'm understanding the situation correctly, vault_login.py imports helpers.py, in which it encounters an assignment that uses settings.get(), then dynaconf attempts to process the settings file, which includes a Vault-formatted setting (offline_token), and dynaconf subsequently tries to retrieve that value from Vault before the login process has completed. This is also why I had hard-coded the log level in this module, which you commented on as well.

There may be another way to work around this race condition, but I have not figured one out yet. Do you have any thoughts on an alternative, or alternatively, do you think my admittedly inelegant solution is acceptable?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm not ideal, but if it needs to be repeated anyway for the vault login then it's up to you whether that repetition happens here or in the vault script. I have no objections either way now.

@@ -2,7 +2,7 @@
import os
from pathlib import Path

from dynaconf import Dynaconf, Validator
from dynaconf import LazySettings, Validator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change was part of my initial debugging. In trying to determine why my Vault integration was failing, I tried matching the Robottelo implementation as closely as possible. I can revert this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah they're equivalent statements since Dynaconf is an alias to LazySettings. However, it's recommended to use Dynaconf here instead. Robottelo is likely just holding on to an old pattern (and should be changed).

https://github.com/dynaconf/dynaconf/blob/master/dynaconf/__init__.py#L28

from manifester.settings import settings

setup_logzero(level="info")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If switching to using the settings module, you can just use the configured log level

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at https://hvac.readthedocs.io/en/stable/usage/auth_methods/jwt-oidc.html#oidc-authorization-url-request, it should be possible to use pure Python implementation, using hvac, of vault login without needing to install vault CLI tool. It is something I have wanted to explore some time ago, but I never found time for it.
If you would like to dig into it, I would be happy to assist/help you.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm definitely interested in this as a possibility. I'll miss the next Automation Brainstorming meeting, but maybe we can discuss this at the following one.

@jyejare
Copy link
Member

jyejare commented Apr 30, 2024

@synkd What if we would have :

  1. Read the secret using robottelo's settings object.
  2. Pass the secret value using robottelo setting object to manifester functions wherever needed.

Hence we don't need to rewrite the code in manifester for vault integration.

Manifester being a standalone tool and since we are the only users of it, does not need to store/access the secrets from vault for now and its just a one secret.

@synkd
Copy link
Collaborator Author

synkd commented May 3, 2024

@jyejare I have been trying to avoid having Manifester depend directly on Robottelo. Although SatQE is currently the only group using Manifester, I think it has potential applications elsewhere as well. However, I'm open to discussion on the topic. Maybe we can discuss this at the Automation Brainstorming meeting in two weeks, along with Ondrej's suggestion above?

Copy link
Member

@JacobCallahan JacobCallahan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No major blocking recommendations remaining for me. However, I will say that manifester should never have robottelo as its dependency. This would result in a circular dependency between the two.

@synkd synkd force-pushed the integrate_vault_with_manifester branch from 8eac938 to 45588d7 Compare May 31, 2024 18:00
@synkd synkd merged commit 2f9263e into SatelliteQE:master May 31, 2024
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
DRAFT Work in progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants