Skip to content

Commit

Permalink
Add option for storing GitHub environment secrets to terraform-to-sec…
Browse files Browse the repository at this point in the history
…rets script
  • Loading branch information
dav3r committed Jan 13, 2025
1 parent a3ad64e commit e52d702
Showing 1 changed file with 47 additions and 13 deletions.
60 changes: 47 additions & 13 deletions project_setup/scripts/terraform-to-secrets
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Usage:
Options:
-d --dry-run Don't create secrets. Just log what would be created.
-e --env=ENVNAME Create secrets in the specified GitHub environment.
-h --help Show this message.
-l --log-level=LEVEL If specified, then the log level will be set to
the specified value. Valid values are "debug", "info",
Expand Down Expand Up @@ -221,28 +222,44 @@ def encrypt(public_key: str, secret_value: str) -> str:
return b64encode(encrypted).decode("utf-8")


def get_public_key(session: requests.Session, repo_name) -> Dict[str, str]:
"""Fetch the public key for a repository."""
logging.info(f"Requesting public key for repository {repo_name}")
response = session.get(
f"https://api.github.com/repos/{repo_name}/actions/secrets/public-key"
)
def get_public_key(session: requests.Session, repo_name, github_env) -> Dict[str, str]:
"""Fetch the public key for a repository or environment."""
if github_env:
logging.info(
f"Requesting public key for environment {github_env} in {repo_name}"
)
response = session.get(
f"https://api.github.com/repos/{repo_name}/environments/{github_env}/secrets/public-key"
)
else:
logging.info(f"Requesting public key for repository {repo_name}")
response = session.get(
f"https://api.github.com/repos/{repo_name}/actions/secrets/public-key"
)
response.raise_for_status()
return response.json()


def set_secret(
session: requests.Session,
repo_name: str,
github_env: str,
secret_name: str,
secret_value: str,
public_key: Dict[str, str],
) -> None:
"""Create a secret in a repository."""
logging.info(f"Creating secret {secret_name}")
if github_env:
logging.info(f"Creating secret {secret_name} in environment {github_env}")
api_url = f"https://api.github.com/repos/{repo_name}/environments/{github_env}/secrets/{secret_name}"
else:
logging.info(f"Creating repository secret {secret_name}")
api_url = (
f"https://api.github.com/repos/{repo_name}/actions/secrets/{secret_name}"
)
encrypted_secret_value = encrypt(public_key["key"], secret_value)
response = session.put(
f"https://api.github.com/repos/{repo_name}/actions/secrets/{secret_name}",
api_url,
json={
"encrypted_value": encrypted_secret_value,
"key_id": public_key["key_id"],
Expand Down Expand Up @@ -321,21 +338,37 @@ def create_user_secrets(user_creds: Dict[str, Tuple[str, str]]) -> Dict[str, str


def create_all_secrets(
secrets: Dict[str, str], github_token: str, repo_name: str, dry_run: bool = False
secrets: Dict[str, str],
github_env: str,
github_token: str,
repo_name: str,
dry_run: bool = False,
) -> None:
"""Log into GitHub and create all encrypted secrets."""
logging.info("Creating GitHub API session using personal access token.")
session: requests.Session = requests.Session()
session.auth = ("", github_token)

# Get the repo's public key to be used to encrypt secrets
public_key: Dict[str, str] = get_public_key(session, repo_name)
# If an environment is specified, verify that it exists
if github_env:
logging.info(f"Checking if environment {github_env} exists")
response = session.get(
f"https://api.github.com/repos/{repo_name}/environments/{github_env}"
)
if response.status_code != 200:
logging.critical(f"Environment {github_env} not found in {repo_name}.")
raise Exception(f"Environment {github_env} not found in {repo_name}.")

# Get the repo or environment public key to be used to encrypt secrets
public_key: Dict[str, str] = get_public_key(session, repo_name, github_env)

for secret_name, secret_value in secrets.items():
if dry_run:
logging.info(f"Would create secret {secret_name}")
else:
set_secret(session, repo_name, secret_name, secret_value, public_key)
set_secret(
session, repo_name, github_env, secret_name, secret_value, public_key
)


def main() -> int:
Expand Down Expand Up @@ -389,6 +422,7 @@ def main() -> int:

# Assign validated arguments to variables
dry_run: bool = validated_args["--dry-run"]
github_env: str = validated_args["--env"]
github_token_to_save: str = validated_args["<github-personal-access-token>"]
log_level: str = validated_args["--log-level"]
repo_name: str = validated_args["--repo"]
Expand Down Expand Up @@ -444,7 +478,7 @@ def main() -> int:
all_secrets.update(user_secrets)

# All the ducks are in a row, let's do this thang!
create_all_secrets(all_secrets, github_token, repo_name, dry_run)
create_all_secrets(all_secrets, github_env, github_token, repo_name, dry_run)

logging.info("Success!")

Expand Down

0 comments on commit e52d702

Please sign in to comment.