Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions examples/validator-vfn/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,25 @@ DEPLOY_FULLNODE=false
# Kubernetes Configuration (optional)
# NAMESPACE=movement-l1

# Validator Identity Secret
# Identity Secrets
#
# OPTION 1: Automatic - Use AWS Secrets Manager (Recommended)
# Store your validator keys in AWS Secrets Manager, and Terraform will automatically
# create the Kubernetes secret for you.
# Resolution order per identity (deploy fails if neither is set):
# 1. <PREFIX>_KEYS_SECRET_NAME → read from AWS Secrets Manager (preferred)
# 2. <PREFIX>_IDENTITY_FILE → read from local file (fallback)
#
# Steps:
# 1. Generate keys: aptos genesis generate-keys --output-dir ./keys
# 2. Store in AWS: aws secretsmanager create-secret \
# --name movement/validator-01/validator-identity \
# --secret-string file://keys/validator-identity.yaml
# 3. Set the secret name below
# If the ASM var is set, the local file is ignored. ASM failures are NOT caught —
# they error out instead of silently falling back, to avoid running with the
# wrong identity.
#
# Validator identity
# VALIDATOR_KEYS_SECRET_NAME=movement/validator-01/validator-identity
#
# OPTION 2: Manual - Create Kubernetes Secret Manually
# Leave VALIDATOR_KEYS_SECRET_NAME empty and create the secret manually:
# kubectl create namespace movement-l1
# kubectl create secret generic validator-identity \
# --from-file=validator-identity.yaml=./keys/validator-identity.yaml \
# -n movement-l1
#
# VALIDATOR_IDENTITY_FILE=./keys/validator-identity.yaml
VALIDATOR_KEYS_SECRET_NAME=
# This is K8s secrete name where used by k8s for indexing the secrets
# K8s Secret object name the chart mounts (rarely needs changing)
VALIDATOR_KEYS_SECRET=validator-identity

# VFN identity (only used when DEPLOY_VFN=true)
# VFN_KEYS_SECRET_NAME=movement/validator-01/vfn-identity
# VFN_IDENTITY_FILE=./keys/validator-full-node-identity.yaml
VFN_KEYS_SECRET_NAME=
VFN_KEYS_SECRET=vfn-identity
97 changes: 60 additions & 37 deletions examples/validator-vfn/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,17 @@ def create_validator_secret_from_aws_sm(
namespace: str,
secret_name: str,
aws_secret_name: str,
secret_key: str,
region: str,
profile: str | None = None,
) -> None:
"""Create Kubernetes secret from AWS Secrets Manager.

Args:
namespace: Kubernetes namespace
secret_name: Name for the Kubernetes secret
aws_secret_name: AWS Secrets Manager secret name
region: AWS region
profile: AWS profile to use (optional)
"""
"""Create Kubernetes secret from AWS Secrets Manager."""
try:
import boto3
from kubernetes import client, config

info(f"Reading validator identity from AWS Secrets Manager: {aws_secret_name}")
info(f"Reading identity from AWS Secrets Manager: {aws_secret_name}")

# Read from AWS Secrets Manager
if profile:
session = boto3.Session(profile_name=profile)
sm_client = session.client("secretsmanager", region_name=region)
Expand All @@ -64,11 +56,9 @@ def create_validator_secret_from_aws_sm(
response = sm_client.get_secret_value(SecretId=aws_secret_name)
secret_data = response["SecretString"]

# Connect to Kubernetes
config.load_kube_config()
v1 = client.CoreV1Api()

# Check if secret already exists
try:
v1.read_namespaced_secret(secret_name, namespace)
info(f" Secret '{secret_name}' already exists in namespace '{namespace}'")
Expand All @@ -77,10 +67,9 @@ def create_validator_secret_from_aws_sm(
if e.status != 404:
raise

# Create Kubernetes secret using string_data (no base64 encoding needed)
k8s_secret = client.V1Secret(
metadata=client.V1ObjectMeta(name=secret_name),
string_data={"validator-identity.yaml": secret_data},
string_data={secret_key: secret_data},
type="Opaque",
)

Expand Down Expand Up @@ -522,35 +511,69 @@ def deploy(env_vars: dict, force_create: bool, validate: bool, terraform_dir: Pa
eks.wait_until_active()
eks.update_kubeconfig()

# Step 1.5: Create identity secrets from local files
# Step 1.5: Create identity secrets — AWS Secrets Manager first, local file fallback
info("\n" + "=" * 80)
info("Creating Kubernetes Identity Secrets")
info("=" * 80)

# Validator identity secret
validator_identity_file = env_vars.get("VALIDATOR_IDENTITY_FILE", "")
if validator_identity_file:
create_identity_secret_from_local_file(
namespace=namespace,
secret_name=validator_keys_secret,
local_file_path=Path(validator_identity_file),
secret_key="validator-identity.yaml",
)
else:
info(f" No VALIDATOR_IDENTITY_FILE set (using existing K8s secret: {validator_keys_secret})")
def provision_identity(
label: str,
k8s_secret_name: str,
secret_key: str,
asm_env: str,
file_env: str,
) -> None:
asm_name = env_vars.get(asm_env, "").strip()
local_file = env_vars.get(file_env, "").strip()

if asm_name:
create_validator_secret_from_aws_sm(
namespace=namespace,
secret_name=k8s_secret_name,
aws_secret_name=asm_name,
secret_key=secret_key,
region=region,
profile=profile,
)
return

# VFN identity secret (only if deploying VFN)
if deploy_vfn:
vfn_identity_file = env_vars.get("VFN_IDENTITY_FILE", "")
if vfn_identity_file:
create_identity_secret_from_local_file(
if local_file:
ok = create_identity_secret_from_local_file(
namespace=namespace,
secret_name=vfn_keys_secret,
local_file_path=Path(vfn_identity_file),
secret_key="validator-full-node-identity.yaml",
secret_name=k8s_secret_name,
local_file_path=Path(local_file),
secret_key=secret_key,
)
else:
info(f" No VFN_IDENTITY_FILE set (using existing K8s secret: {vfn_keys_secret})")
if not ok:
error(
f"{label}: {file_env}={local_file} but file does not exist. "
f"Set {asm_env} to use AWS Secrets Manager or fix the path."
)
sys.exit(1)
return

error(
f"{label}: no identity source configured. "
f"Set {asm_env} (AWS Secrets Manager, preferred) or {file_env} (local file)."
)
sys.exit(1)

provision_identity(
label="Validator identity",
k8s_secret_name=validator_keys_secret,
secret_key="validator-identity.yaml",
asm_env="VALIDATOR_KEYS_SECRET_NAME",
file_env="VALIDATOR_IDENTITY_FILE",
)

if deploy_vfn:
provision_identity(
label="VFN identity",
k8s_secret_name=vfn_keys_secret,
secret_key="validator-full-node-identity.yaml",
asm_env="VFN_KEYS_SECRET_NAME",
file_env="VFN_IDENTITY_FILE",
)

# Step 2: Deploy nodes in order
from tools.helm import HelmManager
Expand Down
Loading