Skip to content

Commit 10e7067

Browse files
authored
Merge pull request #111 from cisagov/improvement/support-gh-env-secrets
Support GitHub environment secrets in `terraform-to-secrets`
2 parents a3ad64e + 6c66598 commit 10e7067

File tree

1 file changed

+48
-14
lines changed

1 file changed

+48
-14
lines changed

project_setup/scripts/terraform-to-secrets

Lines changed: 48 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Usage:
3939
4040
Options:
4141
-d --dry-run Don't create secrets. Just log what would be created.
42+
-e --env=ENVNAME Create secrets in the specified GitHub environment.
4243
-h --help Show this message.
4344
-l --log-level=LEVEL If specified, then the log level will be set to
4445
the specified value. Valid values are "debug", "info",
@@ -221,28 +222,44 @@ def encrypt(public_key: str, secret_value: str) -> str:
221222
return b64encode(encrypted).decode("utf-8")
222223

223224

224-
def get_public_key(session: requests.Session, repo_name) -> Dict[str, str]:
225-
"""Fetch the public key for a repository."""
226-
logging.info(f"Requesting public key for repository {repo_name}")
227-
response = session.get(
228-
f"https://api.github.com/repos/{repo_name}/actions/secrets/public-key"
229-
)
225+
def get_public_key(session: requests.Session, repo_name, github_env) -> Dict[str, str]:
226+
"""Fetch the public key for a repository or environment."""
227+
if github_env:
228+
logging.info(
229+
f"Requesting public key for environment {github_env} in {repo_name}"
230+
)
231+
response = session.get(
232+
f"https://api.github.com/repos/{repo_name}/environments/{github_env}/secrets/public-key"
233+
)
234+
else:
235+
logging.info(f"Requesting public key for repository {repo_name}")
236+
response = session.get(
237+
f"https://api.github.com/repos/{repo_name}/actions/secrets/public-key"
238+
)
230239
response.raise_for_status()
231240
return response.json()
232241

233242

234243
def set_secret(
235244
session: requests.Session,
236245
repo_name: str,
246+
github_env: str,
237247
secret_name: str,
238248
secret_value: str,
239249
public_key: Dict[str, str],
240250
) -> None:
241-
"""Create a secret in a repository."""
242-
logging.info(f"Creating secret {secret_name}")
251+
"""Create a secret in a repository or environment."""
252+
if github_env:
253+
logging.info(f"Creating secret {secret_name} in environment {github_env}")
254+
api_url = f"https://api.github.com/repos/{repo_name}/environments/{github_env}/secrets/{secret_name}"
255+
else:
256+
logging.info(f"Creating repository secret {secret_name}")
257+
api_url = (
258+
f"https://api.github.com/repos/{repo_name}/actions/secrets/{secret_name}"
259+
)
243260
encrypted_secret_value = encrypt(public_key["key"], secret_value)
244261
response = session.put(
245-
f"https://api.github.com/repos/{repo_name}/actions/secrets/{secret_name}",
262+
api_url,
246263
json={
247264
"encrypted_value": encrypted_secret_value,
248265
"key_id": public_key["key_id"],
@@ -321,21 +338,37 @@ def create_user_secrets(user_creds: Dict[str, Tuple[str, str]]) -> Dict[str, str
321338

322339

323340
def create_all_secrets(
324-
secrets: Dict[str, str], github_token: str, repo_name: str, dry_run: bool = False
341+
secrets: Dict[str, str],
342+
github_env: str,
343+
github_token: str,
344+
repo_name: str,
345+
dry_run: bool = False,
325346
) -> None:
326347
"""Log into GitHub and create all encrypted secrets."""
327348
logging.info("Creating GitHub API session using personal access token.")
328349
session: requests.Session = requests.Session()
329350
session.auth = ("", github_token)
330351

331-
# Get the repo's public key to be used to encrypt secrets
332-
public_key: Dict[str, str] = get_public_key(session, repo_name)
352+
# If an environment is specified, verify that it exists
353+
if github_env:
354+
logging.info(f"Checking if environment {github_env} exists")
355+
response = session.get(
356+
f"https://api.github.com/repos/{repo_name}/environments/{github_env}"
357+
)
358+
if response.status_code != 200:
359+
logging.critical(f"Environment {github_env} not found in {repo_name}.")
360+
raise Exception(f"Environment {github_env} not found in {repo_name}.")
361+
362+
# Get the repo or environment public key to be used to encrypt secrets
363+
public_key: Dict[str, str] = get_public_key(session, repo_name, github_env)
333364

334365
for secret_name, secret_value in secrets.items():
335366
if dry_run:
336367
logging.info(f"Would create secret {secret_name}")
337368
else:
338-
set_secret(session, repo_name, secret_name, secret_value, public_key)
369+
set_secret(
370+
session, repo_name, github_env, secret_name, secret_value, public_key
371+
)
339372

340373

341374
def main() -> int:
@@ -389,6 +422,7 @@ def main() -> int:
389422

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

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

449483
logging.info("Success!")
450484

0 commit comments

Comments
 (0)