@@ -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