ansible-collections / ansible.windows

Windows core collection for Ansible
https://galaxy.ansible.com/ansible/windows
GNU General Public License v3.0
242 stars 163 forks source link

win_dns_client crashes on virtual interfaces #339

Open spectras opened 2 years ago

spectras commented 2 years ago
SUMMARY

The powershell script used by win_dns_client inspects the configuration of all interfaces. Virtual Ethernet adapters, however, do not seem to be valid in that context.

The property 'IPEnabled' cannot be found on this object. Verify that the property exists.
At line:125 char:37
+         $net_info = $adapter_info | ForEach-Object -Process {

The error is a bit misleading, as a quick test shows $adapter_info is $null because Get-CimInstance returned $null here: https://github.com/ansible-collections/ansible.windows/blob/main/plugins/modules/win_dns_client.ps1#L139

ISSUE TYPE
COMPONENT NAME

ansible.windows.win_dns_client, in the powershell script.

ANSIBLE VERSION
ansible [core 2.12.2]
  config file = /mnt/d/Workspace/infrastructure/configuration/ansible.cfg
  configured module search path = ['/mnt/d/Workspace/infrastructure/configuration/library']
  ansible python module location = /mnt/d/Workspace/infrastructure/configuration/.env/lib/python3.9/site-packages/ansible
  ansible collection location = /home/spectras/.ansible/collections:/usr/share/ansible/collections
  executable location = /mnt/d/Workspace/infrastructure/configuration/.env/bin/ansible
  python version = 3.9.7 (default, Sep 10 2021, 14:59:43) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True
COLLECTION VERSION
# /mnt/d/Workspace/infrastructure/configuration/.env/lib/python3.9/site-packages/ansible_collections
Collection      Version
--------------- -------
ansible.windows 1.9.0
CONFIGURATION
ANSIBLE_PIPELINING(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = True
DEFAULT_ASK_VAULT_PASS(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = True
DEFAULT_FORCE_HANDLERS(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = True
DEFAULT_GATHERING(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = smart
DEFAULT_HOST_LIST(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = ['/mnt/d/Workspace/infrastructure/configuration/inventory.ini']
DEFAULT_MODULE_PATH(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = ['/mnt/d/Workspace/infrastructure/configuration/library']
DEFAULT_PRIVATE_KEY_FILE(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = /mnt/d/Workspace/infrastructure/configuration/secrets/ansible.key
DEFAULT_PRIVATE_ROLE_VARS(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = True
DEFAULT_REMOTE_USER(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = ansible
DEFAULT_ROLES_PATH(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = ['/mnt/d/Workspace/infrastructure/configuration/galaxy']
DISPLAY_SKIPPED_HOSTS(/mnt/d/Workspace/infrastructure/configuration/ansible.cfg) = False
OS / ENVIRONMENT
STEPS TO REPRODUCE

The problems shows up when using * as adapter name, as the virtual adapter gets enumerated.

- name: Configure DNS host resolution
  ansible.windows.win_dns_client:
    adapter_names: "*"
    dns_servers: "192.168.1.115"
EXPECTED RESULTS

Configuration is done. I think skipping virtual adapters would be fine as they do not seem configurable.

ACTUAL RESULTS

I seems virtual ethernet adapters do not have valid configuration objects from Get-CimInstance, making it return null. Then when the scripts tries to read properties, an exception is thrown.

Full error message below:

TASK [common : Configure DNS host resolution] ***************************************************************************************************task path: /mnt/d/Workspace/infrastructure/configuration/roles/common/tasks/windows.yml:41
The full traceback is:
The property 'IPEnabled' cannot be found on this object. Verify that the property exists.
At line:125 char:37
+         $net_info = $adapter_info | ForEach-Object -Process {
+                                     ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [ForEach-Object], PropertyNotFoundException
    + FullyQualifiedErrorId : PropertyNotFoundStrict,Microsoft.PowerShell.Commands.ForEachObjectCommand

ScriptStackTrace:
at <ScriptBlock>, <No file>: line 141
at Get-NetAdapterInfo<Process>, <No file>: line 125
at <ScriptBlock>, <No file>: line 350

System.Management.Automation.PropertyNotFoundException: The property 'IPEnabled' cannot be found on this object. Verify that the property exists.   at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
   at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
   at System.Management.Automation.ScriptBlock.InvokeWithPipeImpl(ScriptBlockClauseToInvoke clauseToInvoke, Boolean createLocalScope, Dictionary`2 functionsToDefine, List`1 variablesToDefine, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Object[] args)
   at System.Management.Automation.ScriptBlock.<>c__DisplayClass57_0.<InvokeWithPipe>b__0()
   at System.Management.Automation.Runspaces.RunspaceBase.RunActionIfNoRunningPipelinesWithThreadCheck(Action action)
   at System.Management.Automation.ScriptBlock.InvokeWithPipe(Boolean useLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Boolean propagateAllExceptionsToTop, List`1 variablesToDefine, Dictionary`2 functionsToDefine, Object[] args)
   at System.Management.Automation.ScriptBlock.InvokeUsingCmdlet(Cmdlet contextCmdlet, Boolean useLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Object[] args)
   at Microsoft.PowerShell.Commands.ForEachObjectCommand.ProcessRecord()
   at System.Management.Automation.CommandProcessor.ProcessRecord()
fatal: [gitlab-runner9]: FAILED! => {
    "changed": false,
    "msg": "Unhandled exception while executing module: The property 'IPEnabled' cannot be found on this object. Verify that the property exists."
}

Specifying just the physical adapter names explicitly in adapter_names works around the problem.

jborean93 commented 2 years ago

Sorry for the delay in looking at this issue. It seems like the problem is not just about virtual interfaces as the tests in CI run on a virtual loopback adapter and testing locally doesn't seem to bring up the problem you are seeing

PS C:\Windows\system32> Get-CimInstance -ClassName Win32_NetworkAdapterConfiguration -Filter 'InterfaceIndex = 16' -Property DNSServerSearchOrder, IPEnabled, SettingID | Select-Object -Property DNSServerSearchOrder, IPEnabled, @{ N = 'InterfaceGuid'; E = { $_.SettingId } }

DNSServerSearchOrder IPEnabled InterfaceGuid
-------------------- --------- -------------
                          True {2C9EF0FA-B966-47AC-9E5A-518931B949EA}

In the above example InterfaceIndex is the loopback virtual adapter I've added for testing and it definitely returns the output as expected. I also copied and ran that function manually on my host and can verify that it doesn't fail

PS C:\Windows\system32> Get-NetAdapterInfo

Name        InterfaceIndex InterfaceGuid                          RegInfo
----        -------------- -------------                          -------
Ethernet                12 {864AA09D-872B-42C2-A3D2-C32D3CA3A177}
VirtAdapter             16 {2C9EF0FA-B966-47AC-9E5A-518931B949EA}
Ethernet 2               5 {0D60B040-DA3B-478A-BD35-41514BBEC027}

At a guess it's not specifically a virtual adapter that's problematic here but something specific about this type of virtual adapter the code needs to handle better. Are you able to provide the following:

A simple workaround is to change the if statement to something like if (-not $adapter_config -or $adapter_config.IPEnabled -eq $false) { but it would be good to figure out what specifically about your adapter is causing the problem here.