AWSS3BucketsReport.ps1
<#PSScriptInfo
.VERSION 1.1 .GUID a7016e19-4499-46b9-84a9-cf3d7053a4e2 .AUTHOR Vikas Sukhija .COMPANYNAME TechWizard.cloud .COPYRIGHT Vikas Sukhija .TAGS .LICENSEURI https://techwizard.cloud/ .PROJECTURI https://techwizard.cloud/ .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES https://techwizard.cloud/ .PRIVATEDATA =========================================================================== Created with: ISE Created on: 2/26/2023 1:46 PM Created by: Vikas Sukhija Organization: Filename: AWSS3BucketsReport.ps1 =========================================================================== #> <# .DESCRIPTION This solution will generate S3 buckets inventory #> param() #################logs and variables########################## $log = Write-Log -Name "AWSS3BucketsReport" -folder "logs" -Ext "log" $Failedlog = Write-Log -Name "FailedAccounts" -folder "logs" -Ext "log" $Report = Write-Log -Name "AWSS3BucketsReport" -folder "Report" -Ext "csv" $logrecyclelimit = "60" $email1 = "Vikas@labtest.com" ##################Admin params########################## $smtpserver = "smtpserver" $erroremail = "reports@labtest.com" $from = "DoNotRespond@labtest.com" ######################Spo Cet Auth######################### $AccessKey = "Access Key" $SecretKey = "Secret Key" ########################################################### <# .SYNOPSIS Provides maximum or highest average bucket size in gibibytes and number of objects via AWS CloudWatch measurements for a specific S3 bucket or all buckets over a specificed period of days. .DESCRIPTION Accepts a single bucket name or an array of bucket names via the pipline to pass to AWS CloudWatch to retrieve metrics for all (default) or selected storage classes. .PARAMETER BucketName Lower-case name of S3 bucket. .PARAMETER StorageClass One of StandardStorage | StandardIAStorage | ReducedRedundancyStorage. Defaults to all storage classes. Results for storage class AllStorageTypes are always returned in order to provide the number of objects. .PARAMETER AWSProfile String containing name of credentals created via New-AWSCredential. Defaults to credentials stored in default AWS profile, that is whatever is authorized when no credentials are supplied. .PARAMETER Days The number of days for which to collect average or maximum CloudWatch metrics for S3 buckets. Defaults to 5. .PARAMETER Statistic The case-sensitive CloudWatch statistic to retireve. Must be one of 'Maximum' or 'Average'. Defaults to 'Average'. 'Average' returns highest average over the number of days selected. .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject: Bucket = Name of S3 Bucket SizeGiB = Size in gibibytes of contents of bucket by storage class NumObjects = Number of S3 objects in bucket across ALL storage classes StorageClass = bucket storage class (exclusing GLAICER class) .EXAMPLE PS C:\> Get-S3BucketSize Outputs to the pipline a collection of type PSObject that lists the average bucket size and number of objects in all buckets over the previous five days. Uses the default AWS credential profile. .EXAMPLE PS C:\> Get-S3BucketSize -BucketName 'BucketName' -Statistic 'Maximum' -AWSProfile 'myprofile' Outputs to the pipline a (single member) collection of type PSObject that lists the maximum bucket size and number of objects over the previous five days. Selects buckets based on 'myprofile'. .EXAMPLE PS C:\> Get-S3BucketSize -BucketName 'BucketName' -Days 14 Outputs to the pipline a (single member) collection of type PSObject that lists the maximum average bucket size and number of objects over the previous 14 days. Selects buckets based on 'myprofile'. .EXAMPLE PS C:\> Get-S3BucketSize | Measure-Object -Property SizeGiB -Sum Sums the maximum average size over the last five days of all S3 buckets. .EXAMPLE PS C:\> Get-S3BucketSize | Measure-Object -Property NumObjects -Sum Sums the maximum average number of objects over the last five days of all S3 buckets. .EXAMPLE PS C:\> Get-S3BucketSize -StorageClass StandardStorage | Measure-Object -Property SizeGiB -Sum Pipes the maximum average size of StandardStorage over the last five days of all S3 buckets available to the current profile to Measure-Object which sums the total size of all S3 objects in those buckets. .EXAMPLE PS C:\> Import-Csv .\lisofbuckets.csv | Get-S3BucketSize Accepts from pipeline a list of buckets to be retrieved for measurement. The .csv file can be easily created with Get-S3Bucket | Export-Csv .\listofbuckets.csv and edited as required. .EXAMPLE PS C:\> Get-S3Bucket | Get-S3BucketSize Outputs to the pipline a collection of all S3 buckets' size and number of objects. This is equivalent to Get-S3BucketSize since it will also invoke Get-S3Bucket when -BucketName is omitted. .NOTES For more information on S3 metrics in CloudWatch, see http://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html (c) 2016 Air11 Technology LLC -- licensed under the Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0 Author's blog: https://www.yobyot.com #> function Get-S3BucketSize { [CmdletBinding()] [OutputType([string])] param ( [Parameter(ValueFromPipelineByPropertyName = $true, Position = 0, HelpMessage = 'Lower-case name of S3 bucket')] [System.String[]]$BucketName = 'All', [Parameter(HelpMessage = 'Specify storage class ')] [System.String]$StorageClass, [Parameter(HelpMessage = 'Enter the name of the AWS credential profile to be used')] [System.String]$AWSProfile, [Parameter(HelpMessage = 'Enter an integer for the number of days to collect metrics')] [ValidateRange(1, 14)] [System.Int16]$Days = 5, $region, [System.String]$Statistic = 'Average' ) begin { try { $obj = [ordered]@{ 'Bucket' = '' 'SizeGiB' = '' 'NumObjects' = '' 'StorageClass' = '' } $results = @() $daysAgo = (Get-Date ([datetime](Get-Date).AddDays(- $Days)) -Format s) # Date formats for Get-CWMetricStatistics MUST be in ISO format $today = Get-Date -Format s # Date formats for Get-CWMetricStatistics MUST be in ISO format #if ($AWSProfile) { Set-AWSCredentials -ProfileName $AWSProfile } if ($Statistic -cnotmatch '(Maximum|Average)\b') { $Statistic = "Average" } Write-Verbose "Today=$today, DaysAgo=$daysAgo, AWSProfile=$AWSProfile, Statistic=$Statistic" } catch { "An error occurred: $Error" } } process { try { switch ($BucketName) { 'All' { $BucketNameStrings = Get-S3Bucket -Region $region -Credential $creds | Select-Object -ExpandProperty BucketName foreach ($b in $BucketNameStrings) { switch ("$StorageClass") { "StandardStorage" { $results += (getBucketSize "$b" 'StandardStorage') } "StandardIASStorage" { $results += (getBucketSize "$b" 'StandardIAStorage') } "ReducedRedundancyStorage" { $results += (getBucketSize "$b" 'ReducedRedundancyStorage') } default { #Get all classes $results += getBucketSize $b 'StandardStorage' $results += getBucketSize $b 'StandardIAStorage' $results += getBucketSize $b 'ReducedRedundancyStorage' } } $results += (getBucketNumObjects $b) } } ($BucketName -ne 'All') { switch ("$StorageClass") { "StandardStorage" { $results += (getBucketSize $BucketName 'StandardStorage') } "StandardIAStorage" { $results += (getBucketSize $BucketName 'StandardIAStorage') } "ReducedRedundancyStorage" { $results += (getBucketSize $BucketName 'ReducedRedundancyStorage') } default { #Get all classes $results += (getBucketSize $BucketName 'StandardStorage') $results += (getBucketSize $BucketName 'StandardIAStorage') $results += (getBucketSize $BucketName 'ReducedRedundancyStorage') } } $results += (getBucketNumObjects $BucketName) } default { Write-Verbose "Neither 'All' nor individual bucket selected; big problem since default bucket name is 'All' " } } } catch { "An error occurred: $Error" } } end { try { Write-Output $results Write-Verbose "Done" } catch { "An error occurred: $Error" } } } function getBucketSize ($bname, $stgclass) { Write-Verbose "getBucketSize entered with $bname and storage class $stgclass" $metricSize = Get-CWMetricStatistics -Credential $creds -region $region -Namespace 'AWS/S3' -MetricName 'BucketSizeBytes' ` -Dimension @(@{ Name = 'BucketName'; Value = "$bname" }; @{ Name = 'StorageType'; Value = "$stgclass" }) ` -Statistic $Statistic -Period 86400 -UtcStartTime $daysAgo -UtcEndTime $today $maxSize = '{0:N2}' -f (($metricSize.Datapoints | Measure-Object -Property $Statistic -Maximum).Maximum / 1GB) $functionObj = New-Object -TypeName System.Management.Automation.PSObject -Property $obj $functionObj.Bucket = [string]$bname $functionObj.SizeGiB = [decimal]$maxSize $functionObj.NumObjects = '' $functionObj.StorageClass = $stgclass $functionObj } function getBucketNumObjects ($bname) { Write-Verbose "getBucketNumObjects entered with $bname and storage class $stgclass" $metricNumObjects = Get-CWMetricStatistics -Credential $creds -region $region -Namespace 'AWS/S3' -MetricName 'NumberOfObjects' ` -Dimension @(@{ Name = 'BucketName'; Value = "$bname" }; @{ Name = 'StorageType'; Value = 'AllStorageTypes' }) ` -Statistic $Statistic -Period 86400 -UtcStartTime $daysAgo -UtcEndTime $today $numObjects = (($metricNumObjects.Datapoints | Measure-Object -Property $Statistic -Maximum).Maximum) if (!$numObjects) { $numObjects = 0 } $functionObj = New-Object -TypeName System.Management.Automation.PSObject -Property $obj $functionObj.Bucket = [string]$bname $functionObj.SizeGiB = '' $functionObj.NumObjects = $numObjects $functionObj.StorageClass = 'AllStorageTypes' $functionObj } ######################################################################### try { import-module AWSPowershell Write-Log -message "Start ......... Script" -path $log Set-DefaultAWSRegion -Region us-east-1 Set-AWSCredentials -AccessKey $AccessKey -SecretKey $SecretKey $Creds = (Use-STSRole -RoleArn "arn:aws:iam::123456789:role/Aws-Access-role" -RoleSessionName "assume_role_session").Credentials Write-Log -message "Loaded All Modules" -path $log Set-AWSCredential -AccessKey $Creds.AccessKeyId -SecretKey $Creds.SecretAccessKey -SessionToken $Creds.SessionToken } catch { $exception = $_.Exception.Message Write-Log -message "exception $exception has occured loading Modules - AWSS3BucketsReport" -path $log -Severity Error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error - AWSS3BucketsReport" -Body $($_.Exception.Message) break; } #############################GEt all Accounts################################################ try { Write-Log -message "Fetch all ORg Accounts" -path $log $allawsaccounts = Get-ORGAccountList | where{ $_.Status -eq "ACTIVE"} Write-Log -message "Fetch all ORg Regions" -path $log $regions = Get-EC2Region Write-Log -message "Total Accounts and Regions - $($allawsaccounts.count) - $($regions.count)" -path $log } catch { $exception = $_.Exception.Message Write-Log -message "exception $exception has occured loading Accounts - AWSS3BucketsReport" -path $log -Severity Error Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Error - AWSS3BucketsReport" -Body $($_.Exception.Message) break; } #################################get inventory################################################> $collinventory = @() foreach($awsAccount in $allawsaccounts) { $error.clear() $accoundid = $Accountname = $null $accoundid = $awsAccount.Id $Accountname = $awsAccount.Name if($accoundid -eq '987654321'){ Set-AWSCredentials -AccessKey $AccessKey -SecretKey $SecretKey $Creds = Get-AWSCredential } elseif($accoundid -eq '123456789'){ Set-AWSCredentials -AccessKey $AccessKey -SecretKey $SecretKey $Creds = (Use-STSRole -RoleArn "arn:aws:iam::123456789:role/Aws-Access-role" -RoleSessionName "assume_role_session").Credentials } else{ Set-AWSCredentials -AccessKey $AccessKey -SecretKey $SecretKey $Creds = (Use-STSRole -RoleArn "arn:aws:iam::123456789:role/Aws-Access-role" -RoleSessionName "assume_role_session").Credentials Set-AWSCredential -AccessKey $Creds.AccessKeyId -SecretKey $Creds.SecretAccessKey -SessionToken $Creds.SessionToken $Creds = (Use-STSRole -RoleArn $("arn:aws:iam::$accoundid" + ":role/Aws-Access-role") -RoleSessionName "assume_role_session_1").Credentials } if($error) { Write-Log -message "------Error on Account - $accoundid------" -path $Failedlog -Severity Warning $error.clear() } else { Write-Log -message "Success - $accoundid" -path $log $error.clear() $buckets = $null $buckets = Get-S3Bucket -Credential $Creds if($error) { $error.clear Write-Log -message "$accoundid - $($region.RegionName) Inventory not found" -path $log -Severity Warning } else { Write-Log -message "$accoundid - $($region.RegionName) Inventory found - $($buckets.count)" -path $log if($buckets) { $buckets | ForEach-Object{ $mcoll = "" | select Name,Day,AccountName,OwnerId,StorageinGB,Tags,Access,ObjectCount,RegionName $objects = $totalSizeGB = $tags = $BucketName=$S3BucketSize=$getbucketlocation = $NumObjects= $access = $null $BucketName = $_.BucketName $getbucketlocation = $(Get-S3BucketLocation -BucketName $BucketName -credential $Creds).Value switch($getbucketlocation) { "EU" { $regionname = "eu-west-1" } "$null" { $regionname = "us-east-1" } default { $regionname = $getbucketlocation} } $S3BucketSize = get-S3bucketsize -BucketName $BucketName -Region $regionname -StorageClass StandardStorage $NumObjects = $($S3BucketSize.Where{$_.StorageClass -eq "AllStorageTypes"}).NumObjects $totalSizeGB = $($S3BucketSize.Where{$_.StorageClass -eq "StandardStorage"}).SizeGiB Write-Log -message "BucketName - $BucketName BucketLocation - $regionname Objectscount - $NumObjects - $totalSizeGB" -path $log $Tags = Get-S3BucketTagging -BucketName $BucketName -credential $Creds -Region $regionname $mcoll.Name = $BucketName $mcoll.Day = (Get-Date).ToString("MM/dd/yyyy") $mcoll.AccountName = $Accountname $mcoll.OwnerId = $accoundid $mcoll.StorageinGB = $totalSizeGB $mcoll.Tags = ($tags | ConvertTo-csv -NoTypeInformation -Delimiter ":") -join "," $Access = get-S3publicAccessBlock -BucketName $BucketName -credential $Creds -Region $regionname if($error[0] -like "*Access Denied*"){ $mcoll.Access = "UnKnown" } if($Access.BlockPublicAcls -eq $false){ $mcoll.Access = "Public" } if($Access.BlockPublicAcls -eq $True){ $mcoll.Access = "Not Public" } if($Access -eq $null){ $mcoll.Access = "Not Public" } $mcoll.ObjectCount = $NumObjects $mcoll.RegionName = $regionname $collinventory += $mcoll } } } } } $collinventory | Export-Csv $report -NoTypeInformation Send-MailMessage -SmtpServer $smtpserver -From $from -To $email1 -bcc $erroremail -Subject "Report: AWS S3 Report - Buckets $($collinventory.count)" -Attachments $Report ###############################Recycle logs ############################################### Set-Recyclelogs -foldername "logs" -limit $logrecyclelimit -Confirm:$false Write-Log -Message "Script Finished" -path $log Send-MailMessage -SmtpServer $smtpserver -From $from -To $erroremail -Subject "Log - AWSS3BucketsReport" -Attachments $log |