diff --git a/aws-template-dev.sh b/aws-template-dev.sh index a250d440..9db06c0b 100644 --- a/aws-template-dev.sh +++ b/aws-template-dev.sh @@ -16,9 +16,15 @@ ps -auxc | grep ssh-agent eval $(ssh-agent) cd /var/www/html -echo "github private key" > github -chmod go-rw github -echo "github public key" > github.pub +if [ -z "${GITHUB_DEPLOY_KEY_PATH:-}" ]; then + echo "Set GITHUB_DEPLOY_KEY_PATH to a readable deploy key file before cloning private repositories." >&2 + exit 1 +fi + +install -m 600 "$GITHUB_DEPLOY_KEY_PATH" github +if [ -n "${GITHUB_DEPLOY_PUBLIC_KEY_PATH:-}" ]; then + install -m 644 "$GITHUB_DEPLOY_PUBLIC_KEY_PATH" github.pub +fi ssh-add github ssh-keyscan github.com/ >> ~/.ssh/known_hosts apt install -y git @@ -460,4 +466,4 @@ a2enmod headers systemctl restart apache2 #install new cron file -crontab /var/www/html/studenthub/cron/cronlist \ No newline at end of file +crontab /var/www/html/studenthub/cron/cronlist diff --git a/aws-template-docker.sh b/aws-template-docker.sh index fae31927..fe2ec61f 100644 --- a/aws-template-docker.sh +++ b/aws-template-docker.sh @@ -19,10 +19,16 @@ sudo mkdir -p /var/www/html sudo chmod 2775 /var/www cd /var/www/html -echo "github private key" > ~/.ssh/github -chmod go-rw ~/.ssh/github -echo "github public key" > ~/.ssh/github.pub -sudo chmod a+r ~/.ssh/github +if [ -z "${GITHUB_DEPLOY_KEY_PATH:-}" ]; then + echo "Set GITHUB_DEPLOY_KEY_PATH to a readable deploy key file before cloning private repositories." >&2 + exit 1 +fi + +mkdir -p ~/.ssh +install -m 600 "$GITHUB_DEPLOY_KEY_PATH" ~/.ssh/github +if [ -n "${GITHUB_DEPLOY_PUBLIC_KEY_PATH:-}" ]; then + install -m 644 "$GITHUB_DEPLOY_PUBLIC_KEY_PATH" ~/.ssh/github.pub +fi ssh-add ~/.ssh/github ssh-keyscan github.com >> ~/.ssh/known_hosts apt install -y git @@ -50,10 +56,14 @@ docker-compose -f docker-compose-prod.yml -p studenthub-prod-server up -d #rm -rf awscliv2.zip aws # Authenticate Docker to Amazon ECR -#aws ecr get-login-password --region eu-west-2 | sudo docker login --username AWS --password-stdin 438663597141.dkr.ecr.eu-west-2.amazonaws.com +#AWS_ECR_REGION="${AWS_ECR_REGION:-eu-west-2}" +#AWS_ECR_REGISTRY="${AWS_ECR_ACCOUNT_ID}.dkr.ecr.${AWS_ECR_REGION}.amazonaws.com" +#AWS_ECR_IMAGE="${AWS_ECR_IMAGE:-studenthub/backend-prod}" +#AWS_ECR_TAG="${AWS_ECR_TAG:-latest}" +#aws ecr get-login-password --region "$AWS_ECR_REGION" | sudo docker login --username AWS --password-stdin "$AWS_ECR_REGISTRY" # Pull the Docker image from ECR -#sudo docker pull 438663597141.dkr.ecr.eu-west-2.amazonaws.com/studenthub/backend-prod +#sudo docker pull "$AWS_ECR_REGISTRY/$AWS_ECR_IMAGE:$AWS_ECR_TAG" # Run the Docker container -#sudo docker run -d -p 80:80 --name studenthub-backend-prod 438663597141.dkr.ecr.eu-west-2.amazonaws.com/studenthub/backend-prod +#sudo docker run -d -p 80:80 --name studenthub-backend-prod "$AWS_ECR_REGISTRY/$AWS_ECR_IMAGE:$AWS_ECR_TAG" diff --git a/aws-template.sh b/aws-template.sh index 90c8d47d..d6b189c5 100644 --- a/aws-template.sh +++ b/aws-template.sh @@ -16,9 +16,15 @@ ps -auxc | grep ssh-agent eval $(ssh-agent) cd /var/www/html -echo "github private key" > github -chmod go-rw github -echo "github public key" > github.pub +if [ -z "${GITHUB_DEPLOY_KEY_PATH:-}" ]; then + echo "Set GITHUB_DEPLOY_KEY_PATH to a readable deploy key file before cloning private repositories." >&2 + exit 1 +fi + +install -m 600 "$GITHUB_DEPLOY_KEY_PATH" github +if [ -n "${GITHUB_DEPLOY_PUBLIC_KEY_PATH:-}" ]; then + install -m 644 "$GITHUB_DEPLOY_PUBLIC_KEY_PATH" github.pub +fi ssh-add github ssh-keyscan github.com/ >> ~/.ssh/known_hosts apt install -y git @@ -460,4 +466,4 @@ a2enmod headers systemctl restart apache2 #install new cron file -crontab /var/www/html/studenthub/cron/cronlist \ No newline at end of file +crontab /var/www/html/studenthub/cron/cronlist diff --git a/docs/demo/studenthub-55-aws-template-hardening-demo.webm b/docs/demo/studenthub-55-aws-template-hardening-demo.webm new file mode 100644 index 00000000..f0980f00 Binary files /dev/null and b/docs/demo/studenthub-55-aws-template-hardening-demo.webm differ diff --git a/docs/security/aws-deployment-template-hardening.md b/docs/security/aws-deployment-template-hardening.md new file mode 100644 index 00000000..26839019 --- /dev/null +++ b/docs/security/aws-deployment-template-hardening.md @@ -0,0 +1,33 @@ +# AWS Deployment Template Hardening + +The legacy `aws-template*.sh` helpers are public repository bootstrap scripts. They must not contain inline private-key placeholders or account-specific ECR registry URLs. + +## Required Inputs + +Set these values in the operator shell before running a template: + +```sh +export GITHUB_DEPLOY_KEY_PATH=/secure/path/to/deploy-key +export GITHUB_DEPLOY_PUBLIC_KEY_PATH=/secure/path/to/deploy-key.pub +``` + +For the optional ECR commands in `aws-template-docker.sh`, set the registry target explicitly: + +```sh +export AWS_ECR_ACCOUNT_ID=123456789012 +export AWS_ECR_REGION=eu-west-2 +export AWS_ECR_IMAGE=studenthub/backend-prod +export AWS_ECR_TAG=latest +``` + +`GITHUB_DEPLOY_KEY_PATH` is copied with mode `600` into the temporary deploy location used by the script. Do not paste private key material into the script or commit generated key files. + +## Local Regression Check + +Run: + +```sh +python3 scripts/check-aws-template-hardening.py +``` + +The check fails if the deployment templates reintroduce inline GitHub key writes or account-specific ECR registry literals. diff --git a/scripts/check-aws-template-hardening.py b/scripts/check-aws-template-hardening.py new file mode 100644 index 00000000..b7ab8858 --- /dev/null +++ b/scripts/check-aws-template-hardening.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 +"""Regression checks for legacy AWS deployment template hardening.""" + +from pathlib import Path +import re +import sys + + +ROOT = Path(__file__).resolve().parents[1] +TEMPLATE_FILES = [ + ROOT / "aws-template.sh", + ROOT / "aws-template-dev.sh", + ROOT / "aws-template-docker.sh", +] + +FORBIDDEN_PATTERNS = { + r'echo\s+"github private key"\s*>': "inline private-key placeholder write", + r'echo\s+"github public key"\s*>': "inline public-key placeholder write", + r"\b\d{12}\.dkr\.ecr\.[a-z0-9-]+\.amazonaws\.com\b": "hard-coded ECR registry", +} + +REQUIRED_PATTERNS = { + "GITHUB_DEPLOY_KEY_PATH": "deploy key path is required from the environment", + "install -m 600": "private deploy key is installed with restrictive permissions", +} + + +def main() -> int: + failures = [] + + for template in TEMPLATE_FILES: + text = template.read_text() + + for pattern, description in FORBIDDEN_PATTERNS.items(): + if re.search(pattern, text): + failures.append(f"{template.name}: found {description}") + + for pattern, description in REQUIRED_PATTERNS.items(): + if pattern not in text: + failures.append(f"{template.name}: missing {description}") + + docker_template = (ROOT / "aws-template-docker.sh").read_text() + for required in ("AWS_ECR_ACCOUNT_ID", "AWS_ECR_REGION", "AWS_ECR_REGISTRY", "AWS_ECR_IMAGE"): + if required not in docker_template: + failures.append(f"aws-template-docker.sh: missing {required} ECR variable") + + if failures: + for failure in failures: + print(failure, file=sys.stderr) + return 1 + + print("AWS deployment templates use env-driven deploy keys and ECR registry references.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())