Skip to content

Commit

Permalink
Fine-grained repo access policy for ECR
Browse files Browse the repository at this point in the history
  • Loading branch information
emdoyle committed Aug 20, 2024
1 parent c11d036 commit 502aa2a
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 23 deletions.
5 changes: 5 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# API Server for Pare Cloud

Responsible for managing the lifecycle of a Pare endpoint.

Handles user authentication, routing based on the git hash, and deploying/updating Lambdas.
25 changes: 22 additions & 3 deletions api/src/deploy/lambda_deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import asyncio
import json
from typing import Callable, TypeVar
from typing import Any, Callable, TypeVar

import boto3
from botocore.exceptions import ClientError
Expand All @@ -11,7 +11,26 @@
from src import settings


def create_ecr_repository(repository_name: str) -> bool:
def generate_ecr_repo_policy(function_name: str) -> dict[str, Any]:
return {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaECRImageRetrievalPolicy",
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": ["ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer"],
"Condition": {
"StringLike": {
"aws:sourceArn": f"arn:aws:lambda:{settings.AWS_DEFAULT_REGION}:{settings.AWS_ACCOUNT_ID}:function:{function_name}"
}
},
}
],
}


def create_ecr_repository(repository_name: str, function_name: str) -> bool:
ecr_client = boto3.client("ecr", region_name=settings.AWS_DEFAULT_REGION) # type: ignore

try:
Expand All @@ -30,7 +49,7 @@ def create_ecr_repository(repository_name: str) -> bool:

ecr_client.set_repository_policy( # type: ignore
repositoryName=repository_name,
policyText=json.dumps(settings.ECR_REPO_POLICY),
policyText=json.dumps(generate_ecr_repo_policy(function_name)),
)
print(f"Repository policy set for '{repository_name}'")
return True
Expand Down
5 changes: 3 additions & 2 deletions api/src/deploy/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ async def deploy_image(
) -> bool:
repo_name = build_ecr_repo_name(user, service_config.name)
tag = deploy_config.git_hash
repo_created = create_ecr_repository(repo_name)
function_name = build_lambda_function_name(repo_name, tag)
repo_created = create_ecr_repository(repo_name, function_name=function_name)
if not repo_created:
print(f"Failed to create ECR repository for {repo_name}")
return False
Expand All @@ -61,7 +62,7 @@ async def deploy_image(
return False

return await deploy_python_lambda_function_from_ecr(
function_name=build_lambda_function_name(repo_name, tag),
function_name=function_name,
image_name=build_result.image_name,
environment_variables=deploy_config.environment_variables,
)
Expand Down
18 changes: 0 additions & 18 deletions api/src/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from __future__ import annotations

from pathlib import Path
from typing import Any

from environs import Env

Expand Down Expand Up @@ -36,23 +35,6 @@
AWS_LAMBDA_UPDATE_INITIAL_BACKOFF: int = env.int("AWS_LAMBDA_UPDATE_INITIAL_BACKOFF", 1)
AWS_LAMBDA_UPDATE_MAX_RETRIES: int = env.int("AWS_LAMBDA_UPDATE_MAX_RETRIES", 8)

ECR_REPO_POLICY: dict[str, Any] = {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LambdaECRImageRetrievalPolicy",
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": ["ecr:BatchGetImage", "ecr:GetDownloadUrlForLayer"],
"Condition": {
"StringLike": {
"aws:sourceArn": f"arn:aws:lambda:{AWS_DEFAULT_REGION}:{AWS_ACCOUNT_ID}:function:*"
}
},
}
],
}

PARE_ATOMIC_DEPLOYMENT_HEADER: str = env.str(
"PARE_ATOMIC_DEPLOYMENT_HEADER", "X-Pare-Atomic-Deployment"
)
Expand Down

0 comments on commit 502aa2a

Please sign in to comment.