Skip to content

Commit aa8db8d

Browse files
committed
Merge branch 'feature/fix-acl-handling-and-reporting' into 'develop'
Fix ACL handling for buckets that don't support ACLs See merge request genaiic-reusable-assets/engagement-artifacts/genaiic-idp-accelerator!277
2 parents ff90b8c + 73d3527 commit aa8db8d

File tree

1 file changed

+101
-8
lines changed

1 file changed

+101
-8
lines changed

publish.py

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1296,9 +1296,7 @@ def upload_config_library(self):
12961296
s3_key = f"{self.prefix_and_version}/config_library/{relative_path}"
12971297

12981298
try:
1299-
self.s3_client.upload_file(
1300-
local_path, self.bucket, s3_key, ExtraArgs={"ACL": self.acl}
1301-
)
1299+
self.s3_client.upload_file(local_path, self.bucket, s3_key)
13021300
except ClientError as e:
13031301
self.console.print(f"[red]Error uploading {local_path}: {e}[/red]")
13041302
sys.exit(1)
@@ -1363,9 +1361,7 @@ def package_ui(self):
13631361
if e.response["Error"]["Code"] == "404":
13641362
self.console.print("[cyan]Upload source to S3[/cyan]")
13651363
try:
1366-
self.s3_client.upload_file(
1367-
zipfile_path, self.bucket, s3_key, ExtraArgs={"ACL": self.acl}
1368-
)
1364+
self.s3_client.upload_file(zipfile_path, self.bucket, s3_key)
13691365
self.console.print(
13701366
f"[green]Uploaded WebUI zipfile to S3: {zipfile_name}[/green]"
13711367
)
@@ -1514,7 +1510,6 @@ def build_main_template(self, webui_zipfile, components_needing_rebuild):
15141510
packaged_template_path,
15151511
self.bucket,
15161512
final_template_key,
1517-
ExtraArgs={"ACL": self.acl},
15181513
)
15191514
self.console.print(
15201515
"[green]✅ Main template uploaded successfully[/green]"
@@ -1543,7 +1538,6 @@ def build_main_template(self, webui_zipfile, components_needing_rebuild):
15431538
packaged_template_path,
15441539
self.bucket,
15451540
final_template_key,
1546-
ExtraArgs={"ACL": self.acl},
15471541
)
15481542
self.console.print(
15491543
"[green]✅ Main template uploaded successfully[/green]"
@@ -1858,6 +1852,9 @@ def print_outputs(self):
18581852
f" • Public Access: [yellow]{'Yes' if self.public else 'No'}[/yellow]"
18591853
)
18601854

1855+
# Set public ACLs if requested
1856+
self.set_public_acls()
1857+
18611858
# Display hyperlinks with complete URLs as the display text
18621859
self.console.print("\n[bold green]Deployment Outputs[/bold green]")
18631860

@@ -1871,6 +1868,102 @@ def print_outputs(self):
18711868
template_link = f"[link={template_url}]{template_url}[/link]"
18721869
self.console.print(f" {template_link}")
18731870

1871+
def set_public_acls(self):
1872+
"""Set public read ACLs on all uploaded artifacts if public option is enabled"""
1873+
if not self.public:
1874+
return
1875+
1876+
self.console.print(
1877+
"[cyan]Setting public read ACLs on published artifacts...[/cyan]"
1878+
)
1879+
1880+
try:
1881+
# Get all objects with the prefix
1882+
paginator = self.s3_client.get_paginator("list_objects_v2")
1883+
page_iterator = paginator.paginate(
1884+
Bucket=self.bucket, Prefix=self.prefix_and_version
1885+
)
1886+
1887+
objects = []
1888+
for page in page_iterator:
1889+
if "Contents" in page:
1890+
objects.extend(page["Contents"])
1891+
1892+
if not objects:
1893+
self.console.print("[yellow]No objects found to set ACLs on[/yellow]")
1894+
return
1895+
1896+
total_files = len(objects)
1897+
successful_acls = 0
1898+
failed_acls = 0
1899+
1900+
self.console.print(f"[cyan]Setting ACLs on {total_files} files...[/cyan]")
1901+
1902+
for i, obj in enumerate(objects, 1):
1903+
try:
1904+
self.s3_client.put_object_acl(
1905+
Bucket=self.bucket, Key=obj["Key"], ACL="public-read"
1906+
)
1907+
successful_acls += 1
1908+
if i % 10 == 0 or i == total_files: # Progress every 10 files
1909+
self.console.print(
1910+
f"[cyan]Progress: {i}/{total_files} files processed[/cyan]"
1911+
)
1912+
except ClientError as e:
1913+
failed_acls += 1
1914+
if "AccessDenied" in str(e) or "BlockPublicAcls" in str(e):
1915+
# Don't spam with individual permission error messages
1916+
pass
1917+
else:
1918+
self.console.print(
1919+
f"[yellow]Warning: Could not set ACL for {obj['Key']}: {e}[/yellow]"
1920+
)
1921+
1922+
# Also set ACL for main template files
1923+
main_template_keys = [
1924+
f"{self.prefix}/{self.main_template}",
1925+
f"{self.prefix}/{self.main_template.replace('.yaml', f'_{self.version}.yaml')}",
1926+
]
1927+
1928+
for key in main_template_keys:
1929+
try:
1930+
self.s3_client.put_object_acl(
1931+
Bucket=self.bucket, Key=key, ACL="public-read"
1932+
)
1933+
successful_acls += 1
1934+
except ClientError as e:
1935+
failed_acls += 1
1936+
if "AccessDenied" not in str(e) and "BlockPublicAcls" not in str(e):
1937+
self.console.print(
1938+
f"[yellow]Warning: Could not set ACL for {key}: {e}[/yellow]"
1939+
)
1940+
1941+
# Report accurate final status
1942+
if failed_acls == 0:
1943+
self.console.print("[green]✅ Public ACLs set successfully[/green]")
1944+
elif successful_acls == 0:
1945+
self.console.print(
1946+
f"[red]❌ Could not set public ACLs on any files ({failed_acls} failed)[/red]"
1947+
)
1948+
self.console.print(
1949+
"[yellow]Files uploaded successfully but are NOT publicly accessible[/yellow]"
1950+
)
1951+
self.console.print(
1952+
"[yellow]This is usually due to 'Block Public Access' settings or insufficient permissions[/yellow]"
1953+
)
1954+
else:
1955+
self.console.print(
1956+
f"[yellow]⚠️ Partial ACL success: {successful_acls} succeeded, {failed_acls} failed[/yellow]"
1957+
)
1958+
1959+
except Exception as e:
1960+
self.console.print(
1961+
f"[yellow]Warning: Failed to set public ACLs: {e}[/yellow]"
1962+
)
1963+
self.console.print(
1964+
"[yellow]Files were uploaded successfully but may not be publicly accessible[/yellow]"
1965+
)
1966+
18741967
def run(self, args):
18751968
"""Main execution method"""
18761969
try:

0 commit comments

Comments
 (0)