|
5 | 5 |
|
6 | 6 | from src.services.config_service import ConfigService |
7 | 7 | from src.model.dto.aws_credentials_dto import AWSCredentialsDTO |
| 8 | +from src.exception.credentials_validation_exception import CredentialsValidationException |
| 9 | + |
| 10 | + |
| 11 | +def validate_credentials(require_bucket: bool = True): |
| 12 | + """Public validation of credentials before creating S3/STS clients.""" |
| 13 | + credentials: AWSCredentialsDTO = ConfigService.get_aws_credentials() |
| 14 | + errors = {} |
| 15 | + if not credentials.access_key_id: |
| 16 | + errors["access_key_id"] = "Access Key ID is missing" |
| 17 | + if not credentials.secret_access_key: |
| 18 | + errors["secret_access_key"] = "Secret Access Key is missing" |
| 19 | + if require_bucket and not credentials.bucket_name: |
| 20 | + errors["bucket_name"] = "S3 Bucket Name is missing" |
| 21 | + |
| 22 | + if errors: |
| 23 | + raise CredentialsValidationException(errors) |
8 | 24 |
|
9 | 25 |
|
10 | 26 | def create_s3_resource() -> Bucket: |
11 | 27 | """Creates S3 resource with proper configuration""" |
12 | 28 | credentials: AWSCredentialsDTO = ConfigService.get_aws_credentials() |
| 29 | + validate_credentials() |
| 30 | + |
13 | 31 | s3_resource = boto3.resource( |
14 | 32 | "s3", |
15 | 33 | aws_access_key_id=credentials.access_key_id, |
16 | 34 | aws_secret_access_key=credentials.secret_access_key, |
17 | 35 | region_name=credentials.region, |
| 36 | + endpoint_url=getattr(credentials, "endpoint_url", None), |
18 | 37 | ) |
19 | 38 | return s3_resource.Bucket(credentials.bucket_name) |
20 | 39 |
|
21 | 40 |
|
22 | 41 | def create_s3_client() -> S3Client: |
23 | 42 | """Creates S3 resource with proper configuration""" |
24 | 43 | credentials: AWSCredentialsDTO = ConfigService.get_aws_credentials() |
| 44 | + validate_credentials() |
| 45 | + |
25 | 46 | return boto3.client( |
26 | 47 | "s3", |
27 | 48 | aws_access_key_id=credentials.access_key_id, |
28 | 49 | aws_secret_access_key=credentials.secret_access_key, |
29 | 50 | region_name=credentials.region, |
| 51 | + endpoint_url=getattr(credentials, "endpoint_url", None), |
30 | 52 | ) |
31 | 53 |
|
32 | 54 |
|
33 | 55 | def create_sts_client(): |
34 | 56 | """Creates STS client for identity verification""" |
35 | 57 | credentials: AWSCredentialsDTO = ConfigService.get_aws_credentials() |
| 58 | + validate_credentials(require_bucket=False) |
| 59 | + |
36 | 60 | return boto3.client( |
37 | 61 | "sts", |
38 | 62 | aws_access_key_id=credentials.access_key_id, |
39 | 63 | aws_secret_access_key=credentials.secret_access_key, |
40 | 64 | region_name=credentials.region, |
41 | 65 | ) |
| 66 | + |
| 67 | + |
| 68 | +def create_bucket(bucket_name: str, region: str) -> None: |
| 69 | + """Creates an S3 bucket with the specified name and region.""" |
| 70 | + credentials: AWSCredentialsDTO = ConfigService.get_aws_credentials() |
| 71 | + client = boto3.client( |
| 72 | + "s3", |
| 73 | + aws_access_key_id=credentials.access_key_id, |
| 74 | + aws_secret_access_key=credentials.secret_access_key, |
| 75 | + region_name=region, |
| 76 | + endpoint_url=getattr(credentials, "endpoint_url", None), |
| 77 | + ) |
| 78 | + |
| 79 | + if region == "us-east-1": |
| 80 | + client.create_bucket(Bucket=bucket_name) |
| 81 | + else: |
| 82 | + client.create_bucket( |
| 83 | + Bucket=bucket_name, |
| 84 | + CreateBucketConfiguration={"LocationConstraint": region}, |
| 85 | + ) |
| 86 | + |
| 87 | + |
| 88 | +def put_public_access_block(bucket_name: str, region: str) -> None: |
| 89 | + """Configures public access block for the bucket.""" |
| 90 | + credentials: AWSCredentialsDTO = ConfigService.get_aws_credentials() |
| 91 | + client = boto3.client( |
| 92 | + "s3", |
| 93 | + aws_access_key_id=credentials.access_key_id, |
| 94 | + aws_secret_access_key=credentials.secret_access_key, |
| 95 | + region_name=region, |
| 96 | + endpoint_url=getattr(credentials, "endpoint_url", None), |
| 97 | + ) |
| 98 | + client.put_public_access_block( |
| 99 | + Bucket=bucket_name, |
| 100 | + PublicAccessBlockConfiguration={ |
| 101 | + "BlockPublicAcls": True, |
| 102 | + "IgnorePublicAcls": True, |
| 103 | + "BlockPublicPolicy": True, |
| 104 | + "RestrictPublicBuckets": True, |
| 105 | + }, |
| 106 | + ) |
| 107 | + |
| 108 | + |
| 109 | +def list_workstate_buckets() -> list[str]: |
| 110 | + """Lists all S3 buckets that match the Workstate prefix.""" |
| 111 | + credentials: AWSCredentialsDTO = ConfigService.get_aws_credentials() |
| 112 | + client = boto3.client( |
| 113 | + "s3", |
| 114 | + aws_access_key_id=credentials.access_key_id, |
| 115 | + aws_secret_access_key=credentials.secret_access_key, |
| 116 | + region_name=credentials.region, |
| 117 | + endpoint_url=getattr(credentials, "endpoint_url", None), |
| 118 | + ) |
| 119 | + |
| 120 | + try: |
| 121 | + response = client.list_buckets() |
| 122 | + buckets = [b["Name"] for b in response.get("Buckets", [])] |
| 123 | + return [b for b in buckets if b.startswith("workstate-storage-")] |
| 124 | + except Exception: |
| 125 | + return [] |
0 commit comments