├── .gitattributes
├── CloudTrail
└── Basics.ps1
├── EC2
├── BootstrapExample.ps1
├── Get-EC2Images_GroupByOwnerCount.ps1
├── Get-EC2VPCOrgs.ps1
├── Get-SnapshotsByOwner.ps1
├── ListAllEC2Instances.ps1
└── Register-IAMInstanceProfileToAllEC2.ps1
├── IAM
├── Convert Policy to Json.ps1
├── Get MFA Devices in all Orgs.ps1
├── Get-IAMUsersMFAStatus.ps1
├── GetAWSUsersInRoles_allOrgs.ps1
├── GetAccessKeyList_AllOrgs.ps1
├── GetCredentialReport.ps1
├── Level6.ps1
├── New-IAMAuditor - RAPID 7 deployment.ps1
├── New-IAMAuditor.ps1
├── New-MFADevice.ps1
├── Remove-IAMAccessKeyAllOrgs.ps1
├── Update-PasswordPolicyAllOrgs.ps1
└── security_assessment_access.template
├── LICENSE
├── Organizations
├── Get-AllOrgOus.ps1
└── Get-OrgPolicyInformation.ps1
├── README.md
├── S3
├── FlawsS3Buckets.ps1
├── Get-AWSCanonicalUserID.ps1
├── Get-AccessKeysInMetadata.ps1
├── Get-AccessKeysInS3.ps1
├── Get-S3AllObjectMetadata.ps1
├── Get-S3BucketRegion.ps1
├── List All Files In Buckets.ps1
└── Set-S3ACLEasy.ps1
├── STS
├── Get-AWSTempCred.ps1
└── STS Switch Roles in Organization.ps1
└── SecurityHub
└── AddUsertoHub.ps1
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/CloudTrail/Basics.ps1:
--------------------------------------------------------------------------------
1 | $events = Find-CTEvent -StartTime (get-date).AddDays(-1) -EndTime (get-date) -MaxResult 50
2 |
3 |
4 | convertfrom-json($events[0].cloudtrailevent)
5 | (convertfrom-json($events[0].cloudtrailevent)).useridentity
6 | (convertfrom-json($events[0].cloudtrailevent)).useridentity.sessioncontext
7 | (convertfrom-json($events[0].cloudtrailevent)).useridentity.sessioncontext.attributes
--------------------------------------------------------------------------------
/EC2/BootstrapExample.ps1:
--------------------------------------------------------------------------------
1 |
2 |
3 | $installdir = "C:\Bootstrap"
4 | $filename = "filename.zip"
5 | mkdir $installdir
6 | set-location $installdir
7 |
8 | #download file to the folder on local machine
9 | $WebClient = New-object System.net.webclient
10 | $FileURL = "Http://s3bucketlocation/Filurl/" + $filename
11 | $localfile = $installdir + "\" + $filename
12 | $WebClient.DownloadFile("$fileurl","$localfile")
13 |
14 |
15 | #unzip file onto local machine
16 | $NewShell = new-object -com shell.application
17 | $zipFilePath = $newshell.namespace($localfile);
18 | $dest = $NewShell.namespace((get-location).path)
19 | $destionation.copyhere($zipfilepath.items(),0x14)
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/EC2/Get-EC2Images_GroupByOwnerCount.ps1:
--------------------------------------------------------------------------------
1 | #get only machines with ownerid count is 1-5
2 | #
3 |
4 | Function Get-EC2Images_GroupByOwnerCount{
5 |
6 | param (
7 | [Parameter(Mandatory=$true)][int]$MaxImages
8 |
9 | )
10 |
11 | $filter = @{
12 | Name = 'Owner-id'
13 | Values = '137112412989'
14 | }
15 | $CommonOwners = @('099720109477','137112412989')
16 | get-date
17 | $amilist = @()
18 | Get-AWSRegion|%{
19 | $amilist += Get-EC2Image -Region $_.Region| where {$filter}
20 | }
21 | get-date
22 | <#PS $amilist.count
23 | 105431
24 | $amilist2 = get-ec2image -Region eu-west-1
25 | $amilist2.count
26 | 85700
27 | #>
28 |
29 |
30 | $COmmonOwners|%{
31 | $amilist = $amilist|Where-Object -Property ownerid -NE $_
32 | }
33 |
34 |
35 | group-object
36 |
37 |
38 |
39 | }
--------------------------------------------------------------------------------
/EC2/Get-EC2VPCOrgs.ps1:
--------------------------------------------------------------------------------
1 | Function Get-EC2VpcOrgs {
2 | [cmdletbinding()]
3 | param(
4 | [Parameter(Mandatory=$true)][string]$Role, #role used for cross account access
5 | [object]$OrganizationList, #Supply region list you want to test against
6 | [switch]$SkipDefault #if specified, do not list any default VPCs in output
7 | )
8 | if (!$OrganizationList){$OrganizationList = Get-ORGAccountList }else{}
9 | $regions = Get-AWSRegion |Where-Object {
10 | $_.Region -ne 'me-south-1' -and
11 | $_.region -ne 'ap-east-1'}
12 | $orgProgress = 1
13 | $ocount = $organizationlist.count
14 | $originID = (Get-STSCallerIdentity).account
15 | $vpcArray = @()
16 | $OrganizationList |%{
17 |
18 | $orgid = $_.ID
19 | $oname = $_.Name
20 | if ($orgid -ne $originID){$Credentials = Get-STSCreds -OrganizationID $orgid -role $role}
21 | Write-Progress -Activity "Searching Through Orgs: $oname" -id 1 -Status "$orgProgress complete of $ocount" -PercentComplete ($orgProgress/$ocount*100)
22 |
23 | $regionProgress = 1
24 | $rcount = $regions.count
25 | $Regions |%{
26 |
27 | $region = $_
28 | $rname = $_.name
29 | Write-Progress -Activity "Searching Through REGION: $rname on ORG: $oname" -id 2 -Status "$regionProgress complete of $Rcount" -PercentComplete ($regionProgress/$Rcount*100) -CurrentOperation "Looking for VPCs in all regions for All Orgs"
30 | if ($orgid -ne $originID){$VPCs = get-ec2vpc -Region $_.Region -Credential $Credentials}else{
31 | $VPCs = get-ec2vpc -Region $_.Region
32 | }
33 |
34 | $VPCs |%{
35 | if($SkipDefault -and $_.IsDefault -eq $true){}Else{
36 | $obj = new-object psobject
37 | $obj |Add-member NoteProperty OrganizationID $orgid
38 | $obj |Add-member NoteProperty OrganizationName $oName
39 | $obj |Add-member NoteProperty Region $rname
40 | $obj |Add-member NoteProperty VPC $VPCs
41 | $obj |Add-member NoteProperty CidrBlock $_.CidrBlock
42 | $obj |Add-member NoteProperty IsDefault $_.IsDefault
43 | if($_.tags.key -contains 'Name'){
44 | $n = ($_.tags|where-object {$_.key -eq 'Name'}).value
45 | }else{
46 | $n = 'NoTagName'
47 | }
48 | $obj |Add-member NoteProperty Name $n
49 | $obj |Add-member NoteProperty OwnerID $_.OwnerId
50 | $obj |Add-member NoteProperty VPCID $_.VpcId
51 | $obj |Add-member NoteProperty State $_.State
52 |
53 | $VPCArray += $obj
54 | }
55 | }
56 |
57 |
58 |
59 |
60 | $regionProgress++
61 | }
62 |
63 | $orgProgress++
64 | }
65 | $VPCArray
66 | }
67 |
68 | #list all orgs, foreach org, get all regions, foreach region get ec2vpcs,
--------------------------------------------------------------------------------
/EC2/Get-SnapshotsByOwner.ps1:
--------------------------------------------------------------------------------
1 | Function Get-SnapshotsByOwner{
2 |
3 | param (
4 | [Parameter(Mandatory=$true)][string]$OrganizationID,
5 | [Parameter(Mandatory=$true)][string]$Profile
6 |
7 | )
8 | $snapshotlist = @()
9 | Get-AWSRegion|%{
10 | $rn = $_.Region
11 | try{$snapshotlist += Get-EC2Snapshot -ProfileName $Profile -Region $_.region -OwnerId $OrganizationID}
12 | catch{write-host "Error on Region $rn"}
13 |
14 | }
15 | $snapshotlist
16 | }
--------------------------------------------------------------------------------
/EC2/ListAllEC2Instances.ps1:
--------------------------------------------------------------------------------
1 | Function Get-EC2InstanceList {
2 | [CmdletBinding()]
3 |
4 | param
5 | (
6 | [Parameter(Mandatory = $false,
7 | Position = 1,
8 | HelpMessage = 'Supply a stored AWS credential role authorized for cross accounts listing')]
9 | [System.String]$Role
10 | )
11 |
12 |
13 | $regions = Get-AWSRegion
14 | $rcount = $Regions.count
15 | $ec2Array = @()
16 | if ($Role){
17 | $orgs = Get-ORGAccountList
18 | $orgProgress = 1
19 | $ocount = $orgs.count
20 |
21 | $orgs|%{
22 | $org = $_
23 | $oname = $org.name
24 | Write-Progress -Activity "Searching Through Org: $oname" -id 1 -Status "$orgProgress complete of $ocount" -PercentComplete ($orgProgress/$ocount*100)
25 |
26 | $regionProgress = 1
27 | try{
28 | try{$Credentials = Get-STSCreds -OrganizationID $_.Id -role $role
29 | $regions | % {
30 | $oname = $org.name
31 | $region = $_
32 | $rname = $_.name
33 | Write-Progress -Activity "Searching Through REGION: $rname on ORG: $oname" -id 2 -Status "$regionProgress complete of $Rcount" -PercentComplete ($regionProgress/$Rcount*100) -CurrentOperation "Looking for EC2s in all regions for All Orgs"
34 |
35 | try{$ec2 = Get-EC2Instance -Credential $Credentials -Region $_.Region
36 | $EC2|%{
37 | Clear-Variable -Name status
38 | $status = Get-ec2instancestatus -InstanceId $_.instances.instanceid -Region $region.Region -Credential $Credentials
39 | $Pemkey = $ec2 |select instances
40 | $obj = new-object psobject
41 |
42 | $obj |Add-member NoteProperty OrganizationID $org.id
43 | $obj |Add-member NoteProperty OrganizationName $org.Name
44 | $obj |Add-member NoteProperty InstanceID $_.instances.instanceid
45 | $obj |Add-member NoteProperty InstanceType $_.instances.InstanceType
46 | $obj |Add-member NoteProperty Region $region.Region
47 | if($status){
48 | $obj |Add-member NoteProperty InstanceState $status.instancestate.name
49 | $obj |Add-member NoteProperty Reachability $status.status.status
50 | $obj |Add-member NoteProperty InstanceStatus $status
51 |
52 | }
53 | else{
54 | $obj |Add-member NoteProperty InstanceState "NoStateFound"
55 | $obj |Add-member NoteProperty Reachability "NoStateFound"
56 | $obj |Add-member NoteProperty InstanceStatus "NoStateFound"
57 | }
58 | $obj |Add-member NoteProperty Instances $_.instances
59 | $ec2Array += $obj
60 |
61 | }
62 |
63 | }
64 | catch{}
65 | $regionProgress++
66 | }
67 | }
68 | catch{}
69 | #Iterate over all regions and list instances
70 |
71 | }
72 | catch{$regions | % {
73 | $oname = $org.name
74 | $region = $_
75 | $rname = $_.name
76 | Write-Progress -Activity "Searching Through REGION: $rname on ORG: $oname" -id 2 -Status "$regionProgress complete of $Rcount" -PercentComplete ($regionProgress/$Rcount*100) -CurrentOperation "Looking for EC2s in all regions for All Orgs"
77 | try{$ec2 = Get-EC2Instance -Region $_.Region
78 | $EC2|%{
79 | Clear-Variable -Name status
80 | $status = Get-ec2instancestatus -InstanceId $_.instances.instanceid -Region $region.Region
81 | $Pemkey = $_ |select instances
82 | $obj = new-object psobject
83 |
84 | $obj |Add-member NoteProperty OrganizationID $org.id
85 | $obj |Add-member NoteProperty OrganizationName $org.Name
86 | $obj |Add-member NoteProperty InstanceID $_.instances.instanceid
87 | $obj |Add-member NoteProperty InstanceType $_.instances.InstanceType
88 | $obj |Add-member NoteProperty Region $region.Region
89 | if($status){
90 | $obj |Add-member NoteProperty InstanceState $status.instancestate.name
91 | $obj |Add-member NoteProperty Reachability $status.status.status
92 | $obj |Add-member NoteProperty InstanceStatus $status
93 |
94 | }
95 | else{
96 | $obj |Add-member NoteProperty InstanceState "NoStateFound"
97 | $obj |Add-member NoteProperty Reachability "NoStateFound"
98 | $obj |Add-member NoteProperty InstanceStatus "NoStateFound"
99 | }
100 | $obj |Add-member NoteProperty Instances $ec2.instances
101 | $ec2Array += $obj
102 |
103 | }
104 |
105 | }
106 | catch{}
107 | $regionProgress++
108 | }
109 | }
110 | $orgProgress++
111 | }
112 | }else{ #NO role Specified, only doing for 1 account
113 |
114 | $regions | % {
115 | $oname = Get-IAMAccountAlias
116 | $acctid = (Get-STSCallerIdentity).account
117 | if (!$oname){$oname = 'NoAccountAlias'}
118 | $region = $_
119 | $rname = $_.name
120 | Write-Progress -Activity "Searching Through REGION: $rname on ORG: $oname" -id 2 -Status "$regionProgress complete of $Rcount" -PercentComplete ($regionProgress/$Rcount*100) -CurrentOperation "Looking for EC2s in all regions for All Orgs"
121 | try{$ec2 = Get-EC2Instance -Region $_.Region
122 | $EC2|%{
123 | Clear-Variable -Name status
124 | $status = Get-ec2instancestatus -InstanceId $_.instances.instanceid -Region $region.Region
125 | $Pemkey = $_ |select instances
126 | $obj = new-object psobject
127 |
128 | $obj |Add-member NoteProperty OrganizationID $acctid
129 | $obj |Add-member NoteProperty OrganizationName $oname
130 | $obj |Add-member NoteProperty InstanceID $_.instances.instanceid
131 | $obj |Add-member NoteProperty InstanceType $_.instances.InstanceType
132 | $obj |Add-member NoteProperty Region $region.Region
133 | if($status){
134 | $obj |Add-member NoteProperty InstanceState $status.instancestate.name
135 | $obj |Add-member NoteProperty Reachability $status.status.status
136 | $obj |Add-member NoteProperty InstanceStatus $status
137 |
138 | }
139 | else{
140 | $obj |Add-member NoteProperty InstanceState "NoStateFound"
141 | $obj |Add-member NoteProperty Reachability "NoStateFound"
142 | $obj |Add-member NoteProperty InstanceStatus "NoStateFound"
143 | }
144 | $obj |Add-member NoteProperty Instances $ec2.instances
145 | $ec2Array += $obj
146 |
147 | }
148 |
149 | }
150 | catch{}
151 | $regionProgress++
152 | }
153 |
154 | }
155 |
156 |
157 |
158 |
159 | $ec2Array
160 |
161 | }
162 |
163 |
164 |
165 |
--------------------------------------------------------------------------------
/EC2/Register-IAMInstanceProfileToAllEC2.ps1:
--------------------------------------------------------------------------------
1 | Function Register-EC2IamInstanceProfileAll {
2 | [CmdletBinding()]
3 |
4 | param
5 | (
6 | [Parameter(Mandatory = $true,
7 | Position = 1,
8 | HelpMessage = 'List of EC2s to attach IAM Role onto')]
9 | [object]$EC2List,
10 | [Parameter(Mandatory = $true,
11 | Position = 2,
12 | HelpMessage = 'The EC2 IAM Role to be attached to EC2 in list')]
13 | [System.String]$InstanceProfileName,
14 | [Parameter(Mandatory = $false,
15 | Position = 3,
16 | HelpMessage = 'Cross account role with access to set ec2 instance profiles')]
17 | [System.String]$Role
18 | )
19 | $ec2array = @()
20 | if($Role){
21 |
22 | }else{
23 | $EC2Profile = Get-IAMInstanceProfile -InstanceProfileName $InstanceProfileName
24 | if (!$EC2Profile){Write-Warning "$InstanceProfileName Does not exist. Exiting Script"}
25 | $EC2List |%{
26 | clear-variable -name attached
27 | $ec2id = $_.instanceid
28 | $ec2region = $_.region
29 | $attached = Get-EC2IamInstanceProfileAssociation -Filter @{name='instance-id'; values=$ec2id} -Region $ec2region
30 | if ($attached.IamInstanceProfile.id -contains $EC2Profile.InstanceProfileId){
31 | #do nothing, already attached
32 | $profileinfo = Get-EC2IamInstanceProfileAssociation -Region $ec2region |where {($_.instanceid -eq $ec2id) -and ($_.iaminstanceprofile.id -eq $EC2Profile.instanceprofileid)}
33 | $obj = new-object psobject
34 |
35 | $obj |Add-member NoteProperty InstanceID $ec2id
36 | $obj |Add-member NoteProperty Region $ec2region
37 | $obj |Add-member NoteProperty ProfileName $InstanceProfileName
38 | $obj |Add-Member Noteproperty AttachedStatus $profileinfo
39 | $ec2array += $obj
40 | }else{
41 | $iamec2arn = $ec2profile.arn
42 | Register-EC2IamInstanceProfile -InstanceId $ec2id -region $ec2region -IamInstanceProfile_Arn $iamec2arn
43 | $profileinfo = Get-EC2IamInstanceProfileAssociation -Region $ec2region |where {($_.instanceid -eq $ec2id) -and ($_.iaminstanceprofile.id -eq $EC2Profile.instanceprofileid)}
44 |
45 | $obj = new-object psobject
46 |
47 | $obj |Add-member NoteProperty InstanceID $ec2id
48 | $obj |Add-member NoteProperty Region $ec2region
49 | $obj |Add-member NoteProperty ProfileName $InstanceProfileName
50 | $obj |Add-Member Noteproperty AttachedStatus $profileinfo
51 | $ec2array += $obj
52 | }
53 | }
54 | }
55 | $ec2array
56 | }
--------------------------------------------------------------------------------
/IAM/Convert Policy to Json.ps1:
--------------------------------------------------------------------------------
1 | Function Convert-PolicyToJson {
2 |
3 | param (
4 | $Policy
5 | )
6 | if (($Policy|gm).name -contains 'document'){
7 | [System.Reflection.Assembly]::LoadWithPartialName("System.Web.HttpUtility")
8 | $policy = [System.Web.HttpUtility]::UrlDecode($Policy.Document)
9 | $policy
10 | }
11 |
12 | }
--------------------------------------------------------------------------------
/IAM/Get MFA Devices in all Orgs.ps1:
--------------------------------------------------------------------------------
1 | Function Get-MFADevicesAllOrgs {
2 | param (
3 |
4 | [Parameter(Mandatory=$true)][string]$Role
5 |
6 | )
7 | $mfadevices = @()
8 | $orgs = Get-ORGAccountList|select id, name, email
9 | foreach ($org in $orgs){
10 | $orgid = $null
11 | $credentials = $null
12 | $rolearn = $null
13 |
14 | $Orgid= $org.id
15 | $RoleArn = "arn:aws:iam::${Orgid}:role/$role"
16 | if ((Get-STSCallerIdentity).account -ne $Orgid){
17 | write-verbose "On $orgID"
18 | try{$credentials = Switch-AWSRoles -OrganizationID $Orgid -Role $Role
19 | #Get-IAMVirtualMFADevice -Credential $Credentials
20 | $mfadevices += Get-IAMVirtualMFADevice -Credential $Credentials
21 | }
22 | Catch{write-verbose $error[0]}
23 | }
24 |
25 | else{
26 | $mfadevices += Get-IAMVirtualMFADevice
27 | }
28 |
29 | }
30 | $MFAreadable = @()
31 |
32 | foreach ($device in $mfadevices){
33 | $obj = new-object psobject
34 | $obj |Add-member NoteProperty SerialNumber $device.serialnumber
35 | $obj |Add-member NoteProperty DevOrganizationID $(($device.serialnumber -split ":")[4])
36 | $obj | Add-member NoteProperty UserARN $device.user.Arn
37 | $obj | Add-member NoteProperty UserName $device.user.UserName
38 | $obj |Add-member NoteProperty UserOrganizationID $(($device.user.Arn -split ":")[4])
39 | $MFAreadable += $obj
40 | }
41 | $mfareadable
42 | }
--------------------------------------------------------------------------------
/IAM/Get-IAMUsersMFAStatus.ps1:
--------------------------------------------------------------------------------
1 |
2 |
3 | function Get-IAMUsersMFAStatus {
4 | #used in conjunction with list all admins output
5 | param (
6 | [parameter(Mandatory=$true)][object]$UserList,
7 | [parameter(Mandatory=$true)][string]$Role
8 |
9 | )
10 |
11 | $mfadevices = @()
12 | $MFAreadable = @()
13 | $MFAListAll = @()
14 | foreach ($org in $userlist){
15 | $orgid = $null
16 | $polgroupmembers = $null
17 | $policyusers = $null
18 | $orgid = $org.organizationid
19 | $polgroupmembers = $org.polgroupmembers
20 | $policyusers = $org.policyusers
21 |
22 |
23 | $account = $orgid
24 | #$RoleArn = "arn:aws:iam::${Account}:role/$role"
25 | if ((Get-STSCallerIdentity).account -ne $orgid){
26 | #$Response = (Use-STSRole -Region $Region -RoleArn $RoleArn -RoleSessionName 'CMDB').Credentials
27 | $Credentials = Switch-AWSRoles -OrganizationID $orgid -Role $role
28 | #New-AWSCredentials -AccessKey $Response.AccessKeyId -SecretKey $Response.SecretAccessKey -SessionToken $Response.SessionToken
29 | $mfadevices += Get-IAMVirtualMFADevice -Credential $Credentials
30 | } else {
31 | $mfadevices += Get-IAMVirtualMFADevice
32 | }
33 |
34 | #
35 | foreach ($device in $mfadevices){
36 | $obj = new-object psobject
37 | $obj |Add-member NoteProperty SerialNumber $device.serialnumber
38 | $obj | Add-member NoteProperty UserARN $device.user.Arn
39 | $obj |Add-member NoteProperty OrganizationID $(($device.serialnumber -split ":")[4])
40 | $obj | Add-member NoteProperty UserName $device.user.UserName
41 | $MFAreadable += $obj
42 | }
43 |
44 |
45 |
46 | #check for root in mfareadable
47 | $obj = new-object psobject
48 | $obj |Add-member NoteProperty OrganizationID $org.OrganizationID
49 | $obj |Add-member NoteProperty OrganizationName $org.OrganizationName
50 | $obj |Add-member Noteproperty Username "Root"
51 | $orgID = $org.OrganizationID
52 | $rootarn = "arn:aws:iam::${orgid}:root"
53 | $rootmfaexists = $null
54 | $rootmfaexists = ($mfadevices.user.arn -contains $rootarn)
55 | if ($rootmfaexists -eq $true){
56 | #this if shows that an mfa device is created for the root account
57 | $obj |Add-member NoteProperty MFAEnabled "YES"
58 | }else {
59 | #this else shows there is no MFA device created for the root accoutn
60 | $obj |Add-member NoteProperty MFAEnabled "NO"
61 | }
62 | $mfalistall += $obj
63 | if($org.polgroupmembers.count -gt 0){
64 | foreach ($u in $org.polgroupmembers){
65 | $obj = new-object psobject
66 | $orgID = $org.OrganizationID
67 | $uname = $u.username
68 |
69 | $obj |Add-member NoteProperty OrganizationID $orgID
70 | $obj |Add-member NoteProperty OrganizationName $org.OrganizationName
71 | $obj |Add-member Noteproperty Username $uname
72 |
73 | $arn = "arn:aws:iam::${orgid}:user/${Uname}"
74 |
75 | $rootmfaexists = $null
76 | $rootmfaexists = ($MFAreadable.userarn -eq $arn)
77 | if ($rootmfaexists){
78 | #this if shows that an mfa device is created for the root account
79 | $obj |Add-member NoteProperty MFAEnabled "YES"
80 | }
81 | else {
82 | #this else shows there is no MFA device created for the root accoutn
83 | $obj |Add-member NoteProperty MFAEnabled "NO"
84 | }
85 | $mfalistall += $obj
86 | }
87 |
88 | }
89 | if($org.policyusers.count -gt 0){
90 | foreach ($u in $org.policyusers){
91 | $obj = new-object psobject
92 | $orgID = $org.OrganizationID
93 | $uname = $u.username
94 | $obj |Add-member NoteProperty OrganizationID $org.OrganizationID
95 | $obj |Add-member NoteProperty OrganizationName $org.OrganizationName
96 | $obj |Add-member Noteproperty Username $uname
97 |
98 | $arn = "arn:aws:iam::${orgid}:user/${Uname}"
99 | $rootmfaexists = $null
100 | $rootmfaexists = ($MFAreadable.userarn -eq $arn)
101 | if ($rootmfaexists){
102 | #this if shows that an mfa device is created for the root account
103 | $obj |Add-member NoteProperty MFAEnabled "YES"
104 | }
105 | else {
106 | #this else shows there is no MFA device created for the root accoutn
107 | $obj |Add-member NoteProperty MFAEnabled "NO"
108 | }
109 | $mfalistall += $obj
110 | }
111 |
112 | }
113 | }
114 |
115 |
116 | #now i have all the mfa devices in an entire org, split the $mfadevices into an object that is org id/ user
117 |
118 | $MFALISTALL |Sort-Object -Property organizationid,username -Unique
119 |
120 | }
121 |
122 |
--------------------------------------------------------------------------------
/IAM/GetAWSUsersInRoles_allOrgs.ps1:
--------------------------------------------------------------------------------
1 | Function Get-IAMUsersInRoleAllOrgs {
2 | [alias("Get-AWSRoleUserList")]
3 | #This function currently lists all IAM user accounts specified in an instance under the policy titled: AdministratorAccess
4 | param(
5 | [Parameter(Mandatory=$true)]$Role, #where $role is the role you want to assume to authenticate to another organization.
6 | [string]$PolicyName = "AdministratorAccess",
7 | [switch]$AllUsers
8 | )
9 | $orgs = Get-ORGAccountList|select id, name, email
10 | $adminlist = @()
11 | $userlist = @()
12 | foreach ($org in $orgs){
13 | if($AllUsers){
14 | $id =$org.Id
15 | $nm = $org.name
16 | #write-host "On account $id $nm"
17 | $obj = new-object psobject
18 | $obj |Add-member NoteProperty OrganizationID $id
19 | $obj |Add-member NoteProperty Arn $org.arn
20 | $obj | Add-Member NoteProperty OrganizationName $nm
21 | $account = $org.id
22 | $Credentials = Get-STSCreds -OrganizationID $id -Role $role
23 | $userinORglist = Get-IAMUserList -Credential $Credentials
24 | $obj |add-member NoteProperty IAMUsers $userinORglist
25 | $userlist += $obj
26 | }else{
27 | $id =$org.Id
28 | $nm = $org.name
29 | #write-host "On account $id $nm"
30 | $obj = new-object psobject
31 | $obj |Add-member NoteProperty OrganizationID $id
32 | $obj |Add-member NoteProperty Arn $org.arn
33 | $obj | Add-Member NoteProperty OrganizationName $nm
34 | $account = $org.id
35 |
36 | #$RoleArn = "arn:aws:iam::${Account}:role/$role"
37 |
38 | #Request temporary credentials for each account and create a credential object
39 | try {
40 | #$Response = (Use-STSRole -Region $Region -RoleArn $RoleArn -RoleSessionName 'CMDB').Credentials
41 | $Credentials = Switch-AWSRoles -OrganizationID $id -Role $role
42 | #New-AWSCredentials -AccessKey $Response.AccessKeyId -SecretKey $Response.SecretAccessKey -SessionToken $Response.SessionToken
43 |
44 | #List all policies, get all entities on policy
45 | $admins = ""
46 | $admins = Get-IAMEntitiesForPolicy -PolicyArn "arn:aws:iam::aws:policy/$PolicyName" -Credential $Credentials
47 | $obj | add-member NoteProperty PolicyGroups $admins.policygroups
48 | if ($admins.policygroups.count -gt 0){
49 | $i = 0
50 | foreach ($grp in $admins.policygroups){
51 | $grpmembers = get-iamgroup -GroupName $admins.PolicyGroups[$i].groupname -Credential $Credentials
52 | $obj |add-member NoteProperty PolGroupMembers $grpmembers.users
53 | $i++
54 | $grpmembers = $null
55 | }
56 |
57 | }
58 | else{
59 |
60 | }
61 | }
62 | catch {$admins = Get-IAMEntitiesForPolicy -PolicyArn "arn:aws:iam::aws:policy/$PolicyName"
63 | $obj | add-member NoteProperty PolicyGroups $admins.policygroups
64 | if ($admins.policygroups.count -gt 0){
65 | $i = 0
66 | foreach ($grp in $admins.policygroups){
67 | $grpmembers = get-iamgroup -GroupName $admins.PolicyGroups[$i].groupname
68 | $obj |add-member NoteProperty PolGroupMembers $grpmembers.users
69 | $i++
70 | }
71 |
72 | }
73 | else{
74 |
75 | }
76 | }
77 |
78 |
79 | $obj | add-member NoteProperty PolicyRoles $admins.PolicyRoles
80 | $obj | add-member NoteProperty PolicyUsers $admins.PolicyUsers
81 | $adminlist += $obj
82 |
83 |
84 | }}
85 |
86 | if ($AllUsers){$userlist}else{
87 | $adminlist }
88 | }
89 |
--------------------------------------------------------------------------------
/IAM/GetAccessKeyList_AllOrgs.ps1:
--------------------------------------------------------------------------------
1 | Function Get-IAMAccessKeysAllOrgs{
2 |
3 | param(
4 | [Parameter(Mandatory=$true)]$Role
5 |
6 | )
7 |
8 | $orgs = Get-ORGAccountList|select id, name, email
9 | $AKDetails = @()
10 |
11 | $accesskeys = @()
12 |
13 | foreach ($org in $orgs){
14 | $id =$org.Id
15 | $nm = $org.name
16 | $userlist = @()
17 | $accesskeys = @()
18 | if ((Get-STSCallerIdentity).account -ne $id){
19 |
20 | $id = $null
21 | $credentials = $null
22 | $rolearn = $null
23 |
24 | $id= $org.id
25 | $RoleArn = "arn:aws:iam::${Orgid}:role/$role"
26 | $Credentials = Switch-AWSRoles -OrganizationID $id -Role $role
27 | $userlist = get-iamuserlist -Credential $Credentials
28 | $userlist |% {
29 | $uarn = $_.arn
30 | $uorg = ($uarn -split ":")[4]
31 | $accesskeys += Get-IAMAccessKey -UserName $_.UserName -Credential $credentials
32 | }
33 | $accesskeys |% {
34 | $lastused = Get-IAMAccessKeyLastUsed -AccessKeyId $_.AccessKeyId -Credential $credentials
35 |
36 | $obj = new-object psobject
37 | $obj |Add-member NoteProperty OrganizationID $uorg
38 | $obj |Add-member NoteProperty OrganizationName $nm
39 | $obj |Add-member NoteProperty UserName $lastused.UserName
40 | $obj |Add-member Noteproperty AccessKeyID $_.AccessKeyId
41 | $obj |Add-Member NoteProperty KeyCreateDate $_.CreateDate
42 | $obj |Add-Member NoteProperty KeyStatus $_.Status
43 | $obj |Add-member Noteproperty LastUsed $lastused.AccessKeyLastUsed.LastUsedDate
44 | $obj |Add-member Noteproperty Region $lastused.AccessKeyLastUsed.Region
45 | $obj |Add-member Noteproperty Service $lastused.AccessKeyLastUsed.ServiceName
46 | $akdetails += $obj
47 | }
48 | }
49 |
50 | else {
51 |
52 |
53 | $id = $null
54 | $credentials = $null
55 | $rolearn = $null
56 |
57 | $id= $org.id
58 | $userlist = get-iamuserlist
59 | $userlist |% {
60 | $uarn = $_.arn
61 | $uorg = ($uarn -split ":")[4]
62 | $accesskeys += Get-IAMAccessKey -UserName $_.UserName
63 | }
64 | $accesskeys |% {
65 | $lastused = Get-IAMAccessKeyLastUsed -AccessKeyId $_.AccessKeyId
66 |
67 | $obj = new-object psobject
68 | $obj |Add-member NoteProperty OrganizationID $uorg
69 | $obj |Add-member NoteProperty OrganizationName $nm
70 | $obj |Add-member NoteProperty UserName $lastused.UserName
71 | $obj |Add-member Noteproperty AccessKeyID $_.AccessKeyId
72 | $obj |Add-Member NoteProperty KeyCreateDate $_.CreateDate
73 | $obj |Add-Member NoteProperty KeyStatus $_.Status
74 | $obj |Add-member Noteproperty LastUsed $lastused.AccessKeyLastUsed.LastUsedDate
75 | $obj |Add-member Noteproperty Region $lastused.AccessKeyLastUsed.Region
76 | $obj |Add-member Noteproperty Service $lastused.AccessKeyLastUsed.ServiceName
77 | $akdetails += $obj
78 | }
79 | }
80 |
81 | }
82 | $akdetails |sort-object organizationid,LastUsed
83 |
84 | }
85 |
86 |
87 |
88 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/IAM/GetCredentialReport.ps1:
--------------------------------------------------------------------------------
1 | function Get-AWSCredentialReport {
2 |
3 | param(
4 | [string]$Role
5 | )
6 | $originID = (Get-STSCallerIdentity).account
7 | $objects = @()
8 | if(!$Role){
9 | Request-IAMCredentialReport |Out-Null
10 | $report = Get-iamCredentialReport -AsTextArray
11 |
12 | $columnnames = $report[0] -split ','
13 | $i = 1 #start above first line
14 |
15 | do {
16 | $values = $report[$i] -split ','
17 |
18 | $columnnum = 0
19 | $obj = new-object psobject
20 | foreach ($column in $columnnames){
21 | $obj |Add-member NoteProperty $column $values[$columnnum]
22 | $columnnum++
23 | }
24 | $objects += $obj
25 |
26 | $i++
27 | }
28 | while ($i -lt $report.count)
29 | }else{
30 | $OrgAccountList = Get-ORGAccountList
31 | $ocount = $OrgAccountList.count
32 | $orgProgress = 1
33 |
34 | foreach ($acct in $orgaccountlist){
35 | $orgid = $acct.ID
36 | $oname = $acct.Name
37 | if ($orgid -ne $originID){$Credentials = Get-STSCreds -OrganizationID $orgid -role $role}
38 | Write-Progress -Activity "Searching Through Orgs: $oname" -id 1 -Status "$orgProgress complete of $ocount" -PercentComplete ($orgProgress/$ocount*100)
39 | ###Adding code here
40 | if ($orgid -ne $originID){Request-IAMCredentialReport -Credential $credentials|Out-Null
41 | $report = Get-iamCredentialReport -Credential $Credentials -AsTextArray
42 | }else{
43 | Request-IAMCredentialReport|Out-Null
44 | $report = Get-iamCredentialReport -AsTextArray
45 | }
46 |
47 |
48 | $columnnames = $report[0] -split ','
49 | $i = 1 #start above first line
50 |
51 | do {
52 | $values = $report[$i] -split ','
53 |
54 | $columnnum = 0
55 | $obj = new-object psobject
56 | $obj |Add-member NoteProperty AccountID $acct.id
57 | $obj |Add-member NoteProperty AccountName $acct.Name
58 | foreach ($column in $columnnames){
59 | $obj |Add-member NoteProperty $column $values[$columnnum]
60 | $columnnum++
61 | }
62 | $objects += $obj
63 |
64 | $i++
65 | }
66 | while ($i -lt $report.count)
67 | ###
68 |
69 | $orgProgress++
70 | }
71 | }
72 |
73 |
74 |
75 | $objects
76 | }
--------------------------------------------------------------------------------
/IAM/Level6.ps1:
--------------------------------------------------------------------------------
1 | #Show attached policies to user and other user info:
2 | $profile = "level6"
3 | $user = (Get-IAMAccountAuthorizationDetail -ProfileName $profile).UserDetailList|Where-Object -Property arn -eq ((Get-STSCallerIdentity -ProfileName $profile).Arn)
4 |
5 | $user.attachedmanagedpolicies
6 |
7 | Get-IAMPolicy -PolicyArn arn:aws:iam::975426262029:policy/list_apigateways
8 |
9 | Get-IAMPolicyversion -PolicyArn arn:aws:iam::975426262029:policy/list_apigateways -VersionId v4
10 |
11 | get-lmfunctionlist
12 |
13 | $pol = Get-LMPolicy -FunctionName Level6
14 | $temp = (ConvertFrom-Json $pol.Policy).statement
15 | $temp.condition
16 | <#
17 | ArnLike
18 | -------
19 | @{AWS:SourceArn=arn:aws:execute-api:us-west-2:975426262029:s33ppypa75/*/GET/level6}
20 | #>
21 | get-agstagelist -RestApiId s33ppypa75
22 |
23 | build url =
24 | htt[s://$lambdaname.$executeapi.$region.amazonaws.com/$stagelist.Stagename/
--------------------------------------------------------------------------------
/IAM/New-IAMAuditor - RAPID 7 deployment.ps1:
--------------------------------------------------------------------------------
1 | get orgs
2 | sift through, foreach do assume role, and then new iamauditor
3 |
4 | $STSRole = 'Credential-role'
5 | #=====================================
6 | $policyjson = '{
7 | "Version": "2012-10-17",
8 | "Statement": [
9 | {
10 | "Effect": "Allow",
11 | "Action": [
12 | "acm:ListTagsForCertificate",
13 | "cloudtrail:ListPublicKeys",
14 | "cloudtrail:ListTags",
15 | "cloudtrail:GetTrailStatus",
16 | "cloudtrail:GetEventSelectors",
17 | "ecr:DescribeRepositories",
18 | "ecr:GetLifecyclePolicy",
19 | "ecr:GetRepositoryPolicy",
20 | "ecr:ListImages",
21 | "iam:GenerateServiceLastAccessedDetails",
22 | "lambda:GetFunction",
23 | "lambda:GetLayerVersion",
24 | "lambda:GetLayerVersionPolicy",
25 | "lambda:GetPolicy",
26 | "lambda:ListFunctions",
27 | "lambda:ListLayerVersions",
28 | "sqs:ListQueues",
29 | "sqs:ListDeadLetterSourceQueues",
30 | "sqs:ListQueueTags",
31 | "sqs:GetQueueUrl",
32 | "sqs:GetQueueAttributes",
33 | "states:DescribeStateMachineForExecution",
34 | "states:DescribeActivity",
35 | "states:DescribeStateMachine",
36 | "states:DescribeExecution",
37 | "states:ListExecutions",
38 | "states:GetExecutionHistory"
39 | ],
40 | "Resource": "*"
41 | }
42 | ]
43 | }'
44 | #supplied by rapid7
45 | #=====================================
46 | $rolejson = '{
47 | "Version": "2012-10-17",
48 | "Statement": [
49 | {
50 | "Sid": "",
51 | "Effect": "Allow",
52 | "Principal": {
53 | "AWS": "arn:aws:iam::012345678910:root"
54 | },
55 | "Action": "sts:AssumeRole",
56 | "Condition": {
57 | "StringEquals": {
58 | "sts:ExternalId": "51f6f3c1-bd77-aaaa-aaaa-88884f42cccc"
59 | }
60 | }
61 | }
62 | ]
63 | }'
64 | #======================================
65 |
66 | $orgs = Get-ORGAccountList
67 |
68 | $orgs |%{
69 |
70 | $creds = Switch-AWSRoles -OrganizationID $_.id -Role $STSRole
71 | New-IAMAuditor -PolicyDocument $policyjson -RoleDocument $rolejson -Credentials $creds
72 |
73 | }
74 |
75 |
76 |
--------------------------------------------------------------------------------
/IAM/New-IAMAuditor.ps1:
--------------------------------------------------------------------------------
1 | Function New-IAMAuditor {
2 | [cmdletbinding()]
3 | param(
4 | [string]$PolicyName = 'Rapid7-Security-Audit',
5 | [parameter(Mandatory=$true)][string]$PolicyDocument,
6 | [string]$RoleName = $PolicyName,
7 | [parameter(Mandatory=$true)][string]$RoleDocument,
8 | [object]$Credentials
9 |
10 |
11 | )
12 | #$PolicyName
13 |
14 | try{$NewiamPol = New-IAMPolicy -PolicyName $PolicyName -PolicyDocument $PolicyDocument -Credential $Credentials}
15 | catch{
16 | if ($error[0].Exception -like "*Duplicate*"){
17 | $OrganizationID = (Get-STSCallerIdentity -Credential $creds).account
18 | $policyarn = "arn:aws:iam::${OrganizationID}:policy/$PolicyName"
19 | $newiampol = Get-IAMPolicy -PolicyArn $policyarn -Credential $Credentials
20 |
21 | }
22 |
23 | }
24 | $NewIAMRole = New-IAMRole -RoleName $RoleName -AssumeRolePolicyDocument $RoleDocument -Credential $Credentials
25 |
26 | Register-IAMRolePolicy -PolicyArn $NewiamPol.Arn -RoleName $RoleName -Credential $Credentials
27 |
28 | Register-IAMRolePolicy -PolicyArn 'arn:aws:iam::aws:policy/SecurityAudit' -RoleName $RoleName -Credential $Credentials
29 |
30 | $NewIAMRole.Arn
31 | }
--------------------------------------------------------------------------------
/IAM/New-MFADevice.ps1:
--------------------------------------------------------------------------------
1 | function New-MFADevice {
2 | param(
3 |
4 | [parameter(Mandatory=$true)][string]$DeviceName,
5 | $OpenInChrome,
6 | [Switch]$Credential,
7 | [string]$CSVImport,
8 | [Switch]$FindKeys
9 |
10 | )
11 |
12 | $Device = New-IAMVirtualMFADevice -VirtualMFADeviceName $devicename -Credential $creds
13 | $BR = New-Object System.IO.BinaryReader($Device.QRCodePNG)
14 | $BR.ReadBytes($BR.BaseStream.Length) | Set-Content -Encoding Byte -Path "c:\reports\QRCode.png"
15 |
16 |
17 | }
--------------------------------------------------------------------------------
/IAM/Remove-IAMAccessKeyAllOrgs.ps1:
--------------------------------------------------------------------------------
1 | $daysold = 45
2 | $lastusedDays = 90
3 | $role = 'cross-account-access-role'
4 | $iamkeys = Get-IAMAccessKeysAllOrgs -Role $role
5 |
6 | $oldiamkeys = $iamkeys|Where-Object -Property keycreatedate -lt ((get-date).AddDays(-$daysold))|Where-Object -Property lastused -lt ((get-date).AddDays(-$lastusedDays))
7 | $oldiamkeys |%{
8 |
9 | $creds = Get-STSCreds -OrganizationID $_.OrganizationID -Role $role
10 | $keyid = $_.accesskeyid
11 | Get-IAMUserList -Credential $creds|%{get-iamaccesskey -UserName $_.username -Credential $creds|where-object -Property accesskeyid -eq $keyid|Remove-IAMAccessKey -AccessKeyId $keyid -Credential $creds}
12 |
13 | }
--------------------------------------------------------------------------------
/IAM/Update-PasswordPolicyAllOrgs.ps1:
--------------------------------------------------------------------------------
1 | Function Update-IAMAccountPasswordPolicyOrgs{
2 | [CmdletBinding()]
3 |
4 | param
5 | (
6 | [string]$Role,
7 | [object]$OrganizationList,
8 | [bool]$AllowUsersToChangePassword = $True,
9 | [bool]$ExpirePasswords = $True,
10 | [bool]$HardExpiry = $False,
11 | [int]$MaxPasswordAge = 90,
12 | [int]$MinimumPasswordLength = 15,
13 | [int]$PasswordReusePrevention = 5,
14 | [bool]$RequireLowercaseCharacters = $True,
15 | [bool]$RequireNumbers =$True,
16 | [bool]$RequireSymbols =$True,
17 | [bool]$RequireUppercaseCharacters = $True
18 | )
19 |
20 | # set password policy from a list of orgs
21 | if (!$OrganizationList){try{$organizationlist = Get-ORGAccountList}catch{}}
22 | if (!$Role){
23 | $a = (get-stscalleridentity).account
24 | Write-host "No Role Specified. Setting PWD Policy only on account $a"
25 | Update-IAMAccountPasswordPolicy -AllowUsersToChangePassword $AllowUsersToChangePassword -MaxPasswordAge $MaxPasswordAge -MinimumPasswordLength $MinimumPasswordLength -PasswordReusePrevention $PasswordReusePrevention -RequireLowercaseCharacter $RequireLowercaseCharacters -RequireNumber $RequireNumbers -RequireSymbol $RequireSymbols -RequireUppercaseCharacters $RequireUppercaseCharacters -hardexpiry $false
26 | Get-IAMAccountPasswordPolicy
27 | break
28 | }
29 | if (!$OrganizationList){
30 | $a = (get-stscalleridentity).account
31 | Write-host "No Organization Account List Found. Setting PWD Policy only on account $a"
32 | Update-IAMAccountPasswordPolicy -AllowUsersToChangePassword $AllowUsersToChangePassword -MaxPasswordAge $MaxPasswordAge -MinimumPasswordLength $MinimumPasswordLength -PasswordReusePrevention $PasswordReusePrevention -RequireLowercaseCharacter $RequireLowercaseCharacters -RequireNumber $RequireNumbers -RequireSymbol $RequireSymbols -RequireUppercaseCharacters $RequireUppercaseCharacters -hardexpiry $false
33 | Get-IAMAccountPasswordPolicy
34 | break
35 | }
36 |
37 | foreach($org in $organizationlist){
38 | $credential = get-stscreds -OrganizationID $org.id -Role $Role
39 | $name = $org.name
40 | write-host "On $name"
41 | Update-IAMAccountPasswordPolicy -Credential $credential -AllowUsersToChangePassword $AllowUsersToChangePassword -MaxPasswordAge $MaxPasswordAge -MinimumPasswordLength $MinimumPasswordLength -PasswordReusePrevention $PasswordReusePrevention -RequireLowercaseCharacter $RequireLowercaseCharacters -RequireNumber $RequireNumbers -RequireSymbol $RequireSymbols -RequireUppercaseCharacters $RequireUppercaseCharacters -hardexpiry $false
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/IAM/security_assessment_access.template:
--------------------------------------------------------------------------------
1 | AWSTemplateFormatVersion: '2010-09-09'
2 | Description: 'Provides Summit Route with the ability to perform a security assessment on this account. An IAM role is created to provide view-only access of the metadata in the account.'
3 | Resources:
4 | CFNSummitRouteRole:
5 | Type: AWS::IAM::Role
6 | Properties:
7 | AssumeRolePolicyDocument:
8 | Version: '2012-10-17'
9 | Statement:
10 | - Effect: Allow
11 | Principal:
12 | AWS: arn:aws:iam::393727464233:root
13 | Action: 'sts:AssumeRole'
14 | Condition:
15 | Bool:
16 | 'aws:MultiFactorAuthPresent': true
17 | ManagedPolicyArns:
18 | - 'arn:aws:iam::aws:policy/SecurityAudit'
19 | - 'arn:aws:iam::aws:policy/job-function/ViewOnlyAccess'
20 | RoleName: SummitRouteAudit
21 | Policies:
22 | - PolicyName: SummitRouteAdditionalViewPrivileges
23 | PolicyDocument:
24 | Version : '2012-10-17'
25 | Statement:
26 | - Effect: Allow
27 | Action:
28 | - 'acm:DescribeCertificate'
29 | - 'eks:DescribeCluster'
30 | - 'eks:ListClusters'
31 | - 'elasticfilesystem:DescribeMountTargetSecurityGroups'
32 | - 'elasticfilesystem:DescribeMountTargets'
33 | - 'elasticmapreduce:DescribeCluster'
34 | - 'elasticmapreduce:DescribeSecurityConfiguration'
35 | - 'events:DescribeRule'
36 | - 'fms:ListComplianceStatus'
37 | - 'fms:ListPolicies'
38 | - 'guardduty:ListDetectors'
39 | - 'guardduty:ListFindings'
40 | - 'guardduty:ListIPSets'
41 | - 'guardduty:ListInvitations'
42 | - 'guardduty:ListMembers'
43 | - 'guardduty:ListThreatIntelSets'
44 | - 'iam:GenerateServiceLastAccessedDetails'
45 | - 'inspector:DescribeAssessmentRuns'
46 | - 'inspector:DescribeAssessmentTargets'
47 | - 'inspector:DescribeAssessmentTemplates'
48 | - 'inspector:DescribeCrossAccountAccessRole'
49 | - 'inspector:DescribeFindings'
50 | - 'inspector:DescribeResourceGroups'
51 | - 'inspector:DescribeRulesPackages'
52 | - 'iot:DescribeAuthorizer'
53 | - 'iot:DescribeCACertificate'
54 | - 'iot:DescribeCertificate'
55 | - 'iot:DescribeDefaultAuthorizer'
56 | - 'iot:GetPolicy'
57 | - 'iot:GetPolicyVersion'
58 | - 'lambda:GetFunctionConfiguration'
59 | - 'lightsail:GetInstances'
60 | - 'lightsail:GetLoadBalancers'
61 | - 'opsworks:DescribeStacks'
62 | - 'organizations:Describe*'
63 | - 'organizations:List*'
64 | - 'shield:DescribeAttack'
65 | - 'shield:DescribeProtection'
66 | - 'shield:DescribeSubscription'
67 | - 'sso:DescribePermissionsPolicies'
68 | - 'sso:ListApplicationInstanceCertificates'
69 | - 'sso:ListApplicationInstances'
70 | - 'sso:ListApplicationTemplates'
71 | - 'sso:ListApplications'
72 | - 'sso:ListDirectoryAssociations'
73 | - 'sso:ListPermissionSets'
74 | - 'sso:ListProfileAssociations'
75 | - 'sso:ListProfiles'
76 | Resource: '*'
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Organizations/Get-AllOrgOus.ps1:
--------------------------------------------------------------------------------
1 | Function Get-OrgOUList{
2 | [Alias("Get-IAMOrgOUList")]
3 | <#
4 | .SYNOPSIS
5 | Displays a formatted table of AWS Organization OUs on the console
6 |
7 | .DESCRIPTION
8 | Starting at the root OU, this function displays a formatted list of OUs in an AWS Organization. The user MUST be a user with admin access to the Organization's root account and this function MUST be run in that root account
9 |
10 | .PARAMETER AWSStoredProfile
11 | A stored profile containing the AWS credentials providing admin access to the AWS Organization's master account
12 |
13 | .PARAMETER CSV
14 | This parameter allows you to send the output of the function in CSV format to a file in your home directory. Specify $true; defaults to $false
15 |
16 | .EXAMPLE
17 | PS C:\> ./AddNewOrgAccounToMFSMaster.ps1 -AWSStoredProfile # Displays OUs as table on console
18 | PS C:\> ./AddNewOrgAccounToMFSMaster.ps1 -AWSStoredProfile | Out-File # Writes text to file
19 | PS C:\> ./AddNewOrgAccounToMFSMaster.ps1 -AWSStoredProfile -CSV $true
20 |
21 |
22 | .NOTES
23 | Updates 9/12/2019 - DRowe - Updated output to remove format-table. Allows script to be exported into variable with ease
24 | 9/19/2019 - Added root ou to output
25 |
26 |
27 | Alex Neihaus 2019-07-15
28 | (c) 2019 Air11 Technology LLC -- licensed under the Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0
29 | Licensed under the Apache License, Version 2.0 (the "License");
30 | you may not use this file except in compliance with the License.
31 | You may obtain a copy of the License at
32 | http://www.apache.org/licenses/LICENSE-2.0
33 |
34 | Unless required by applicable law or agreed to in writing, software
35 | distributed under the License is distributed on an "AS IS" BASIS,
36 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37 | See the License for the specific language governing permissions and
38 | limitations under the License.
39 |
40 | Author's blog: https://www.yobyot.com
41 |
42 |
43 | #>
44 | [CmdletBinding()]
45 |
46 | param
47 | (
48 | [Parameter(Mandatory = $false,
49 | Position = 1,
50 | HelpMessage = 'Supply a stored AWS credential profile authorized in the master account to create new accounts')]
51 | [Alias('creds')]
52 | [System.String]$AWSStoredProfile,
53 | [Parameter(Position = 2,
54 | HelpMessage = 'Enter TRUE to pipe output to a file in .csv format')]
55 | [ValidateSet($true, $false, IgnoreCase = $true)]
56 | [boolean]$CSV = $false,
57 | [Parameter(Mandatory = $false,
58 | Position = 2,
59 | HelpMessage = 'Use if you want to list accounts instead of OUs')]
60 | [switch]$ListAccounts
61 | )
62 | <# This function recursively lists all OUs starting from the root and places the ARN, ID and name
63 | of the OU into an array to be presented to the user as a formatted table
64 | #>
65 | function Get-OrgChildOUs {
66 | param(
67 | [Parameter(Mandatory = $false,
68 | Position = 1)]
69 | [System.String]$ParentOUId,
70 | [Parameter(Mandatory = $false,
71 | Position = 2)]
72 | [System.String]$ParentName,
73 | [System.String]$ChildType = 'ORGANIZATIONAL_UNIT'
74 | )
75 |
76 |
77 | $childouids = Get-ORGChild -ParentId $ParentOUId -ChildType $ChildType
78 | foreach ($childouid in $childouids.Id) {
79 | $obj = New-Object -TypeName PSObject -Property @{
80 | "Arn" = "";
81 | "Id" = "";
82 | "Name" = "";
83 | "Parent" = "";
84 | }
85 | $t = Get-ORGOrganizationalUnit -OrganizationalUnitId $childouid
86 | # If we assign output of Get-ORGOrganizationUnit to a variable, it becomes type Amazon.Organizations.Model.OrganizationalUnit which we cannot modify
87 | # So, we manually copy the properties into our object, which is then added to the array of all OUs
88 | $obj.Arn = $t.Arn
89 | $obj.Id = $t.Id
90 | $obj.Name = $t.Name
91 | $obj.Parent = $ParentName
92 | $Script:AllOUs += $obj
93 | Start-Sleep -Seconds .6 # For some reason, AWS cmdlet Get-OrgOrganizationalUnit fails if lots of IDs are passed via pipeline, so this foreach loop slows it down
94 | # Using the current OU id, see if there are any child OUs and recursively call this function.
95 | do {
96 | if(!$PSBoundParameters.ContainsKey('ListAccounts')){Get-OrgChildOUs -ParentOUId $obj.Id -ParentName $obj.Name}
97 | else{Get-OrgChildOUs -ParentOUId $obj.Id -ParentName $obj.Name -ChildType ACCOUNT}
98 |
99 | }
100 | until ($null -eq $($AWSHistory.LastServiceResponse.Children)) # $AWSHistory contains $null when there are no more child OUs
101 |
102 | }
103 | }
104 | function Get-AllOrgOus {
105 | Begin {
106 | switch ($PSVersionTable.PSEdition) {
107 | # Find out which version of pwsh is running and load the proper AWS cmdlet module
108 | "Core" {
109 | Import-Module AWSPowerShell.NetCore
110 | }
111 | "Desktop" {
112 | Import-Module AWSPowerShell
113 | }
114 | default {
115 | "There's a big problem; this version of PowerShell is unknown"
116 | "Returned edition of PowerShell is: $PSVersionTable.PSEdition"
117 | exit
118 | }
119 | }
120 | $error.clear() # Reset the error variable
121 | # On macOS using the VSCode debugger as of 2019-07-19, a simple Set-AWSCredential causes an error
122 | # If so, Initialize-AWSDefaultConfiguration works. See https://github.com/PowerShell/vscode-powershell/issues/2050
123 | switch (Test-Path Variable:PSDebugContext -IsValid) {
124 | $true {
125 | if ($PSBoundParameters.ContainsKey('AWSStoredProfile')){Initialize-AWSDefaultConfiguration -ProfileName $AWSStoredProfile}
126 | else{}
127 | }
128 | $false {
129 | if ($PSBoundParameters.ContainsKey('AWSStoredProfile')){
130 | Set-AWSCredential -ProfileName $AWSStoredProfile -ErrorAction SilentlyContinue # Set the profile to be used
131 | if ($null -ne $error[0]) {
132 | # Profile was NOT set correctly; Set-AWSCredentals does NOT store errors in $AWSHistory variable, so check $error array varaiable
133 | "Your AWS stored profile was incorrect in some way"
134 | "Set-AWSCredential returned: $error[0].Exception"
135 | exit
136 | }
137 | }
138 |
139 | }
140 | }
141 | }
142 | Process {
143 | # Start by getting the OUs off the root.
144 | $Script:AllOUs = @()
145 | $objarray = @()
146 | $r = get-orgroot
147 | $RootOUId = $r.Id # Get the four-character root OU ID
148 | $obj = new-object psobject
149 |
150 | $obj |Add-member NoteProperty Parent "TOP"
151 | $obj |Add-member NoteProperty OUName $r.name
152 | $obj |Add-member NoteProperty Id $RootOUId
153 | $obj |Add-member NoteProperty Arn $r.Arn
154 | $objarray += $obj
155 | Get-OrgChildOUs -ParentOUId $RootOUId -ParentName "Root" # Get the OU IDs at level one below the root
156 | }
157 | End {
158 |
159 | foreach ($id in $Script:AllOUs.id) {
160 | $obj = new-object psobject
161 |
162 | $obj |Add-member NoteProperty Parent $($Script:AllOUs.Parent[($Script:AllOUs.id).IndexOf($id)])
163 | $obj |Add-member NoteProperty OUName $($Script:AllOUs.Name[($Script:AllOUs.id).IndexOf($id)])
164 | $obj |Add-member NoteProperty Id $($Script:AllOUs.Id[($Script:AllOUs.id).IndexOf($id)])
165 | $obj |Add-member NoteProperty Arn $($Script:AllOUs.Arn[($Script:AllOUs.id).IndexOf($id)])
166 | <#"OUName" = "$($Script:AllOUs.Name[($Script:AllOUs.id).IndexOf($id)])";
167 | "OUId" = "$($Script:AllOUs.Id[($Script:AllOUs.id).IndexOf($id)])";
168 | "Parent" = "$($Script:AllOUs.Parent[($Script:AllOUs.id).IndexOf($id)])";
169 | "Arn" = "$($Script:AllOUs.Arn[($Script:AllOUs.id).IndexOf($id)])";#>
170 |
171 | $objarray += $obj
172 | }
173 | switch ($CSV) {
174 | $false {
175 | # Write-Host -ForegroundColor Yellow "Displaying all OUs in this AWS Organization"
176 | $objarray | Sort-Object -Property "OUName" #| Format-Table Parent, OUName, OUId, Arn -AutoSize
177 | }
178 | $true {
179 | $csvfile = "$HOME/AWSOUs-$(Get-Date -Format "yyyy-mm-dd-THH-MM-ss").csv"
180 | Write-Host -ForegroundColor Yellow "Writing a CSV file to $csvfile with all OUs in this AWS Organization"
181 | $objarray | Sort-Object -Property "OUName" | Export-Csv -Path $csvfile
182 | }
183 | }
184 |
185 | }
186 | }
187 | Get-AllOrgOus
188 | }
189 |
190 | Function Get-OrgAccountLocation{
191 |
192 | <#
193 | .SYNOPSIS
194 | Displays a formatted table of AWS Organization SCPs applied to OUs
195 |
196 | .DESCRIPTION
197 | Pulls SCP information from the Ous provided and generates output of all attached scps to OUs. The user MUST be a user with admin access to the Organization's root account and this function MUST be run in that root account
198 |
199 | .PARAMETER OrgList
200 | A parameter containing the AWS OUs. Currently only set to work from the output of get-allorgous.ps1
201 |
202 | .EXAMPLE
203 | Get-OrgPolicyInformation -OrgList $OUs #WHere OUs is $ous = Get-OrgOUList
204 | Get-OrgPolicyInformation -OrgList (Get-OrgOUList)
205 |
206 | .NOTES
207 | v1 - Created script and output data - Generates SCP attached to OUs. Made to work with the input from Get-AllOrgOus.ps1
208 |
209 |
210 | David Rowe 2019-09-19
211 | (c) 2019 SecFrame - licensed under the Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0
212 | Licensed under the Apache License, Version 2.0 (the "License");
213 | you may not use this file except in compliance with the License.
214 | You may obtain a copy of the License at
215 | http://www.apache.org/licenses/LICENSE-2.0
216 |
217 | Unless required by applicable law or agreed to in writing, software
218 | distributed under the License is distributed on an "AS IS" BASIS,
219 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
220 | See the License for the specific language governing permissions and
221 | limitations under the License.
222 |
223 | Author's blog: https://www.secframe.com
224 |
225 |
226 | #>
227 | [CmdletBinding()]
228 |
229 | param
230 | (
231 | [Parameter(Mandatory = $false,
232 | Position = 1,
233 | HelpMessage = 'A parameter containing the AWS OUs. Currently only set to work from the output of get-allorgous.ps1')]
234 | [object]$OrgList
235 | )
236 | $Accts = @()
237 | $orglist |%{
238 | $o = $_
239 | $ChildAccounts = Get-ORGChild -ParentId $_.OUID -ChildType Account
240 | $childaccounts |%{
241 | $acct = get-orgaccount -accountid $_.id
242 |
243 | $obj = new-object psobject
244 | #$obj |Add-member NoteProperty OUParent $o.Parent
245 | $obj |Add-member NoteProperty OUName $o.OUName
246 | $obj |Add-member NoteProperty OUID $o.OUID
247 | $obj |Add-member Noteproperty OUArn $o.arn
248 | $obj |Add-member NoteProperty AccountID $acct.Id
249 | $obj |Add-member NoteProperty AccountName $acct.name
250 | $obj |Add-member NoteProperty AccountArn $acct.arn
251 | $obj |Add-member NoteProperty AccountStatus $acct.status
252 | $accts += $obj
253 | Start-Sleep -Seconds .6
254 | }
255 | }
256 | $Accts
257 |
258 | }
--------------------------------------------------------------------------------
/Organizations/Get-OrgPolicyInformation.ps1:
--------------------------------------------------------------------------------
1 | Function Get-OrgPolicyInformation{
2 |
3 | <#
4 | .SYNOPSIS
5 | Displays a formatted table of AWS Organization SCPs applied to OUs
6 |
7 | .DESCRIPTION
8 | Pulls SCP information from the Ous provided and generates output of all attached scps to OUs. The user MUST be a user with admin access to the Organization's root account and this function MUST be run in that root account
9 |
10 | .PARAMETER OrgList
11 | A parameter containing the AWS OUs. Currently only set to work from the output of get-allorgous.ps1
12 |
13 | .EXAMPLE
14 | Get-OrgPolicyInformation -OrgList $OUs #WHere OUs is $ous = Get-OrgOUList
15 | Get-OrgPolicyInformation -OrgList (Get-OrgOUList)
16 |
17 | .NOTES
18 | v1 - Created script and output data - Generates SCP attached to OUs. Made to work with the input from Get-AllOrgOus.ps1
19 |
20 |
21 | David Rowe 2019-09-19
22 | (c) 2019 SecFrame - licensed under the Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0
23 | Licensed under the Apache License, Version 2.0 (the "License");
24 | you may not use this file except in compliance with the License.
25 | You may obtain a copy of the License at
26 | http://www.apache.org/licenses/LICENSE-2.0
27 |
28 | Unless required by applicable law or agreed to in writing, software
29 | distributed under the License is distributed on an "AS IS" BASIS,
30 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
31 | See the License for the specific language governing permissions and
32 | limitations under the License.
33 |
34 | Author's blog: https://www.secframe.com
35 |
36 |
37 | #>
38 | [CmdletBinding()]
39 |
40 | param
41 | (
42 | [Parameter(Mandatory = $false,
43 | Position = 1,
44 | HelpMessage = 'A parameter containing the AWS OUs. Currently only set to work from the output of get-allorgous.ps1')]
45 | [object]$OrgList,
46 | [validateset('OUId','AccountID')][string]$TargetID
47 | )
48 | $objarray = @()
49 | $OrgList | %{
50 | $ou = $_
51 | if (!$targetid){$targetid = 'OUId'}
52 | $targetid
53 | $policyfortarget = Get-ORGPolicyForTarget -TargetId $ou.$TargetID -Filter SERVICE_CONTROL_POLICY
54 | $policyfortarget |%{
55 | $pol = Get-ORGPolicy -PolicyId $_.Id
56 | $obj = new-object psobject
57 | $json = ($pol.content |ConvertFrom-Json).statement
58 |
59 | $obj |Add-member NoteProperty PolicyName $pol.PolicySummary.name
60 | $obj |Add-member NoteProperty PolicyID $pol.PolicySummary.id
61 | $obj |Add-member NoteProperty PolicyDesc $pol.PolicySummary.Description
62 | $obj |Add-member NoteProperty Parent $ou.Parent
63 | if ($targetid -eq 'OUID'){
64 | $obj |Add-member NoteProperty AttachedToName $ou.OUName
65 | $obj |Add-member NoteProperty AttachedToId $ou.ouId
66 | $obj |Add-member NoteProperty AttachedToArn $ou.Arn
67 | $obj |Add-member Noteproperty AttachedToType 'OU'
68 |
69 | }
70 | if ($targetid -eq 'AccountID'){
71 | $obj |Add-member NoteProperty AttachedToName $ou.AccountName
72 | $obj |Add-member NoteProperty AttachedToId $ou.AccountID
73 | $obj |Add-member NoteProperty AttachedToArn $ou.AccountArn
74 | $obj |Add-member Noteproperty AttachedToType 'Account'
75 |
76 | }
77 | $obj |Add-member NoteProperty Content $json
78 | $obj |Add-member NoteProperty PolicySummary $pol.PolicySummary
79 |
80 | $objarray += $obj
81 | Start-Sleep .6
82 | }
83 |
84 |
85 | }
86 |
87 | $objarray
88 | }
89 |
90 | Function Convert-RoleToJson {
91 | [CmdletBinding()]
92 |
93 | param
94 | (
95 | [Parameter(Mandatory = $false,
96 | Position = 1,
97 | HelpMessage = 'A parameter containing the PolList. Currently only set to work from the output of Get-OrgPolicyInformation')]
98 | [object]$PolList,
99 | [string]$DestFolder
100 | )
101 | $uniquePols = $PolList|select policyname, content -unique
102 | $poljson = @()
103 | $uniquePols |%{
104 | $obj = new-object psobject
105 | $obj |add-member NoteProperty Name $_.policyname
106 | $obj |Add-member NoteProperty Content ($_.content|convertto-json)
107 | $poljson += $obj
108 | }
109 | $poljson
110 | if($DestFolder){
111 | $poljson |%{
112 |
113 | $n = $_.name
114 | $filename = ($DestFolder +'\' + $_.name + ".json")
115 | $_.content |Out-File $filename
116 | write-host "File saved for $n at $filename"
117 | }
118 |
119 | }
120 | }
121 |
122 |
123 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AWS_PowerTools
2 | AWS Powershell scripts to make management of AWS accounts easier
3 |
--------------------------------------------------------------------------------
/S3/FlawsS3Buckets.ps1:
--------------------------------------------------------------------------------
1 | 2017-02-18 14:41:52 2f4e53154c0a7fd086a04a12a452c2a4caed8da0.flaws.cloud
2 | 2017-05-29 12:34:53 config-bucket-975426262029
3 | 2018-07-07 12:09:49 flaws-logs
4 | 2017-02-18 14:40:54 flaws.cloud
5 | 2017-02-24 00:15:42 level2-c8b217a33fcf1f839f6f1f73a00a9ae7.flaws.cloud
6 | 2017-02-26 13:29:03 level3-9afd3927f195e10225021a578e6f78df.flaws.cloud
7 | 2017-02-26 13:49:31 level4-1156739cfb264ced6de514971a4bef68.flaws.cloud
8 | 2017-02-26 14:49:03 level5-d2891f604d2061b6977c2481b0c8333e.flaws.cloud
9 | 2017-02-26 14:48:40 level6-cc4c404a8a8b876167f5e70a7d8c9880.flaws.cloud
10 | 2017-02-26 15:07:13 theend-797237e8ada164bf9f12cebf93b282cf.flaws.cloud
--------------------------------------------------------------------------------
/S3/Get-AWSCanonicalUserID.ps1:
--------------------------------------------------------------------------------
1 | function Get-AWSCanonicalUserID {
2 | [CmdletBinding()]
3 |
4 | $buckets = get-s3bucket
5 | $region = 'us-east-1'
6 | $objects = $buckets| %{Get-S3Object -BucketName $_.bucketName -region $region -MaxKey 10}
7 | ($objects |select-object -property owner -unique).owner.id
8 | }
9 |
10 | Function Get-AWSCanonicalUserIDOrgs {
11 | [CmdletBinding()]
12 | param (
13 | #[Parameter(Mandatory=$true)][object]$OrgList,
14 | [Parameter(Mandatory=$true)][string]$Role
15 |
16 | )
17 | $CanIDList = @()
18 | get-orgaccountlist -ProfileName default |%{
19 | Set-AWSCredential -ProfileName Default
20 | try {$creds = Get-STSCreds -OrganizationID $_.id -role $Role
21 | Set-AWSCredential -Credential $creds -storeas TempProfile
22 | set-awscredential -ProfileName tempprofile
23 | }
24 | catch{}
25 | $CanID = Get-AWSCanonicalUserID
26 | $obj = new-object psobject
27 | $obj |add-member NoteProperty OrgID $_.id
28 | $Obj | Add-member NoteProperty OrgName $_.name
29 | $Obj | Add-member NoteProperty CanonicalID $CanID
30 | $canidlist += $obj
31 | }
32 | $CanIDList
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/S3/Get-AccessKeysInMetadata.ps1:
--------------------------------------------------------------------------------
1 | Function Get-AccessKeysInMetadata{
2 | param(
3 | [parameter(Mandatory=$true)][string]$BucketName
4 |
5 | )
6 | #$bucketname = "4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud"
7 | $magic = "/proxy/169.254.169.254/latest/meta-data/"
8 | $AccessKeyRegEx = "(^|[^A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9])"
9 | $SecretKeyRegEx = "(^|[^A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=])"
10 | $url = "HTTP://" + $BucketName + $magic
11 |
12 | $webpage = Invoke-WebRequest $url -UseBasicParsing
13 |
14 | if($webpage){
15 | $content = $webpage.Content.Split([environment]::NewLine)
16 | $content |% {
17 | $url2 = ($url + $_)
18 | $url2
19 | $webpage2 = Invoke-WebRequest $url2 -UseBasicParsing
20 | $content2 = $webpage2.Content.Split([environment]::NewLine)
21 |
22 | $content2 |% {
23 | $url3 = ($url2 + $_)
24 | $url3
25 | try{$webpage3 = Invoke-WebRequest $url3 -UseBasicParsing
26 | $content3 = $webpage2.Content.Split([environment]::NewLine)
27 |
28 | }
29 | catch {
30 | $content2
31 | }
32 | }
33 | }
34 |
35 | }
36 |
37 |
38 |
39 |
40 | }
--------------------------------------------------------------------------------
/S3/Get-AccessKeysInS3.ps1:
--------------------------------------------------------------------------------
1 | Function Get-AccessKeysInS3 {
2 | param(
3 |
4 | #[parameter(Mandatory=$true)][string]$BucketName,
5 | [parameter(Mandatory=$true)][string]$GitFolder
6 |
7 | )
8 |
9 |
10 |
11 | if (-not (test-path -literalpath $GitFolder) ){
12 |
13 | write-warning -Message "$GitFolder Does not exist. Exiting Script"
14 | break
15 | }
16 |
17 | Import-Module posh-git
18 | cd $GitFolder
19 | #get to git master branch to list all commits
20 | if ((git branch) -ne '* master') {
21 |
22 | git checkout master
23 | }
24 |
25 | $gitHist = (git log --format="%ai`t%H`t%an`t%ae`t%s" -n 100) | ConvertFrom-Csv -Delimiter "`t" -Header ("Date","CommitId","Author","Email","Subject")
26 | $showall = @()
27 |
28 | $gitHist|% {
29 | $showall += git show $_.commitid
30 | }
31 |
32 | $AccessKeyRegEx = "(^|[^A-Z0-9])[A-Z0-9]{20}(?![A-Z0-9])"
33 | $SecretKeyRegEx = "(^|[^A-Za-z0-9/+=])[A-Za-z0-9/+=]{40}(?![A-Za-z0-9/+=])"
34 |
35 | $accesskeys = $showall|Select-String -Pattern $AccessKeyRegEx
36 | $secretkeys = $showall|Select-String -Pattern $SecretKeyRegEx|where-object {($_ -notlike "commit*")}|where-object {($_ -notlike "+git checkout*")}
37 |
38 |
39 | $secretslist = @()
40 | $i=0
41 | $accesskeys |% {
42 | $Key = $_ # -split ""|Select-String -Pattern $AccessKeyRegEx
43 |
44 | $obj = new-object psobject
45 | $obj |Add-member NoteProperty AccessKeyMatch $_
46 | $obj |Add-member NoteProperty SecretKeyMatch ""
47 | $githist | %{ if(git show $_.commitid|Select-String -simplematch -Pattern $key){
48 | $obj |Add-member Noteproperty CommitID $_.commitid}
49 | else{}
50 | }
51 |
52 | $secretslist += $obj
53 | $i++
54 | }
55 |
56 | $secretkeys |% {
57 | $key = $_
58 | $obj = new-object psobject
59 | $obj |Add-member NoteProperty AccessKeyMatch ""
60 | $obj |Add-member NoteProperty SecretKeyMatch $_
61 | $githist | %{ if(git show $_.commitid|Select-String -simplematch -Pattern $key){
62 | $obj |Add-member Noteproperty CommitID $_.commitid}
63 | else{} }
64 |
65 | $secretslist += $obj
66 | }
67 | #$secretslist
68 |
69 | $formattedSecrets = @()
70 | $accesskeys | %{
71 | $ak = [regex]::match($_,$AccessKeyRegEx).value
72 | $ak = $Ak -replace '[\W]',''
73 | $secretkeys |%{
74 | $sk = [regex]::match($_,$SecretKeyRegEx).value
75 | $sk = $sk -replace ' ',''
76 | $sk = $sk -replace '`',''
77 | $obj = new-object psobject
78 | $obj |Add-Member NoteProperty AccessKey $ak
79 | $obj |Add-member NoteProperty Secret $sk
80 | $formattedSecrets += $obj
81 | }
82 |
83 | }
84 | remove-Module posh-git
85 | $secretsunique = $formattedSecrets |sort-object accesskey,secret |Get-Unique -AsString
86 | $secretsunique | % {
87 | Switch-AccessWithAWSKey -AccessKey $_.accesskey -SecretKey $_.secret -Profile GITTest
88 | $temp = $_
89 | try {Get-STSCallerIdentity -ProfileName GITTest|Out-Null
90 | }
91 | catch {$secretsunique = $secretsunique -ne $temp
92 | }
93 |
94 |
95 | }
96 |
97 |
98 |
99 | $secretsunique
100 | }
--------------------------------------------------------------------------------
/S3/Get-S3AllObjectMetadata.ps1:
--------------------------------------------------------------------------------
1 | $buckets = get-s3bucket
2 | $region = 'us-east-1'
3 | $objects = $buckets| %{Get-S3Object -BucketName $_.bucketName -region $region|%{get-s3objectmetadata -bucketName $_.bucketName -key $_.key -Region $region }}
--------------------------------------------------------------------------------
/S3/Get-S3BucketRegion.ps1:
--------------------------------------------------------------------------------
1 |
2 | Function Get-S3BucketRegion {
3 | [cmdletbinding()]
4 | param(
5 | [string]$BucketName,
6 | [object]$Regions, #Supply region list you want to test against
7 | [object]$Credential # use for organization testing for all buckets and regions
8 | )
9 | #standardize bucketname string to an object
10 | if (!$BucketName -and !$Credential){
11 | $S3 = get-s3bucket
12 | }
13 | if (!$BucketName -and $Credential){
14 | $s3 = get-s3bucket -credential $credential
15 | }
16 | if ($bucketname -and !$Credential){$S3 = Get-S3Bucket |where-object {$_.bucketname -eq $bucketname}}
17 | if ($bucketname -and $Credential){$S3 = Get-S3Bucket -Credential $credential|where-object {$_.bucketname -eq $bucketname}}
18 | if (!$S3){
19 | write-warning "No Bucket found with name $bucketname. Aborting script"
20 | break
21 | }
22 |
23 |
24 | if(!$Regions){$Regions = Get-AWSRegion|Sort-Object name -Descending}
25 | $objarray = @()
26 |
27 |
28 |
29 | $S3|%{
30 |
31 | $bname = $_
32 |
33 | $Regions | %{
34 | if (!$region) {
35 | $r = $_
36 | try {
37 |
38 | if (!$credential) {$region = Get-s3bucketversioning -BucketName $bname.BucketName -Region $r.region}else{
39 | $region = Get-s3bucketversioning -BucketName $bname.BucketName -Region $r.region -Credential $credential
40 | #if ($region.status -ne 'Enabled'){write-error -message 'wrong region'}
41 | }
42 |
43 | try{
44 | if ($credential){get-s3publicaccessblock -BucketName $_.bucketname -credential $creds -Region $_.Region}else{
45 | $publicaccess = get-s3publicaccessblock -BucketName $_.bucketname -Region $_.Region
46 | }
47 | }catch{}
48 |
49 | $region = $r
50 | $obj = new-object psobject
51 |
52 | $obj |Add-member NoteProperty BucketName $bname.BucketName
53 | $obj |Add-member NoteProperty Region $r
54 | if($publicaccess){
55 | $obj |Add-member NoteProperty BlockPublicAcls $publicaccess.BlockPublicAcls
56 | $obj |Add-member NoteProperty IgnorePublicAcls $publicaccess.IgnorePublicAcls
57 | $obj |Add-member NoteProperty BlockPublicPolicy $publicaccess.BlockPublicPolicy
58 | $obj |Add-member NoteProperty RestrictPublicBuckets $publicaccess.RestrictPublicBuckets
59 | }else{
60 | $obj |Add-member NoteProperty BlockPublicAcls "No Configuration Found"
61 | $obj |Add-member NoteProperty IgnorePublicAcls "No Configuration Found"
62 | $obj |Add-member NoteProperty BlockPublicPolicy "No Configuration Found"
63 | $obj |Add-member NoteProperty RestrictPublicBuckets "No Configuration Found"
64 | }
65 | $objarray += $obj
66 | }Catch{
67 |
68 | }
69 | }
70 |
71 | }
72 | } #
73 | $objarray
74 |
75 | }
76 |
77 |
78 | Function Get-S3BucketRegionOrgs {
79 | [cmdletbinding()]
80 | param(
81 | [Parameter(Mandatory = $true,
82 | Position = 1,
83 | HelpMessage = 'Role used to authenticate and read into sub accounts')]
84 | [string]$Role
85 | )
86 | try {$orgs = Get-ORGAccountList }catch {break}
87 | $s3array = @()
88 | $callerID = (Get-STSCallerIdentity).account
89 | $orgcount = $orgs.count
90 | $orgprogress = 1
91 | $orgs |%{
92 | $org = $_
93 | Write-Progress -Activity "Searching Through Accounts in Organization" -id 1 -Status "$orgProgress complete of $orgcount" -PercentComplete ($orgProgress/$orgcount*100)
94 | if ($_.id -ne $callerID){
95 | $creds = get-stscreds -organizationid $_.id -role $role
96 | $s3 = get-s3bucketregion -Credential $creds}else{
97 | $s3 = get-s3bucketregion
98 | }
99 | $s3count = $s3.count
100 | $s3progress = 1
101 | $s3 |%{
102 | if($s3count -gt 0){Write-Progress -Activity "Searching Through S3 Buckets in Account" -id 2 -Status "$s3progress complete of $s3count" -PercentComplete ($s3progress/$s3count*100)}
103 | Clear-Variable -Name publicaccess
104 | if ($org.id -ne $callerid){
105 |
106 | try{$publicaccess = get-s3publicaccessblock -BucketName $_.bucketname -credential $creds -Region $_.Region}catch{}}Else{
107 | try{$publicaccess = get-s3publicaccessblock -BucketName $_.bucketname -Region $_.Region}catch{}
108 | }
109 |
110 | $obj = new-object psobject
111 | $obj |Add-member NoteProperty AccountID $org.Id
112 | $obj |Add-member Noteproperty AccountName $org.Name
113 | $obj |Add-member NoteProperty BucketName $_.BucketName
114 | $obj |Add-member NoteProperty Region $_.Region
115 | if($publicaccess){
116 | $obj |Add-member NoteProperty BlockPublicAcls $publicaccess.BlockPublicAcls
117 | $obj |Add-member NoteProperty IgnorePublicAcls $publicaccess.IgnorePublicAcls
118 | $obj |Add-member NoteProperty BlockPublicPolicy $publicaccess.BlockPublicPolicy
119 | $obj |Add-member NoteProperty RestrictPublicBuckets $publicaccess.RestrictPublicBuckets
120 | }else{
121 | $obj |Add-member NoteProperty BlockPublicAcls "No Configuration Found"
122 | $obj |Add-member NoteProperty IgnorePublicAcls "No Configuration Found"
123 | $obj |Add-member NoteProperty BlockPublicPolicy "No Configuration Found"
124 | $obj |Add-member NoteProperty RestrictPublicBuckets "No Configuration Found"
125 | }
126 |
127 | $s3array += $obj
128 | $s3progress++
129 | }
130 | $orgProgress++
131 | }
132 | $s3array
133 | }
--------------------------------------------------------------------------------
/S3/List All Files In Buckets.ps1:
--------------------------------------------------------------------------------
1 | Function Get-AllFilesInS3Bucket {
2 | param(
3 |
4 | [parameter(Mandatory=$true)][string]$BucketName,
5 | [switch]$OpenInChrome,
6 | [Switch]$Sync,
7 | [Switch]$FindKeys
8 |
9 | )
10 |
11 | #Bucket
12 | #$s3 = "level3-9afd3927f195e10225021a578e6f78df.flaws.cloud"
13 | $s3 = $BucketName
14 |
15 | #region
16 | $region = (resolve-dnsname ((resolve-dnsname $s3).ipaddress)).namehost
17 | $regionsplit = ($region.Split("-.")[2]+"-"+$region.Split("-.")[3]+"-"+$region.Split("-.")[4])
18 |
19 |
20 | #All Files
21 | #$files = aws s3 ls s3://$s3 --no-sign-request --region ($region.Split("-.")[2]+"-"+$region.Split("-.")[3]+"-"+$region.Split("-.")[4])
22 | $files = Get-S3Object -BucketName $s3 -Region $regionsplit
23 |
24 | #HTTP URL For all files
25 | $output = @()
26 | $files|%{
27 | $output += "http://" + $s3 +"."+ $region +'/'+$_.key
28 | }
29 | $output
30 |
31 | if($PSBoundParameters.ContainsKey('OpenInChrome')){
32 | $output | % {
33 | & 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' $_
34 | }
35 |
36 | }
37 |
38 | if($PSBoundParameters.ContainsKey('Sync')){
39 | #if (-not (test-path -literalpath (((Get-location).path) + "\ListAllFilesInBucket"))) {New-Item -Path $path -ItemType Directory -ErrorAction Stop | Out-Null }
40 | $syncvar = "aws s3 sync s3://$s3/ . --no-sign-request --region $regionsplit"
41 | aws s3 sync s3://$s3/ . --no-sign-request --region $regionsplit
42 |
43 | }
44 | $cd = (get-location)
45 | if ($PSBoundParameters.ContainsKey('FindKeys')){
46 | if ($output -like "*/.git/*"){
47 | Get-AccessKeysInS3 -GitFolder $cd}
48 | else{write-host "Couldnt find a /.git/ folder"}
49 | }
50 |
51 |
52 | }
--------------------------------------------------------------------------------
/S3/Set-S3ACLEasy.ps1:
--------------------------------------------------------------------------------
1 | Function Set-S3ACLEasy{
2 | [CmdletBinding()]
3 | param (
4 | [Parameter(Mandatory=$true)][string]$BucketName,
5 | [Parameter(Mandatory=$true)][string]$Region,
6 | [Parameter(Mandatory=$true)][object]$Credential,
7 | [Parameter(Mandatory=$true)]
8 | [ValidateSet("READ","FULL_CONTROL","WRITE","READ_ACP","WRITE_ACP","RESTORE_OBJECT")]
9 | [string]$Permission,
10 | [Object]$CanonicalID
11 | )
12 |
13 | <#
14 |
15 | When applied to a bucket, grants permission to list the bucket.
16 | When applied to an object, this grants permission to read the
17 | object data and/or metadata.
18 |
19 |
20 |
21 |
22 | When applied to a bucket, grants permission to create, overwrite,
23 | and delete any object in the bucket. This permission is not
24 | supported for objects.
25 |
26 |
27 |
28 |
29 | Grants permission to read the ACL for the applicable bucket or object.
30 | The owner of a bucket or object always has this permission implicitly.
31 |
32 |
33 |
34 |
35 | Gives permission to overwrite the ACP for the applicable bucket or object.
36 | The owner of a bucket or object always has this permission implicitly.
37 | Granting this permission is equivalent to granting FULL_CONTROL because
38 | the grant recipient can make any changes to the ACP.
39 |
40 |
41 |
42 |
43 | Provides READ, WRITE, READ_ACP, and WRITE_ACP permissions.
44 | It does not convey additional rights and is provided only for convenience.
45 |
46 |
47 |
48 |
49 | Gives permission to restore an object that is currently stored in Amazon Glacier
50 | for archival storage.
51 |
52 |
53 | #>
54 | #$grants = Get-S3acl -BucketName $bucketname -Region $Region -Credential $Credential
55 | $ACL = Get-S3ACL -BucketName $BucketName -Region $Region -Credential $Credential
56 | $grants = @()
57 | $acl.grants |%{
58 | $grants += $_
59 | }
60 | $CanonicalID|%{
61 | $grantee = New-Object -TypeName Amazon.S3.Model.S3Grantee
62 | $grantee.DisplayName = get-iamaccountalias -Credential $Credential
63 | $grantee.CanonicalUser = $_.CanonicalID
64 |
65 |
66 | $grant = New-Object -TypeName Amazon.S3.Model.S3Grant
67 | $grant.Grantee = $grantee
68 | $grant.Permission = [Amazon.S3.S3Permission]::$Permission
69 | $grants += $grant
70 | }
71 | Set-S3ACL -BucketName $BucketName -Region $region -Credential $Credential -Grant $grants -OwnerId $acl.owner.id
72 |
73 | }
--------------------------------------------------------------------------------
/STS/Get-AWSTempCred.ps1:
--------------------------------------------------------------------------------
1 | #original source https://gist.github.com/jgard/17262e0fc073c82bc7930db2f5603446
2 | #Thanks to the work of jgard. Some stuff didnt work, but a bit of debugging got it going!
3 |
4 | Function Get-Choice {
5 | [cmdletbinding()]
6 | param(
7 | [parameter(
8 | Mandatory = $true,
9 | ValueFromPipeline = $true)]
10 | [string[]]$Options,
11 | [string]$Property,
12 | [string]$Message="Make a selection"
13 | )
14 | Begin {
15 | $i=0
16 | $array = @()
17 | }
18 | Process {
19 | $i++
20 | $array += $_
21 | write-host " $i. " -NoNewline -ForegroundColor 'Green'
22 | if ($Property) {
23 | write-host $_.$Property
24 | } else {
25 | write-host $_
26 | }
27 | }
28 | End {
29 | Do {
30 | $answer=Read-Host -Prompt $message
31 | try{
32 | $Chosen = $array[[int]$answer-1]
33 | } catch {
34 | }
35 | if (!$Chosen) {
36 | Write-Host "Invalid choice '$answer'. Please try again or press Ctrl+C to quit." -ForegroundColor Yellow
37 | } else {
38 | $Chosen
39 | }
40 | } While (!$Chosen)
41 | }
42 | }
43 |
44 | Function Get-STSSAMLCred {
45 | [CmdletBinding()]
46 | [alias("Get-AWSTempCred")]
47 | param (
48 | [string]$ADFSHost='adfs.domain.com', ##Change for environment-appropriate default if desired
49 | [string]$RelyingParty = 'urn:amazon:webservices',
50 | [switch]$SetHost,
51 | [switch]$ChangeUser,
52 | [pscredential]$Credential
53 | )
54 | $WebRequestParams=@{ #Initialize parameters object
55 | Uri = "https://$ADFSHost/adfs/ls/IdpInitiatedSignon.aspx?LoginToRP=$RelyingParty"
56 | Method = 'POST'
57 | ContentType = 'application/x-www-form-urlencoded'
58 | SessionVariable = 'WebSession'
59 | UseBasicParsing = $true
60 | }
61 | if ($Credential) {
62 | $WebRequestParams.Add('Body',@{UserName=$Credential.UserName;Password=$Credential.GetNetworkCredential().Password})
63 | } else {
64 | if ($changeuser){$Credential = Get-Credential -Message "Enter the domain credentials" }
65 | else {$Credential = Get-Credential -Message "Enter the domain credentials" -UserName "$env:USERDOMAIN\$env:USERNAME"}
66 | $WebRequestParams.Add('Body',@{UserName=$Credential.UserName;Password=$Credential.GetNetworkCredential().Password})
67 | }
68 |
69 | #Initial post to ADFS
70 | $InitialResponse=Invoke-WebRequest @WebRequestParams
71 | $SAMLResponseEncoded=$InitialResponse.InputFields.FindByName('SAMLResponse').value
72 | if (!$SAMLResponseEncoded) { #Initial result from ADFS didn't have assertion
73 | if ($InitialResponse.InputFields.FindByName('AuthMethod').value -eq 'SecurIDv2Authentication') { #Handle RSA SecurID
74 | $SAMLResponseEncoded = Read-SecurIDv2Authentication -WebRequestParams $WebRequestParams -InitialResponse $InitialResponse
75 | }
76 | }
77 | if (!$SAMLResponseEncoded) {
78 | Throw "No valid ADFS assertion received. Suggestion: Supply alternate credentials, use different ADFSHost, or a new MFA method is not yet supported by this module."
79 | }
80 |
81 | #Evaluate SAML Response
82 | $SAMLResponseDecoded=[xml]([System.Text.Encoding]::utf8.GetString([System.Convert]::FromBase64String($SAMLResponseEncoded))) | select -ExpandProperty response
83 | #removing this portion temporarily because the configabbrev doesnt look to be a standard response. This portion should pull the account name into the get-choice function
84 | #once i figure out what the standard is, i can add it to the parameter list and set a standard.
85 | <# $AvailableAWSAccts = $SAMLResponseDecoded.Assertion.AttributeStatement.Attribute |?{$_.name -eq 'https://ConfigAbbrev.bch'} | %{
86 | $_.AttributeValue |%{
87 | [PSCustomObject]@{"Accts" = (($_ -replace "\|", "`t ") -split "`t")[0,2] -join ""}
88 | }
89 | }#>
90 |
91 | $AvailableRoles = $SAMLResponseDecoded.Assertion.AttributeStatement.Attribute |?{$_.name -eq 'https://aws.amazon.com/SAML/Attributes/Role'} | %{
92 | <#$AvailableRoles = $SAMLResponseDecoded.Assertion.AttributeStatement.Attribute |?{$_.name -eq 'https://ConfigAbbrev.bch'} | %{
93 | $_.AttributeValue |%{
94 | [PSCustomObject]@{"Role" = ($_ -split "|",0,"SimpleMatch")[0,2] -join "";"SAMLProvider" = ($_ -split ",")[1]}
95 | }
96 | #>
97 | $_.AttributeValue |%{
98 | [PSCustomObject]@{"Role" = ($_ -split ",")[0];"SAMLProvider" = ($_ -split ",")[1]}
99 | }
100 | }
101 | $AvailableRoles = @($AvailableRoles) #Force to be an array to simplfy role count assessment
102 | if ($AvailableRoles.count -eq 0) {
103 | Throw "No available AWS roles found in ADFS response."
104 | }
105 |
106 | If ($AvailableRoles.count -gt 1) {
107 |
108 | <# $AccountsandRoles = @()
109 | $I = 0
110 | do {
111 | $obj = new-object psobject
112 | $obj | Add-member NoteProperty AccountName $AvailableAWSAccts[$i].accts
113 | $obj | Add-Member NoteProperty Role $AvailableRoles[$i].role
114 | $obj | Add-member Noteproperty SAMLProvider $AvailableRoles[$i].SAMLProvider
115 | $AccountsandRoles += $obj
116 | $i++
117 | }
118 | while ($I -lt $AvailableRoles.count)#Choose role logic
119 | #>
120 | $ChosenRole= $AvailableRoles | Get-Choice -Message "Choose which role to assume" -Property 'Role'
121 | } else {
122 | $ChosenRole=$AvailableRoles[0]
123 | }
124 |
125 | #Send token to AWS STS
126 | try {
127 | Write-Host "Using role $($ChosenRole.Role)"
128 | $AssumedRole=Use-STSRoleWithSAML -SAMLAssertion $SAMLResponseEncoded -PrincipalArn $ChosenRole.SAMLProvider -RoleArn $ChosenRole.Role -ErrorAction Stop
129 |
130 |
131 | } catch{
132 | Write-Warning "STS error: $($_.Exception.Message)"
133 | Throw "Failure calling AWS STS service. Likely issues: a) Outgoing internet connectivity or proxy issue, or b) Problem with ADFS trust, claims, or role."
134 | }
135 | write-host ""
136 | #Write-Host "New access key: $($AssumedRole.Credentials.AccessKeyId), expires $($AssumedRole.Credentials.Expiration)"
137 | #Write-Host "Setting as default AWSCredential for future AWSPowershell usage, by exporting to `$Global:StoredAWSCredentials"
138 | #write-host ""
139 |
140 |
141 | if ($SetHost){
142 | Write-Host "Setting as default AWSCredential for future AWSPowershell usage, by exporting to `$Global:StoredAWSCredentials"
143 | Set-AWSCredential -AccessKey $AssumedRole.Credentials.AccessKeyId -SecretKey $AssumedRole.Credentials.SecretAccessKey -SessionToken $AssumedRole.Credentials.SessionToken -StoreAs SAML
144 | Set-AWSCredential -ProfileName SAML
145 | #todo, make the $assumedrole export to the .aws credentials file and overwrite the default
146 | $Global:StoredAWSCredentials = $StoredAWSCredentials
147 | }
148 | else{
149 | #Updating to pscustomobjectoutput. This hides the end of the session token. So to see the output of the script, you will have to store the get-stssamlcred as a variable
150 | [PSCustomObject]@{'AccessKey' = $($AssumedRole.Credentials.AccessKeyId); 'SecretKey' = $($AssumedRole.Credentials.SecretAccessKey); 'SessionToken' = $($AssumedRole.Credentials.SessionToken)}
151 |
152 | }
153 | #Set-AWSCredential -AccessKey $AssumedRole.Credentials.AccessKeyId -SecretKey $AssumedRole.Credentials.SecretAccessKey -SessionToken $AssumedRole.Credentials.SessionToken
154 | #$Global:StoredAWSCredentials = $StoredAWSCredentials
155 | }
156 |
157 | function Read-SecurIDv2Authentication {
158 | [CmdletBinding()]
159 | param (
160 | [hashtable]$WebRequestParams,
161 | $InitialResponse
162 | )
163 |
164 | $WebRequestParams.Remove('SessionVariable')
165 | $WebRequestParams.Add('WebSession',$WebSession)
166 | $WebRequestParams['Body'] = @{AuthMethod=$InitialResponse.InputFields.FindByName('AuthMethod').value;Context=$InitialResponse.InputFields.FindByName('Context').value;InitStatus='true'}
167 | if ($InitialResponse.BaseResponse.ResponseUri.AbsoluteUri) {
168 | $WebRequestParams['Uri'] = $InitialResponse.BaseResponse.ResponseUri.AbsoluteUri
169 | } else {
170 | $WebRequestParams['Uri'] = $InitialResponse.BaseResponse.RequestMessage.RequestUri.AbsoluteUri
171 | }
172 | $RSAInitResponse=Invoke-WebRequest @WebRequestParams
173 |
174 | if ($RSAInitResponse.InputFields.FindById('passcodeInput')) {
175 | $passcode = Read-Host 'Enter RSA SecurID passcode' -AsSecureString
176 | $WebRequestParams['Body'] = @{AuthMethod=$RSAInitResponse.InputFields.FindByName('AuthMethod').value;Context=$RSAInitResponse.InputFields.FindByName('Context').value;Passcode=(New-Object PSCredential "user",$passcode).GetNetworkCredential().Password}
177 | if ($RSAInitResponse.BaseResponse.ResponseUri.AbsoluteUri) {
178 | $WebRequestParams['Uri'] = $RSAInitResponse.BaseResponse.ResponseUri.AbsoluteUri
179 | } else {
180 | $WebRequestParams['Uri'] = $RSAInitResponse.BaseResponse.RequestMessage.RequestUri.AbsoluteUri
181 | }
182 | $RSAResponse = Invoke-WebRequest @WebRequestParams
183 | $RSAResponse.InputFields.FindByName('SAMLResponse').value
184 | }
185 | }
186 |
187 |
--------------------------------------------------------------------------------
/STS/STS Switch Roles in Organization.ps1:
--------------------------------------------------------------------------------
1 | Function Get-STSCreds {
2 | [alias("Switch-AWSRoles")]
3 | param(
4 | [Parameter(Mandatory=$true)][string]$OrganizationID,
5 | [Parameter(Mandatory=$true)][string]$Role
6 |
7 | )
8 |
9 | $region = (Get-AWSRegion|where-object -Property isshelldefault -eq $true)
10 |
11 | $RoleArn = "arn:aws:iam::${OrganizationID}:role/$role"
12 |
13 | #Request temporary credentials for each account and create a credential object
14 |
15 | $Response = (Use-STSRole -Region $Region -RoleArn $RoleArn -RoleSessionName 'CMDB').Credentials
16 | $Credentials = New-AWSCredentials -AccessKey $Response.AccessKeyId -SecretKey $Response.SecretAccessKey -SessionToken $Response.SessionToken
17 | Set-AWSCredential -AccessKey $Response.AccessKeyId -SecretKey $Response.SecretAccessKey -SessionToken $Response.SessionToken -StoreAs 'STSCreds'
18 | $Credentials
19 |
20 | }
21 |
22 | Function Get-STSRoleToken {
23 |
24 | param(
25 | [Parameter(Mandatory=$true)][string]$OrganizationID,
26 | [Parameter(Mandatory=$true)][string]$Role,
27 | [int]$DurationInSeconds = 3600
28 |
29 | )
30 |
31 | $region = (Get-AWSRegion|where-object -Property isshelldefault -eq $true)
32 |
33 | $RoleArn = "arn:aws:iam::${OrganizationID}:role/$role"
34 |
35 | #Request temporary credentials for each account and create a credential object
36 |
37 | $Response = (Use-STSRole -Region $Region -RoleArn $RoleArn -RoleSessionName 'CMDB' -DurationInSeconds $DurationInSeconds).Credentials
38 | $Response
39 |
40 | }
41 |
42 | Function Switch-AccessWithAWSKey {
43 | param (
44 | [Parameter(Mandatory=$true)][string]$AccessKey,
45 | [Parameter(Mandatory=$true)][string]$SecretKey,
46 | [string]$SessionToken,
47 | [string]$Profile = 'tempprofile'
48 | )
49 | if ($PSBoundParameters.ContainsKey('SessionToken')){
50 | Set-AWSCredential -AccessKey $AccessKey -SecretKey $SecretKey -StoreAs $Profile -SessionToken $SessionToken
51 | }
52 | else{Set-AWSCredential -AccessKey $AccessKey -SecretKey $SecretKey -StoreAs $Profile}
53 | Set-AWSCredential -ProfileName $Profile
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/SecurityHub/AddUsertoHub.ps1:
--------------------------------------------------------------------------------
1 | $orgs = Get-ORGAccountList|select id, name, email|ft
--------------------------------------------------------------------------------