From 523d4b0e4180149934a247ecca67054079665668 Mon Sep 17 00:00:00 2001 From: Alistair Mackay <34012094+fireflycons@users.noreply.github.com> Date: Thu, 11 Jul 2019 09:36:30 +0100 Subject: [PATCH] Closes #20 --- .../Get-ATEC2SecurityGroupDependencies.ps1 | 197 ++++++++++++++++-- .../Get-ATEC2SecurityGroupDependencies.md | 111 ++++++++++ docs/en-US/aws-toolbox.md | 3 + 3 files changed, 290 insertions(+), 21 deletions(-) create mode 100644 docs/en-US/Get-ATEC2SecurityGroupDependencies.md diff --git a/aws-toolbox/Public/EC2/Get-ATEC2SecurityGroupDependencies.ps1 b/aws-toolbox/Public/EC2/Get-ATEC2SecurityGroupDependencies.ps1 index 935210e..dffb226 100644 --- a/aws-toolbox/Public/EC2/Get-ATEC2SecurityGroupDependencies.ps1 +++ b/aws-toolbox/Public/EC2/Get-ATEC2SecurityGroupDependencies.ps1 @@ -1,8 +1,59 @@ function Get-ATEC2SecurityGroupDependencies { +<# + .SYNOPSIS + Find all dependencies of a given security group or groups. + + .DESCRIPTION + You cannot delete a security group if it is in use anywhere. + Usages come down to whether it is bound to any network interface (e.g. instance or laod balancer), + or whether it is referenced as the target of a rule in another security group. + + This cmdlet enables you to determine what may be linked to the given security group so you can + break those links prior to deleting it. + + .PARAMETER GroupId + One or more security groups to obtain dependency information for + + .PARAMETER AsText + If set, print a report to the console, else returns an object that can be used by a calling script. + Where possible, if a dependency belongs to a cloudformation stack, then the owning stack name is shown in parentheses. + + .EXAMPLE + Get-ATEC2SecurityGroupDependencies -GroupId sg-00000000 -AsText + List dependencies of given group to console + + .EXAMPLE + Get-ATEC2SecurityGroupDependencies -GroupId sg-00000000 + Return dependencies of given group as object + + .EXAMPLE + (Get-ATEBEnvironmentResourceList my-eb-environment).Instances.SecurityGroups.SecurityGroupId | sort -Unique | Get-ATEC2SecurityGroupDependencies -AsText + List dependencies of security groups attached to instances of an Elastic Beanstalk environment to console. + + .EXAMPLE + (Get-ATEBEnvironmentResourceList my-eb-environment).LoadBalancers.SecurityGroups.SecurityGroupId | Get-ATEC2SecurityGroupDependencies -AsText + List dependencies of security groups attached to load balancers of an Elastic Beanstalk environment to console. + + .NOTES + IAM permissions required to run this command + + - ec2:DescribeSecurityGroups + - ec2:DescribeTags + - elasticloadbalancing:DescribeLoadBalancers + - elasticloadbalancing:DescribeTags + + .INPUTS + [string] + Security Group ID(s) + + .OUTPUTS + [object] + Or nothing if -AsText +#> param ( - [Parameter(ValueFromPipeline)] + [Parameter(ValueFromPipeline, Position = 0)] [string[]]$GroupId, [switch]$AsText @@ -10,30 +61,97 @@ function Get-ATEC2SecurityGroupDependencies begin { - function Get-ENIDetails + function Write-RuleReferences + { + param + ( + [string]$ReferenceType, + [object]$References + ) + + if ($null -eq $References) + { + Write-Host "- No $($ReferenceType.ToLower()) rule references" + } + else + { + Write-Host "- $($ReferenceType) rule references from:" + + $References | + ForEach-Object { + Write-Host " - $_" + } + } + } + + function Get-ELBStack { - [CmdletBinding()] param ( - [Parameter(ValueFromPipelineByPropertyName)] - [string[]]$NetworkInterfaceId + [string]$ElbDescription ) - begin - { } + if ($ElbDescription -match '(ELB\s+)?\w+/(?.*)?/') + { + $elbName = $matches.name - process + try + { + $elb = Get-ELB2LoadBalancer -Name $elbName + } + catch + { + $elb = null + } + } + elseif ($ElbDescription -match '(ELB\s+)?(?.*)') { - $NetworkInterfaceId | - Foreach-Object { - New-Object PSObject -Property @{ - NetworkInterface = $_ - Instance = Get-EC2Instance -Filter @{ Name = 'network-interface.network-interface-id'; Values = $_ } | - Select-Object -ExpandProperty Instances | - Select-Object -ExpandProperty InstanceId - } + $elbName = $matches.name + + try + { + $elb = Get-ELBLoadBalancer -LoadBalancerName $elbName + } + catch + { + $elb = $null } } + + if ($null -eq $elb) + { + return 'Not a load balancer' + } + + if ($elb -is [Amazon.ElasticLoadBalancing.Model.LoadBalancerDescription]) + { + $tags = Get-ELBResourceTag -LoadBalancerName $elbName | Select-Object -ExpandProperty Tags + + } + else + { + $tags = Get-ELB2Tag -ResourceArn $elb.LoadBalancerArn | Select-Object -ExpandProperty Tags + } + + if ($null -eq $tags) + { + return '*NONE*' + } + + $stack = $tags | + Where-Object { + $_.Key -eq 'aws:cloudformation:stack-name' + } | + Select-Object -ExpandProperty Value + + if ($stack) + { + return $stack + } + else + { + return '*NONE*' + } } } @@ -48,23 +166,60 @@ function Get-ATEC2SecurityGroupDependencies { $sg = $sgs.SecurityGroupId - New-Object PSObject -Property @{ + $detail = New-Object PSObject -Property @{ SecurityGroup = $sgs - NetworkInterfaces = Get-EC2NetworkInterface -Filter @{ Name = 'group-id'; Values = $sg } | - Get-ENIDetails - + NetworkInterfaces = Get-EC2NetworkInterface -Filter @{ Name = 'group-id'; Values = $sg } IngressReferences = Get-EC2SecurityGroup -Filter @{ Name = 'ip-permission.group-id'; Values = $sg } | Get-SecurityGroupWithStack | Where-Object { $_.SecurityGroupId -ne $sgs.SecurityGroupId } - EgressReferences = Get-EC2SecurityGroup -Filter @{ Name = 'egress.ip-permission.group-id'; Values = $sg } | Get-SecurityGroupWithStack | Where-Object { $_.SecurityGroupId -ne $sgs.SecurityGroupId } } + + if ($AsText) + { + Write-Host "Dependencies for $sgs" + Write-Host "Attached to:" + + if ($null -eq $detail.NetworkInterfaces) + { + Write-Host "- No network attachments" + } + else + { + $detail.NetworkInterfaces | + ForEach-Object { + + if (-not [string]::IsNullOrEmpty($_.Attachment.InstanceId)) + { + Write-Host "- Instance $($_.Attachment.InstanceId)" + } + elseif (-not [string]::IsNullOrEmpty($_.Description)) + { + $elbStack = Get-ELBStack -ElbDescription $_.Description + Write-Host "- $($_.Description):$($_.AvailabilityZone) ($elbStack)" + } + else + { + Write-Host "- Unknown attachment" + } + } + } + + Write-Host "Other security groups that reference this one:" + Write-RuleReferences -ReferenceType "Ingress" -References $detail.IngressReferences + Write-RuleReferences -ReferenceType "Egress" -References $detail.EgressReferences + Write-Host + } + else + { + $detail + } } } } diff --git a/docs/en-US/Get-ATEC2SecurityGroupDependencies.md b/docs/en-US/Get-ATEC2SecurityGroupDependencies.md new file mode 100644 index 0000000..0488632 --- /dev/null +++ b/docs/en-US/Get-ATEC2SecurityGroupDependencies.md @@ -0,0 +1,111 @@ +--- +external help file: aws-toolbox-help.xml +Module Name: aws-toolbox +online version: https://github.com/fireflycons/aws-toolbox/tree/master/docs/en-US/Get-ATEC2LatestAMI.md +schema: 2.0.0 +--- + +# Get-ATEC2SecurityGroupDependencies + +## SYNOPSIS +Find all dependencies of a given security group or groups. + +## SYNTAX + +``` +Get-ATEC2SecurityGroupDependencies [[-GroupId] ] [-AsText] [] +``` + +## DESCRIPTION +You cannot delete a security group if it is in use anywhere. +Usages come down to whether it is bound to any network interface (e.g. +instance or laod balancer), +or whether it is referenced as the target of a rule in another security group. + +This cmdlet enables you to determine what may be linked to the given security group so you can +break those links prior to deleting it. + +## EXAMPLES + +### EXAMPLE 1 +``` +Get-ATEC2SecurityGroupDependencies -GroupId sg-00000000 -AsText +``` + +List dependencies of given group to console + +### EXAMPLE 2 +``` +Get-ATEC2SecurityGroupDependencies -GroupId sg-00000000 +``` + +Return dependencies of given group as object + +### EXAMPLE 3 +``` +(Get-ATEBEnvironmentResourceList my-eb-environment).Instances.SecurityGroups.SecurityGroupId | sort -Unique | Get-ATEC2SecurityGroupDependencies -AsText +``` + +List dependencies of security groups attached to instances of an Elastic Beanstalk environment to console. + +### EXAMPLE 4 +``` +(Get-ATEBEnvironmentResourceList my-eb-environment).LoadBalancers.SecurityGroups.SecurityGroupId | Get-ATEC2SecurityGroupDependencies -AsText +``` + +List dependencies of security groups attached to load balancers of an Elastic Beanstalk environment to console. + +## PARAMETERS + +### -GroupId +One or more security groups to obtain dependency information for + +```yaml +Type: String[] +Parameter Sets: (All) +Aliases: + +Required: False +Position: 1 +Default value: None +Accept pipeline input: True (ByValue) +Accept wildcard characters: False +``` + +### -AsText +If set, print a report to the console, else returns an object that can be used by a calling script. +Where possible, if a dependency belongs to a cloudformation stack, then the owning stack name is shown in parentheses. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: False +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. +For more information, see about_CommonParameters (http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +### [string] +### Security Group ID(s) +## OUTPUTS + +### [object] +### Or nothing if -AsText +## NOTES +IAM permissions required to run this command + +- ec2:DescribeSecurityGroups +- ec2:DescribeTags +- elasticloadbalancing:DescribeLoadBalancers +- elasticloadbalancing:DescribeTags + +## RELATED LINKS diff --git a/docs/en-US/aws-toolbox.md b/docs/en-US/aws-toolbox.md index ce74360..4032124 100644 --- a/docs/en-US/aws-toolbox.md +++ b/docs/en-US/aws-toolbox.md @@ -41,6 +41,9 @@ Read Load Balancer logs into a list of PowerShell custom objects. ### [Test-ATEC2IsRunningInEC2](Test-ATEC2IsRunningInEC2.md) Tests for executing on EC2 by trying to read EC2 instance metadata URL. +### [Get-ATEC2SecurityGroupDependencies](Get-ATEC2SecurityGroupDependencies.md) +Find dependencies and attachments of given security group(s) + ## IAM Cmdlets ### [Get-ATIAMSessionCredentials](Get-ATIAMSessionCredentials.md) Gets keys from a federated AWS login