Hace unos días, el 17 de febrero 2022, salía una nueva característica.
General availability: Automatically delete a VM and its associated resources simultaneously
Automatically delete disks, NICs and Public IPs associated with a VM at the same time you delete the VM. With this feature, you can specify the associated resources that should be automatically deleted when you delete a VM. This will allow you to save time and simplify the VM management process.
El caso es que por esta característica y a raiz de comentarlo por Linkedin me ha surgido la idea de este post. Una mezcla de teoría de NSGs y PowerShell.
Vamos al lío.
Para la entrada anterior de Draw.io he creado un grupo de recursos con una máquina virtual. Nada complicado. VM con Windows 10, siguiente, siguiente…

Una vez termino de echar las capturas para el artículo, voy a borrar la VM. Y vemos la nueva característica del borrado.

Tenemos la opción de «Apply force delete» que me indica que si no hago este borrado, tendré recursos huérfanos.
You can also choose to delete associated resources at the same time. Resources that aren’t deleted will be orphaned. Associated resources that are in use by other resources are not shown here.

Vamos a jugar un poco con Powershell para ver el tipo de recursos que tengo en un grupo de recursos y contarlos.
Get-AzResource -ResourceGroupName RG-drawio | select ResourceType
(De todos los grupos de recursos sólo quiere uno y además me quedo con una propiedad: ResorceType)

Vamos a contarlos ayudándonos de una variable auxiliar.
$aux = Get-AzResource -ResourceGroupName RG-drawio
$aux.count
(Dime todos los recursos de un grupo de recursos. Me los pones en una variable. Y luego uso el «count» de esa variable para saber el número de estos).

Tengo 7 recursos. Y procedo a borrar usando la nueva característica.

En el «chivatillo» me indica que se borra la VM y los recursos asociados. ¿Todos los recursos asociados?. Veámoslo.

$aux = Get-AzResource -ResourceGroupName RG-drawio
$aux.count

Vuelvo a contar los recursos. Y me dice que quedan 2 (ha borrado 5).
Mostramos el tipo y vemos la Vnet y un NSG.
Get-AzResource -ResourceGroupName RG-drawio | select ResourceType

En el portal.


En la imagen podemos comprobar los elementos borrados. Se ha eliminado la propia VM, Ip pública, NIC y disco. De «regalo» nos ha eliminado «schedules» (en las PoC suelo poner que la máquina se apague por la tarde ya que a quién no le ha pasado de dejarse algo corriendo 🙂 )
Pero, como apreciaba el compañero en Linkedin, el NSG sigue apareciendo ¿no es un elemento asociado a la máquina virtual?. En principio sí. Pero entiendo que no se borra ya que podrían tener ese NSG asociado a otros elementos. No sería trivial ese borrado. Quizás si el NSG no está asociado a otra NIC o a la subnet… pero ante la duda, mejor el borrado manual.
Como buena práctica, que además figura en varias iniciativas de seguridad, prefiero asociar los NSGs a subnets en lugar de a NICs de máquinas virtuales.
«Subnets should be associated with a Network Security Group«.
Pero como consultores debemos suponer que esto no siempre va a pasar. Entre nuestros scripts tenemos que tener uno para detectar este tipo de recursos.
¿Cómo se yo qué NSG ha quedado huérfano?
Sabemos que los NSGs se pueden asociar o bien a una Subnet o bien a una NIC.
En la POC teniamos un NSG asociado a una NIC y hemos borrado dicha NIC. Además, para este post encontramos otro NSG asociado a una Subnet.
Vamos a verlo en el portal.


Como ir navegando por el portal para ver cómo están los NSGs puede ser un poco tedioso, vamos a pedir ayuda a Powershell.
Get-AzNetworkSecurityGroup | select name
(Oye, dime qué NSGs tengo en la subcripción. Selecciona el nombre)

OK. Tenemos los dos NSGs que vimos antes en el portal. Ahora sácamos las propiedades de los NSGs que me interesan, quiero ver qué me indica.
Get-AzNetworkSecurityGroup | select networkInterfaces

Get-AzNetworkSecurityGroup | select subnets

Vaya, las dos están «vacias» pero en el portal vi que un NSG estaba asociado a una Subnet.
Hacemos un «Get-AzNetworkSecurityGroup» a ver qué me dice.
Haciendo un poco de «zoom» entre toda la información que me escupe el comando. Un NSG tiene la «Subnets» vacía, lo esperado.

Pero el otro NSG sí tiene información. Es decir, que está asociada. Vamos a ver que hay un «id» y vemos que encontramos el nombre de la subnet que vimos en la imagen del portal: «default«.

Podemos decir a PowerShell que queremos quedarnos con esa propiedad en concreto.
$nsg = Get-AzNetworkSecurityGroup | select subnets
$nsg.Subnets.Id

Vamos a preguntar. Oye, dime que NSGs no están asociados a una subnet.
$nsg | Where-Object {$_.Subnets.Id -eq $null} | select name
(De la variable de los NSG, dime dónde la subnet está en $null ya que sabré que no está asociada. Me quedo con el nombre)

Ok, ya tenemos medio trabajo hecho. Pero me falta ver los NSGs que no tienen asociado una NIC.
Voy a añadir el «nsg-default» a una NIC para repetir el proceso que se he hecho con la subnet

$nsg = Get-AzNetworkSecurityGroup | select networkInterfaces,name
$nsg

Pero ya vimos antes que aquí «hay gato encerrado». Que tenemos que analizar dentro de esas propiedades para ver si ese {} es un $null.
$nsg = Get-AzNetworkSecurityGroup | select networkInterfaces
$nsg.networkInterfaces # saca demasiada información para loq ue busco
$nsg.networkInterfaces.id # Me quedo sólo con el ID

Como en el caso anterior, nos podemos basar en ese «Id» para chequear los NSGs. Vamos a utilizarlo con la consola.
Inciso: fíjate que en este caso uso «-ne» -> not equals (no es igual a).
Inciso: Link about_Comparison_Operators
$nsg = Get-AzNetworkSecurityGroup | select networkInterfaces,name
$nsg | Where-Object {$_.NetworkInterfaces.Id -ne $null } | select name
Oye, sácame los NSGs que NO sean $null en la NIC. Me quedo con el nombre.

Ahora vamos a conseguir lo opuesto con «-eq».
$nsg = Get-AzNetworkSecurityGroup | select networkInterfaces,name
$nsg | Where-Object {$_.NetworkInterfaces.Id -eq $null } | select name
Oye, lo contrario.

Hacemos las del «coctelero» y mezclamos todo. Añadimos otro operado «-and». Es decir: sin subnet «y» sin NIC.
$nsg | Where-Object {$_.Subnets.Id -eq $null -and $_.NetworkInterfaces.Id-eq $null } | select name

Y ya está. De este modo podemos sacar los NSGs que no tienen asociada ni una NIC, ni una subnet.
Espero que os haya sido interesante esta entrada con PowerShell. Para algunos habrá sido sencilla pero partimos de cero. Y como tocando es cómo se aprende. ¿Serías capaz de indicar los NSGs de una región en concreto?


Súper bien explicado! Súper útil para saber que NSG tenemos que no necesitamos!