# Buggy code
def import_cert(
    name,
    cert_format=_DEFAULT_FORMAT,
    context=_DEFAULT_CONTEXT,
    store=_DEFAULT_STORE,
    exportable=True,
    password="",
    saltenv="base",
):
    """
    Import the certificate file into the given certificate store.

    :param str name: The path of the certificate file to import.
    :param str cert_format: The certificate format. Specify 'cer' for X.509, or
        'pfx' for PKCS #12.
    :param str context: The name of the certificate store location context.
    :param str store: The name of the certificate store.
    :param bool exportable: Mark the certificate as exportable. Only applicable
        to pfx format.
    :param str password: The password of the certificate. Only applicable to pfx
        format. Note that if used interactively, the password will be seen by all minions.
        To protect the password, use a state and get the password from pillar.
    :param str saltenv: The environment the file resides in.

    :return: A boolean representing whether all changes succeeded.
    :rtype: bool

    CLI Example:

    .. code-block:: bash

        salt '*' win_pki.import_cert name='salt://cert.cer'
    """
    cmd = list()
    thumbprint = None
    store_path = r"Cert:\{0}\{1}".format(context, store)
    cert_format = cert_format.lower()

    _validate_cert_format(name=cert_format)

    cached_source_path = __salt__["cp.cache_file"](name, saltenv)

    if not cached_source_path:
        _LOG.error("Unable to get cached copy of file: %s", name)
        return False

    if password:
        cert_props = get_cert_file(name=cached_source_path, password=password)
    else:
        cert_props = get_cert_file(name=cached_source_path)

    current_certs = get_certs(context=context, store=store)

    if cert_props["thumbprint"] in current_certs:
        _LOG.debug(
            "Certificate thumbprint '%s' already present in store: %s",
            cert_props["thumbprint"],
            store_path,
        )
        return True

    if cert_format == "pfx":
        # In instances where an empty password is needed, we use a
        # System.Security.SecureString object since ConvertTo-SecureString will
        # not convert an empty string.
        if password:
            cmd.append(
                r"$Password = ConvertTo-SecureString "
                r"-String '{0}'".format(password)
            )
            cmd.append(" -AsPlainText -Force; ")
        else:
            cmd.append("$Password = New-Object System.Security.SecureString; ")

        cmd.append(
            r"Import-PfxCertificate "
            r"-FilePath '{0}'".format(cached_source_path)
        )
        cmd.append(r" -CertStoreLocation '{0}'".format(store_path))
        cmd.append(r" -Password $Password")

        if exportable:
            cmd.append(" -Exportable")
    else:
        cmd.append(
            r"Import-Certificate "
            r"-FilePath '{0}'".format(cached_source_path)
        )
        cmd.append(r" -CertStoreLocation '{0}'".format(store_path))

    _cmd_run(cmd=str().join(cmd))

    new_certs = get_certs(context=context, store=store)

    for new_cert in new_certs:
        if new_cert not in current_certs:
            thumbprint = new_cert

    if thumbprint:
        _LOG.debug("Certificate imported successfully: %s", name)
        return True
    _LOG.error("Unable to import certificate: %s", name)
    return False


# Traceback (KeyError)
salt-call win_pki.import_cert name=salt://sha2.pfx cert_format=pfx context=LocalMachine store=My exportable=True password=XXXXXXX saltenv=stage -l debug

[DEBUG   ] Reading configuration from c:\salt\conf\minion
[DEBUG   ] Including configuration from 'c:\salt\conf\minion.d\_schedule.conf'
[DEBUG   ] Reading configuration from c:\salt\conf\minion.d\_schedule.conf
[DEBUG   ] Configuration file path: c:\salt\conf\minion
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[DEBUG   ] Reading configuration from c:\salt\conf\minion
[DEBUG   ] Including configuration from 'c:\salt\conf\minion.d\_schedule.conf'
[DEBUG   ] Reading configuration from c:\salt\conf\minion.d\_schedule.conf
[DEBUG   ] Motherboard info not available on this system
[DEBUG   ] Connecting to master. Attempt 1 (infinite attempts)
[DEBUG   ] Initializing new AsyncAuth for ('c:\\salt\\conf\\pki\\minion', 'minion', 'tcp://1.1.1.1:4506')
[DEBUG   ] Generated random reconnect delay between '1000ms' and '11000ms' (1506)
[DEBUG   ] Setting zmq_reconnect_ivl to '1506ms'
[DEBUG   ] Setting zmq_reconnect_ivl_max to '11000ms'
[DEBUG   ] Initializing new AsyncZeroMQReqChannel for ('c:\\salt\\conf\\pki\\minion', 'minion', 'tcp://1.1.1.1:4506', 'clear')
[DEBUG   ] Decrypting the current master AES key
[DEBUG   ] Loaded minion key: c:\salt\conf\pki\minion\minion.pem
[DEBUG   ] SaltEvent PUB socket URI: 4510
[DEBUG   ] SaltEvent PULL socket URI: 4511
[DEBUG   ] Initializing new IPCClient for path: 4511
[DEBUG   ] Sending event: tag = salt/auth/creds; data = {'_stamp': '2017-04-28T13:38:38.054000', 'creds': {'publish_port': 4505, 'aes': 'XXXXXX=', 'master_uri': 'tcp://1.1.1.1:4506'}, 'key': ('c:\\salt\\conf\\pki\\minion', '
minion', 'tcp://1.1.1.1:4506')}
[DEBUG   ] Loaded minion key: c:\salt\conf\pki\minion\minion.pem
[DEBUG   ] Determining pillar cache
[DEBUG   ] Initializing new AsyncZeroMQReqChannel for ('c:\\salt\\conf\\pki\\minion', 'minion', 'tcp://1.1.1.1:4506', 'aes')
[DEBUG   ] Initializing new AsyncAuth for ('c:\\salt\\conf\\pki\\minion', 'minion', 'tcp://1.1.1.1:4506')
[DEBUG   ] Loaded minion key: c:\salt\conf\pki\minion\minion.pem
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] LazyLoaded cmd.shell_info
[DEBUG   ] LazyLoaded reg.list_keys
[DEBUG   ] LazyLoaded win_pki.import_cert
[DEBUG   ] LazyLoaded cp.cache_file
[DEBUG   ] Initializing new AsyncZeroMQReqChannel for ('c:\\salt\\conf\\pki\\minion', 'minion', 'tcp://1.1.1.1:4506', 'aes')
[DEBUG   ] Initializing new AsyncAuth for ('c:\\salt\\conf\\pki\\minion', 'minion', 'tcp://1.1.1.1:4506')
[DEBUG   ] In saltenv 'stage', looking at rel_path 'sha2.pfx' to resolve 'salt://sha2.pfx'
[DEBUG   ] In saltenv 'stage', ** considering ** path 'c:\salt\var\cache\salt\minion\files\stage\sha2.pfx' to resolve 'salt://sha2.pfx'
[INFO    ] Executing command 'Powershell -NonInteractive -NoProfile "Import-Module -Name PKI; ConvertTo-Json -Compress -Depth 4 -InputObject @($CertObject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2; $CertObject.Import('c:\salt\var\cache\salt\minion\files\stage\ctn201
6.sha2.pfx'); $CertObject | Select-Object DnsNameList, SerialNumber, Subject, Thumbprint, Version)"' in directory 'C:\Users\ido'
[ERROR   ] Command 'Import-Module -Name PKI; ConvertTo-Json -Compress -Depth 4 -InputObject @($CertObject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2; $CertObject.Import('c:\salt\var\cache\salt\minion\files\stage\sha2.pfx'); $CertObject | Select-Object DnsName
List, SerialNumber, Subject, Thumbprint, Version)' failed with return code: -532462766
[ERROR   ] stderr: Exception calling "Import" with "1" argument(s): "The specified network password is not correct.
"
At line:1 char:164
+ ... 9Certificate2; $CertObject.Import('c:\salt\var\cache\salt\minion\files\stage\ctn ...
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CryptographicException


Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Management.Automation.Security.NativeMethods.CCGetCertNameList(IntPtr certContext, AltNameType dwAltNameChoice, CryptDecodeFlags dwFlags, UInt32&amp; cName, IntPtr&amp; papwszName)
at Microsoft.PowerShell.Commands.DnsNameProperty.GetCertNames(IntPtr certHandle, AltNameType nameType)
at Microsoft.PowerShell.Commands.DnsNameProperty..ctor(X509Certificate2 cert)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object[] arguments, Object[] originalArguments)
at System.Management.Automation.DotNetAdapter.ConstructorInvokeDotNet(Type type, ConstructorInfo[] constructors, Object[] arguments)
at Microsoft.PowerShell.Commands.NewObjectCommand.CallConstructor(Type type, ConstructorInfo[] constructors, Object[] args)
at Microsoft.PowerShell.Commands.NewObjectCommand.BeginProcessing()
at System.Management.Automation.Cmdlet.DoBeginProcessing()
at System.Management.Automation.CommandProcessorBase.DoBegin()
at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.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.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(Boolean createLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Object[] args)
at System.Management.Automation.ScriptBlock.<>c__DisplayClass4.<InvokeWithPipe>b__2()
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, Object[] args)
at System.Management.Automation.PSScriptProperty.InvokeGetter(Object scriptThis)
at Microsoft.PowerShell.Commands.Internal.Format.MshExpression.GetValue(PSObject target, Boolean eatExceptions)
at Microsoft.PowerShell.Commands.Internal.Format.MshExpression.GetValues(PSObject target, Boolean expand, Boolean eatExceptions)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessParameter(MshParameter p, PSObject inputObject, List`1 result)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessObject(PSObject inputObject)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessObjectAndHandleErrors(PSObject pso)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
at System.Management.Automation.CommandProcessorBase.DoExecute()
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.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.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.DlrScriptCommandProcessor.RunClause(Action`1 clause, Object dollarUnderbar, Object inputToProcess)
at System.Management.Automation.CommandProcessorBase.DoComplete()
at System.Management.Automation.Internal.PipelineProcessor.DoCompleteCore(CommandProcessorBase commandRequestingUpstreamCommandsToStop)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper()
at System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc()
at System.Management.Automation.Runspaces.PipelineThread.WorkerProc()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
[ERROR   ] retcode: -532462766
[ERROR   ] Unable to execute command: $CertObject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2; $CertObject.Import('c:\salt\var\cache\salt\minion\files\stage\sha2.pfx'); $CertObject | Select-Object DnsNameList, SerialNumber, Subject, Thumbprint, Version
Error: Exception calling "Import" with "1" argument(s): "The specified network password is not correct.
"
At line:1 char:164
+ ... 9Certificate2; $CertObject.Import('c:\salt\var\cache\salt\minion\files\stage\ctn ...
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CryptographicException


Unhandled Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Management.Automation.Security.NativeMethods.CCGetCertNameList(IntPtr certContext, AltNameType dwAltNameChoice, CryptDecodeFlags dwFlags, UInt32&amp; cName, IntPtr&amp; papwszName)
at Microsoft.PowerShell.Commands.DnsNameProperty.GetCertNames(IntPtr certHandle, AltNameType nameType)
at Microsoft.PowerShell.Commands.DnsNameProperty..ctor(X509Certificate2 cert)
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Management.Automation.DotNetAdapter.AuxiliaryConstructorInvoke(MethodInformation methodInformation, Object[] arguments, Object[] originalArguments)
at System.Management.Automation.DotNetAdapter.ConstructorInvokeDotNet(Type type, ConstructorInfo[] constructors, Object[] arguments)
at Microsoft.PowerShell.Commands.NewObjectCommand.CallConstructor(Type type, ConstructorInfo[] constructors, Object[] args)
at Microsoft.PowerShell.Commands.NewObjectCommand.BeginProcessing()
at System.Management.Automation.Cmdlet.DoBeginProcessing()
at System.Management.Automation.CommandProcessorBase.DoBegin()
at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.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.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(Boolean createLocalScope, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Object[] args)
at System.Management.Automation.ScriptBlock.<>c__DisplayClass4.<InvokeWithPipe>b__2()
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, Object[] args)
at System.Management.Automation.PSScriptProperty.InvokeGetter(Object scriptThis)
at Microsoft.PowerShell.Commands.Internal.Format.MshExpression.GetValue(PSObject target, Boolean eatExceptions)
at Microsoft.PowerShell.Commands.Internal.Format.MshExpression.GetValues(PSObject target, Boolean expand, Boolean eatExceptions)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessParameter(MshParameter p, PSObject inputObject, List`1 result)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessObject(PSObject inputObject)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessObjectAndHandleErrors(PSObject pso)
at Microsoft.PowerShell.Commands.SelectObjectCommand.ProcessRecord()
at System.Management.Automation.CommandProcessor.ProcessRecord()
at System.Management.Automation.CommandProcessorBase.DoExecute()
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.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.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.DlrScriptCommandProcessor.RunClause(Action`1 clause, Object dollarUnderbar, Object inputToProcess)
at System.Management.Automation.CommandProcessorBase.DoComplete()
at System.Management.Automation.Internal.PipelineProcessor.DoCompleteCore(CommandProcessorBase commandRequestingUpstreamCommandsToStop)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input, Hashtable errorResults, Boolean enumerate)
at System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper()
at System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc()
at System.Management.Automation.Runspaces.PipelineThread.WorkerProc()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
[ERROR   ] Unable to parse return data as Json.
[ERROR   ] Unable to obtain certificate thumbprint: c:\salt\var\cache\salt\minion\files\stage\sha2.pfx
[INFO    ] Executing command 'Powershell -NonInteractive -NoProfile "Import-Module -Name PKI; Test-Path -Path 'Cert:\LocalMachine\My'"' in directory 'C:\Users\ido'
[DEBUG   ] stdout: True
[INFO    ] Executing command 'Powershell -NonInteractive -NoProfile "Import-Module -Name PKI; ConvertTo-Json -Compress -Depth 4 -InputObject @(Get-ChildItem -Path 'Cert:\LocalMachine\My' | Select-Object DnsNameList, SerialNumber, Subject, Thumbprint, Version)"' in directory 'C:\Users\ido'
[DEBUG   ] stdout: []
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
KeyError: 'thumbprint'
Traceback (most recent call last):
File "C:\salt\bin\Scripts\salt-call", line 11, in <module>
salt_call()
File "C:\salt\bin\lib\site-packages\salt\scripts.py", line 379, in salt_call
client.run()
File "C:\salt\bin\lib\site-packages\salt\cli\call.py", line 58, in run
caller.run()
File "C:\salt\bin\lib\site-packages\salt\cli\caller.py", line 134, in run
ret = self.call()
File "C:\salt\bin\lib\site-packages\salt\cli\caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "C:\salt\bin\lib\site-packages\salt\modules\win_pki.py", line 265, in import_cert
if cert_props['thumbprint'] in current_certs:
KeyError: 'thumbprint'
Traceback (most recent call last):
File "C:\salt\bin\Scripts\salt-call", line 11, in <module>
salt_call()
File "C:\salt\bin\lib\site-packages\salt\scripts.py", line 379, in salt_call
client.run()
File "C:\salt\bin\lib\site-packages\salt\cli\call.py", line 58, in run
caller.run()
File "C:\salt\bin\lib\site-packages\salt\cli\caller.py", line 134, in run
ret = self.call()
File "C:\salt\bin\lib\site-packages\salt\cli\caller.py", line 197, in call
ret['return'] = func(*args, **kwargs)
File "C:\salt\bin\lib\site-packages\salt\modules\win_pki.py", line 265, in import_cert
if cert_props['thumbprint'] in current_certs:
KeyError: 'thumbprint'

# Fixed code
def import_cert(
    name,
    cert_format=_DEFAULT_FORMAT,
    context=_DEFAULT_CONTEXT,
    store=_DEFAULT_STORE,
    exportable=True,
    password="",
    saltenv="base",
):
    """
    Import the certificate file into the given certificate store.

    :param str name: The path of the certificate file to import.
    :param str cert_format: The certificate format. Specify 'cer' for X.509, or
        'pfx' for PKCS #12.
    :param str context: The name of the certificate store location context.
    :param str store: The name of the certificate store.
    :param bool exportable: Mark the certificate as exportable. Only applicable
        to pfx format.
    :param str password: The password of the certificate. Only applicable to pfx
        format. Note that if used interactively, the password will be seen by all minions.
        To protect the password, use a state and get the password from pillar.
    :param str saltenv: The environment the file resides in.

    :return: A boolean representing whether all changes succeeded.
    :rtype: bool

    CLI Example:

    .. code-block:: bash

        salt '*' win_pki.import_cert name='salt://cert.cer'
    """
    cmd = list()
    thumbprint = None
    store_path = r"Cert:\{0}\{1}".format(context, store)
    cert_format = cert_format.lower()

    _validate_cert_format(name=cert_format)

    cached_source_path = __salt__["cp.cache_file"](name, saltenv)

    if not cached_source_path:
        _LOG.error("Unable to get cached copy of file: %s", name)
        return False

    if password:
        cert_props = get_cert_file(
            name=cached_source_path, cert_format=cert_format, password=password
        )
    else:
        cert_props = get_cert_file(name=cached_source_path, cert_format=cert_format)

    current_certs = get_certs(context=context, store=store)

    if cert_props["thumbprint"] in current_certs:
        _LOG.debug(
            "Certificate thumbprint '%s' already present in store: %s",
            cert_props["thumbprint"],
            store_path,
        )
        return True

    if cert_format == "pfx":
        # In instances where an empty password is needed, we use a
        # System.Security.SecureString object since ConvertTo-SecureString will
        # not convert an empty string.
        if password:
            cmd.append(
                r"$Password = ConvertTo-SecureString "
                r"-String '{0}'".format(password)
            )
            cmd.append(" -AsPlainText -Force; ")
        else:
            cmd.append("$Password = New-Object System.Security.SecureString; ")

        cmd.append(
            r"Import-PfxCertificate "
            r"-FilePath '{0}'".format(cached_source_path)
        )
        cmd.append(r" -CertStoreLocation '{0}'".format(store_path))
        cmd.append(r" -Password $Password")

        if exportable:
            cmd.append(" -Exportable")
    else:
        cmd.append(
            r"Import-Certificate "
            r"-FilePath '{0}'".format(cached_source_path)
        )
        cmd.append(r" -CertStoreLocation '{0}'".format(store_path))

    _cmd_run(cmd=str().join(cmd))

    new_certs = get_certs(context=context, store=store)

    for new_cert in new_certs:
        if new_cert not in current_certs:
            thumbprint = new_cert

    if thumbprint:
        _LOG.debug("Certificate imported successfully: %s", name)
        return True
    _LOG.error("Unable to import certificate: %s", name)
    return False