Skip to content

Commit

Permalink
modifying vault utils, separating the client + introducing cli and co…
Browse files Browse the repository at this point in the history
…nfig for server
  • Loading branch information
telliere committed Mar 20, 2024
1 parent 427341d commit b5c42e9
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 19 deletions.
18 changes: 11 additions & 7 deletions server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from tools.docker_utils import get_build_env_image_digests
from pyspiffe.spiffe_id.spiffe_id import SpiffeId

sys.path.append(os.path.expanduser("../"))
from tools.config.config import parse_configuration
from tools.cli.cli import parse_arguments
from utils.vault.vault_utils import (
vault_login,
write_client_policy,
Expand All @@ -20,11 +21,14 @@

app = Quart(__name__)

options = parse_arguments()
configuration = parse_configuration(options.config)

# Defining the trust domain (SPIRE Trust Domain)
trust_domain = "lumi-sd-dev"
trust_domain = configuration['spire-server']['trust-domain']

# Perform vault login, to be able to run later operations against vault
vault_login(get_server_identity_JWT(), "lumi-sd-server")
hvac_client = vault_login(configuration['vault']['url'], get_server_identity_JWT(), configuration['vault']['server-role'])


# Dummy endpoint that handles the registration of compute nodes.
Expand Down Expand Up @@ -73,7 +77,7 @@ async def handle_client_registration():
client_id = hashlib.sha256(client_id.encode()).hexdigest()[0:9]

# Write a policy to the vault to authorize the client to write secrets
write_client_policy(f"client_{client_id}")
write_client_policy(hvac_client, f"client_{client_id}")

# Create spiffeID out of this client id
agent_spiffeID = SpiffeId.parse(f"spiffe://{trust_domain}/c/{client_id}")
Expand All @@ -93,7 +97,7 @@ async def handle_client_registration():
)

# Write the role bound to the workload's spiffeID
write_client_role(f"client_{client_id}", workload_spiffeID)
write_client_role(hvac_client, f"client_{client_id}", workload_spiffeID)

# For each authorized container preparation process (Here, a list of docker container_preaparation image names)
for digest in get_build_env_image_digests():
Expand Down Expand Up @@ -223,10 +227,10 @@ async def handle_workload_creation():
compute_nodes_added[compute_node]["groups"] = groups_added

# Generate and create a policy that gives read-only access to the application's secret
write_user_policy(f"client_{client_id}", data["secret"])
write_user_policy(hvac_client, f"client_{client_id}", data["secret"])

# Generate and create a role bound to the policy and to the spiffeID
write_user_role(f"client_{client_id}", data["secret"], spiffeID)
write_user_role(hvac_client, f"client_{client_id}", data["secret"], spiffeID)

# Success
return {
Expand Down
20 changes: 20 additions & 0 deletions server/tools/cli/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import argparse

# Parse arguments from the cli
def parse_arguments():
"""Parse arguments from cli
Returns:
ArgumentParser: the ArgumentParser produced
"""
parser = argparse.ArgumentParser(description="CLI Optinons")

parser.add_argument(
"--config",
"-c",
type=str,
default="/tmp/hpcs-server.conf",
help="Configuration file (INI Format) (default: /tmp/hpcs-server.conf)",
)

return parser.parse_args()
19 changes: 19 additions & 0 deletions server/tools/config/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from configparser import ConfigParser, NoSectionError, NoOptionError

def parse_configuration(path : str):
config = ConfigParser()
config.read(path)

if not 'spire-server' in config:
raise NoSectionError("spire-server section missing, aborting")

if not 'vault' in config:
raise NoSectionError("vault section missing, aborting")

if not 'address' in config['spire-server'] or not 'port' in config['spire-server'] or not 'trust-domain' in config['spire-server']:
raise NoOptionError("'spire-server' section is incomplete, aborting")

if not 'url' in config['vault'] or not 'server-role' in config['vault']:
raise NoOptionError("'vault' section is incomplete, aborting")

return config
4 changes: 2 additions & 2 deletions utils/ship_a_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,15 +285,15 @@ def create_authorized_workloads(
)

# Login to the vault using client's certificate
vault_login(SVID, f"client_{client_id}")
hvac_client = vault_login(SVID, f"client_{client_id}")

# Prepare secret
secret = {}
with open(pem_path, "r") as pem:
secret["key"] = pem.read()

# Write secret to the vault
write_secret(secrets_path, secret)
write_secret(hvac_client, secrets_path, secret)

print(
f"Key successfully written to the vault. Users needs the role {user_role} to access the secret stored at {secrets_path}"
Expand Down
19 changes: 9 additions & 10 deletions utils/vault/vault_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@
from pyspiffe.svid.jwt_svid import JwtSvid
from pyspiffe.spiffe_id.spiffe_id import SpiffeId

client = hvac.Client(url="")


def vault_login(SVID: JwtSvid, client_id):
def vault_login(url : str, SVID: JwtSvid, client_id) -> hvac.Client :
"""Login to vault
Args:
SVID (JwtSvid): The client's certificate to perform mTLS via OIDC
client_id (str): client's id, which happens to be the name of the role bound to the client
"""
return client.auth.jwt.jwt_login(role=client_id, jwt=SVID.token)
client = hvac.Client(url=url)
client.auth.jwt.jwt_login(role=client_id, jwt=SVID.token)
return client


def write_client_policy(client_id: str):
def write_client_policy(client : hvac.Client, client_id: str):
"""Write a client write-only policy to vault
Args:
Expand All @@ -30,7 +29,7 @@ def write_client_policy(client_id: str):
return client.sys.create_or_update_acl_policy(name=f"{client_id}", policy=policy)


def write_client_role(client_id: str, spiffeID: SpiffeId):
def write_client_role(client : hvac.Client, client_id: str, spiffeID: SpiffeId):
"""Write a client role, mapping a "clientID" named role to a spiffeID
Args:
Expand All @@ -48,7 +47,7 @@ def write_client_role(client_id: str, spiffeID: SpiffeId):
)


def write_user_policy(client_id: str, application: str):
def write_user_policy(client : hvac.Client, client_id: str, application: str):
"""Write a user read-only policy to vault
Args:
Expand All @@ -66,7 +65,7 @@ def write_user_policy(client_id: str, application: str):
)


def write_user_role(client_id: str, application: str, spiffeID: SpiffeId):
def write_user_role(client : hvac.Client, client_id: str, application: str, spiffeID: SpiffeId):
"""Write a user role bounding a spiffeID to the read-only policy accessing the client's secret
Args:
Expand All @@ -85,7 +84,7 @@ def write_user_role(client_id: str, application: str, spiffeID: SpiffeId):
)


def write_secret(secrets_path: str, secret: any):
def write_secret(client : hvac.Client, secrets_path: str, secret: any):
"""Write a secret to the vault
Args:
Expand Down

0 comments on commit b5c42e9

Please sign in to comment.