-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: hashicorp nomad integration (#253)
* chore: bump react icons version * feat: add nomad service config * feat: add icon and docs link for nomad * feat: add service config for nomad * feat: add syncing utils for nomad * feat: add worker job code for nomad sync * feat: add query and mutation resolvers to nomad syncs * feat: add frontend queries and mutations * chore: regenerate graphql schema and types * feat: add dialog to setup nomad sync * feat: allow updating optional fields for sync auth * fix: move namespace to sync config, update auth test url * fix: add field for namespace in sync setup, add loading state when testing auth * fix: revert change to credential management dialog * fix: credential valid state * fix: rename nomad token var * fix: nomad_token_secret dict key * fix: update create nomad sync mutation args * fix: error message for no secrets * fix: menu overflow * feat: add namespace to service info
- Loading branch information
1 parent
7bf0409
commit ac09473
Showing
22 changed files
with
630 additions
and
22 deletions.
There are no files selected for viewing
18 changes: 18 additions & 0 deletions
18
backend/api/migrations/0064_alter_providercredentials_provider.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by Django 4.2.7 on 2024-05-13 09:16 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('api', '0063_lockbox'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='providercredentials', | ||
name='provider', | ||
field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_domad', 'Hashicorp Nomad')], max_length=50), | ||
), | ||
] |
18 changes: 18 additions & 0 deletions
18
backend/api/migrations/0065_alter_providercredentials_provider.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by Django 4.2.7 on 2024-05-13 09:19 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('api', '0064_alter_providercredentials_provider'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='providercredentials', | ||
name='provider', | ||
field=models.CharField(choices=[('cloudflare', 'Cloudflare'), ('aws', 'AWS'), ('github', 'GitHub'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad')], max_length=50), | ||
), | ||
] |
18 changes: 18 additions & 0 deletions
18
backend/api/migrations/0066_alter_environmentsync_service.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by Django 4.2.7 on 2024-05-13 12:09 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('api', '0065_alter_providercredentials_provider'), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name='environmentsync', | ||
name='service', | ||
field=models.CharField(choices=[('cloudflare_pages', 'Cloudflare Pages'), ('aws_secrets_manager', 'AWS Secrets Manager'), ('github_actions', 'GitHub Actions'), ('hashicorp_vault', 'Hashicorp Vault'), ('hashicorp_nomad', 'Hashicorp Nomad')], max_length=50), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
from api.utils.syncing.auth import get_credentials | ||
import requests | ||
import re | ||
|
||
|
||
def get_nomad_token_info(credential_id): | ||
"""Get info for a given nomad token.""" | ||
|
||
credentials = get_credentials(credential_id) | ||
|
||
NOMAD_ADDR = credentials["nomad_addr"] | ||
NOMAD_TOKEN = credentials["nomad_token_secret"] | ||
|
||
session = requests.Session() | ||
session.headers.update( | ||
{ | ||
"Authorization": f"Bearer {NOMAD_TOKEN}", | ||
"Content-Type": "application/json", | ||
} | ||
) | ||
|
||
url = f"{NOMAD_ADDR}/v1/acl/token/self" | ||
response = session.get(url) | ||
response.raise_for_status() | ||
return response.json() | ||
|
||
|
||
def test_nomad_creds(credential_id): | ||
"""Test Nomad credentials by attempting to get token info.""" | ||
try: | ||
get_nomad_token_info(credential_id) | ||
return True | ||
except requests.HTTPError as e: | ||
return False | ||
|
||
|
||
def sync_nomad_secrets(secrets, credential_id, path, namespace="default"): | ||
results = {} | ||
|
||
if not secrets or len(secrets) == 0: | ||
results["error"] = "Error: No secrets to sync." | ||
return False, results | ||
|
||
try: | ||
secrets_dict = dict(secrets) | ||
|
||
# Regex to validate the path | ||
path_regex = re.compile(r"^[a-zA-Z0-9-_~/]{1,128}$") | ||
|
||
# Normalize and check the path | ||
safe_path = path.strip("/").replace("//", "/") | ||
if not path_regex.match(safe_path): | ||
raise ValueError( | ||
f"Invalid path: {safe_path}. Path must match the pattern [a-zA-Z0-9-_~/]{{1,128}}." | ||
) | ||
|
||
credentials = get_credentials(credential_id) | ||
|
||
NOMAD_ADDR = credentials["nomad_addr"] | ||
NOMAD_TOKEN = credentials["nomad_token_secret"] | ||
|
||
session = requests.Session() | ||
session.headers.update( | ||
{ | ||
"Authorization": f"Bearer {NOMAD_TOKEN}", | ||
"Content-Type": "application/json", | ||
} | ||
) | ||
|
||
url = f"{NOMAD_ADDR}/v1/var/{safe_path}?namespace={namespace}" | ||
|
||
# All secrets are included under the 'Items' field in the payload | ||
payload = { | ||
"Namespace": namespace, | ||
"Path": safe_path, | ||
"Items": secrets_dict, | ||
} | ||
|
||
response = session.put(url, json=payload) | ||
|
||
response.raise_for_status() | ||
|
||
success = True | ||
results["message"] = ( | ||
f"All secrets successfully synced to Nomad at path: {safe_path} in namespace: {namespace}." | ||
) | ||
|
||
except Exception as e: | ||
success = False | ||
results["error"] = f"An error occurred: {str(e)}" | ||
|
||
return success, results |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.