Skip to content

Commit ec88d9f

Browse files
authored
feat: add eoapi auth utils to ingest api (#478)
1 parent 089e0c1 commit ec88d9f

File tree

14 files changed

+82
-127
lines changed

14 files changed

+82
-127
lines changed

.example.env

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ VEDA_CLIENT_SECRET=secret
3333
VEDA_DATA_ACCESS_ROLE_ARN=
3434
VEDA_COGNITO_DOMAIN=
3535
VEDA_OPENID_CONFIGURATION_URL=
36-
VEDA_KEYCLOAK_CLIENT_ID=
36+
VEDA_KEYCLOAK_STAC_API_CLIENT_ID=
37+
VEDA_KEYCLOAK_INGEST_API_CLIENT_ID=
3738

3839
STAC_BROWSER_BUCKET=
3940
STAC_URL=

.github/workflows/pr.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,6 @@ jobs:
8080
- name: Install reqs for stac api
8181
run: python -m pip install stac_api/runtime/
8282

83-
- name: Install veda auth for ingest api
84-
run: python -m pip install common/auth
85-
8683
- name: Ingest unit tests
8784
run: NO_PYDANTIC_SSM_SETTINGS=1 python -m pytest ingest_api/runtime/tests/ -vv -s
8885

ingest_api/infrastructure/config.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,6 @@ class IngestorConfig(BaseSettings):
3939
),
4040
default_factory=getuser,
4141
)
42-
43-
userpool_id: str = Field(description="The Cognito Userpool used for authentication")
44-
client_id: str = Field(description="The Cognito APP client ID")
45-
client_secret: Optional[str] = Field(
46-
"", description="The Cognito APP client secret"
47-
)
48-
cognito_domain: AnyHttpUrl = Field(
49-
description="The base url of the Cognito domain for authorization and token urls"
50-
)
5142
stac_db_security_group_id: str = Field(
5243
description="ID of Security Group used by pgSTAC DB"
5344
)
@@ -94,6 +85,10 @@ class IngestorConfig(BaseSettings):
9485
False,
9586
description="Boolean to disable default API gateway endpoints for stac, raster, and ingest APIs. Defaults to false.",
9687
)
88+
89+
keycloak_ingest_api_client_id: str = Field(description="Auth client ID")
90+
91+
openid_configuration_url: AnyHttpUrl = Field(description="OpenID config url")
9792
model_config = SettingsConfigDict(
9893
case_sensitive=False, env_file=".env", env_prefix="VEDA_", extra="ignore"
9994
)

ingest_api/infrastructure/construct.py

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from aws_cdk import CfnOutput, Duration, RemovalPolicy, Stack
55
from aws_cdk import aws_apigateway as apigateway
66
from aws_cdk import aws_apigatewayv2_alpha, aws_apigatewayv2_integrations_alpha
7-
from aws_cdk import aws_cognito as cognito
87
from aws_cdk import aws_dynamodb as dynamodb
98
from aws_cdk import aws_ec2 as ec2
109
from aws_cdk import aws_iam as iam
@@ -31,10 +30,6 @@ def __init__(
3130
super().__init__(scope, construct_id, **kwargs)
3231

3332
self.table = self.build_table()
34-
self.user_pool = cognito.UserPool.from_user_pool_id(
35-
self, "cognito-user-pool", config.userpool_id
36-
)
37-
self.jwks_url = self.build_jwks_url(config.userpool_id)
3833
db_security_group = ec2.SecurityGroup.from_security_group_id(
3934
self,
4035
"db-security-group",
@@ -43,21 +38,17 @@ def __init__(
4338

4439
lambda_env = {
4540
"DYNAMODB_TABLE": self.table.table_name,
46-
"JWKS_URL": self.jwks_url,
4741
"NO_PYDANTIC_SSM_SETTINGS": "1",
4842
"STAC_URL": config.veda_stac_api_cf_url,
49-
"USERPOOL_ID": config.userpool_id,
50-
"CLIENT_ID": config.client_id,
51-
"CLIENT_SECRET": config.client_secret,
5243
"RASTER_URL": config.veda_raster_api_cf_url,
5344
"ROOT_PATH": config.ingest_root_path,
5445
"STAGE": config.stage,
55-
"COGNITO_DOMAIN": str(config.cognito_domain),
46+
"CLIENT_ID": config.keycloak_ingest_api_client_id,
47+
"OPENID_CONFIGURATION_URL": str(config.openid_configuration_url),
5648
}
5749

5850
build_api_lambda_params = {
5951
"table": self.table,
60-
"user_pool": self.user_pool,
6152
"db_secret": db_secret,
6253
"db_vpc": db_vpc,
6354
"db_security_group": db_security_group,
@@ -115,7 +106,6 @@ def build_api_lambda(
115106
*,
116107
table: dynamodb.ITable,
117108
env: Dict[str, str],
118-
user_pool: cognito.IUserPool,
119109
db_secret: secretsmanager.ISecret,
120110
db_vpc: ec2.IVpc,
121111
db_security_group: ec2.ISecurityGroup,
@@ -164,14 +154,6 @@ def build_api_lambda(
164154
handler.grant_principal,
165155
"sts:AssumeRole",
166156
)
167-
168-
handler.add_to_role_policy(
169-
iam.PolicyStatement(
170-
actions=["cognito-idp:AdminInitiateAuth"],
171-
resources=[user_pool.user_pool_arn],
172-
)
173-
)
174-
175157
# Allow handler to read DB secret
176158
db_secret.grant_read(handler)
177159

@@ -216,13 +198,6 @@ def build_api(
216198
disable_execute_api_endpoint=disable_default_apigw_endpoint,
217199
)
218200

219-
def build_jwks_url(self, userpool_id: str) -> str:
220-
region = userpool_id.split("_")[0]
221-
return (
222-
f"https://cognito-idp.{region}.amazonaws.com"
223-
f"/{userpool_id}/.well-known/jwks.json"
224-
)
225-
226201
# item ingest table, comsumed by ingestor
227202
def build_table(self) -> dynamodb.ITable:
228203
table = dynamodb.Table(
@@ -260,9 +235,6 @@ def __init__(
260235
"DYNAMODB_TABLE": table.table_name,
261236
"NO_PYDANTIC_SSM_SETTINGS": "1",
262237
"STAC_URL": config.veda_stac_api_cf_url,
263-
"USERPOOL_ID": config.userpool_id,
264-
"CLIENT_ID": config.client_id,
265-
"CLIENT_SECRET": config.client_secret,
266238
"RASTER_URL": config.veda_raster_api_cf_url,
267239
}
268240

ingest_api/runtime/Dockerfile

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,6 @@ RUN echo "Using PGSTAC Version ${PGSTAC_VERSION}"
55

66
WORKDIR /tmp
77

8-
COPY common/auth /tmp/common/auth
9-
RUN pip install /tmp/common/auth -t /asset
10-
RUN rm -rf /tmp/common
11-
128
COPY ingest_api/runtime/requirements.txt /tmp/ingestor/requirements.txt
139
RUN pip install -r /tmp/ingestor/requirements.txt pypgstac==${PGSTAC_VERSION} -t /asset --no-binary pydantic uvicorn
1410
RUN rm -rf /tmp/ingestor

ingest_api/runtime/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ boto3==1.24.59
1414
aws_xray_sdk>=2.6.0,<3
1515
aws-lambda-powertools>=1.18.0
1616
pydantic-settings>=2.4.1
17+
eoapi-auth-utils==0.3.0

ingest_api/runtime/src/auth.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from typing import Any, Dict
2+
3+
from typing_extensions import Annotated
4+
5+
from fastapi import Depends
6+
7+
from eoapi.auth_utils import OpenIdConnectAuth, OpenIdConnectSettings
8+
9+
auth_settings = OpenIdConnectSettings(_env_prefix="")
10+
11+
oidc_auth = OpenIdConnectAuth(
12+
openid_configuration_url=auth_settings.openid_configuration_url,
13+
allowed_jwt_audiences="account",
14+
)
15+
16+
17+
def get_username(
18+
token: Annotated[Dict[Any, Any], Depends(oidc_auth.valid_token_dependency)],
19+
) -> str:
20+
result = (
21+
token["preferred_username"]
22+
if "preferred_username" in token
23+
else str(token.get("sub"))
24+
)
25+
return result

ingest_api/runtime/src/config.py

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
from typing import Optional
22

3-
from pydantic import AnyHttpUrl, ConfigDict, Field, StringConstraints
3+
from pydantic import AnyHttpUrl, Field, StringConstraints
44
from pydantic_settings import BaseSettings
55
from typing_extensions import Annotated
6-
from veda_auth import VedaAuth
76

87
AwsArn = Annotated[str, StringConstraints(pattern=r"^arn:aws:iam::\d{12}:role/.+")]
98

109

1110
class Settings(BaseSettings):
1211
dynamodb_table: str
1312

14-
jwks_url: Optional[AnyHttpUrl] = Field(
15-
None,
16-
description="URL of JWKS, e.g. https://cognito-idp.{region}.amazonaws.com/{userpool_id}/.well-known/jwks.json", # noqa
17-
)
18-
1913
data_access_role_arn: Optional[AwsArn] = Field( # type: ignore
2014
None, description="ARN of AWS Role used to validate access to S3 data"
2115
)
@@ -26,33 +20,8 @@ class Settings(BaseSettings):
2620
)
2721

2822
stac_url: AnyHttpUrl = Field(description="URL of STAC API")
29-
30-
userpool_id: str = Field(description="The Cognito Userpool used for authentication")
31-
32-
cognito_domain: Optional[AnyHttpUrl] = Field(
33-
None,
34-
description="The base url of the Cognito domain for authorization and token urls",
35-
)
36-
client_id: str = Field(None, description="The Cognito APP client ID")
37-
client_secret: str = Field("", description="The Cognito APP client secret")
3823
root_path: Optional[str] = None
3924
stage: Optional[str] = Field(None, description="API stage")
4025

41-
@property
42-
def cognito_authorization_url(self) -> AnyHttpUrl:
43-
"""Cognito user pool authorization url"""
44-
return f"{self.cognito_domain}/oauth2/authorize"
45-
46-
@property
47-
def cognito_token_url(self) -> AnyHttpUrl:
48-
"""Cognito user pool token and refresh url"""
49-
return f"{self.cognito_domain}/oauth2/token"
50-
51-
model_config = ConfigDict(
52-
env_file=".env", env_file_encoding="utf-8", extra="ignore"
53-
)
54-
5526

5627
settings = Settings()
57-
58-
auth = VedaAuth(settings)

ingest_api/runtime/src/dependencies.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22

33
import boto3
44
import src.services as services
5-
from src.config import auth, settings
5+
from src.auth import get_username
6+
from src.config import settings
67

7-
from fastapi import Depends, HTTPException, security
8+
from fastapi import Depends, HTTPException
89

910
logger = logging.getLogger(__name__)
1011

11-
token_scheme = security.HTTPBearer()
12-
1312

1413
def get_table():
1514
client = boto3.resource("dynamodb")
@@ -23,7 +22,7 @@ def get_db(table=Depends(get_table)) -> services.Database:
2322
def fetch_ingestion(
2423
ingestion_id: str,
2524
db: services.Database = Depends(get_db),
26-
username: str = Depends(auth.get_username),
25+
username: str = Depends(get_username),
2726
):
2827
try:
2928
return db.fetch_one(username=username, ingestion_id=ingestion_id)

0 commit comments

Comments
 (0)