Forum Discussion

mmatec01's avatar
mmatec01
Icon for Neophyte rankNeophyte
3 years ago

ParserError during PowerShell script execution - Bug or design?

Just to make clear, I opened a case on this, I want to hear from Support.  However I also wanted to hear whether or not you have come across this.... I mean PowerShell scripting inside DataSources has been around for years so I cannot be the only one encountering this issue...here it is.

A collector incurs ParseException in DataSources using PowerShell script when parsing script parameters such as wmi.pass or wmi.user or any other device property containing single quotes.
so, typical statement in PowerShell such as;
$my_custom_device_property = '##MY.CUSTOM.PROP##'
If the value of that property contains a single quote DataSource will fail with parsing exception;
Unexpected token 'xxxxx'' in expression or statement.
I wonder.... is this fixed in EA Collector 31.100?  Reading through release notes there is a reference to fixing parser exceptions but I cannot tell if this is it.  I doubt it.
By the way, if you use double quotes in PS script when declaring said parameter then there is no issue. As long as the value does not contain double quote, that is, then you will get parsing exception again. :(

  • Anonymous's avatar
    Anonymous

    I would imagine in certain cases, if there were two single quotes in the token value, it would sometimes have a parsing issue and sometimes not. The problem is that the way the token values are inserted: by simple search and replace. So, with your statement:

    $my_custom_device_property = '##MY.CUSTOM.PROP##'

    If my.custom.prop is:

    some'value

    Then the resulting script that the collector tries to execute will be:

    $my_custom_device_property = 'some'value'

    It's not exactly that anything on the LM side has any issues with that (although i wouldn't rule it out, recursive replacement) but PowerShell obviously has an issue with it. There's no closing quote for the last quote.

    It's possible, but I don't know, that the referenced fix might just replace ' (one single quote) with '' (two single quotes) before injecting the value into the powershell script. However, with PowerShell, the encapsulating quotes determine the method of escaping. So, if the encapsulating quotes are single, a single quote is escaped by preceding it another single quote. However, if the encapsulating quotes are double quotes, then single quotes don't need to be escaped (but double quotes do). 

    Long story short, the lesson is to escape special characters. If you know your script encapsulates the token with single quotes, you'll need to make sure your token's single quotes are escaped with single quotes. Or make sure the script uses double quotes (and escape any double quotes in your token). 

  • The thing is.... sometimes the value of device property I am fetching in PowerShell script is instantiated by some automatic action (for example API update) over which I have no control.  Meaning, I cannot parse and sanitize (escape single quote) the value before I try to declare it in PowerShell.  I can only control what I can control.

  • Can you use groovy since it doesn't do the serach-replace thing? Or perhaps you can try using a here-string like below for powershell.

    $MyProp = @'
        ##MyProp##
    '@.TrimStart()
    

     

    I'm not sure if there is any real 100% solution when the input is directly injected into code.

  • Well.  Mike.  Thank you for couple of suggested workarounds.  I don't want to use groovy in this particular DS.  By the way if groovy can ingest special characters without scrubbing them, so should PowerShell.  That's my point in here, in that PowerShell scripting should be a first-class citizen just like groovy is.  Isn't the JVM that's running under the hood and parses both the groovy and PowerShell?

    Back to this issue.  I ran some tests and now I found a workaround solution.

    • Declaring variable with $my_custom_device_property = '##MY.CUSTOM.PROP##' statement does not work if the value contains single quote.  No surprise there.
    • Declaring variable using here-string syntax (from above post) does not work either for the same reason.
    • Declaring variable by prefixing it by API GET call - which fetches said property works!  For the simple reason that now you can check and sanitize the API result output before you assign it to variable.  Like this:
      $my_custom_device_property = (Get-Device_Property /device/devices/${device_id}/properties/${device_prop_name}) -replace "'",''

    Note to self - go back to your scripts and change the simple assignments to API get function for the properties you can not control their contents.

  • Anonymous's avatar
    Anonymous
    50 minutes ago, mmatec01 said:

    By the way if groovy can ingest special characters without scrubbing them, so should PowerShell. 

    It's a limitation of the language, not the JVM. The language specifies different ways of escaping based on encapsulation. Groovy is a language that has a unified escaping method, regardless of encapsulating markers.

  • Hmm, I'm not sure if it's about escaping method, afaik groovy has the same single and double quote syntax as PowerShell or many other languages. I think it's more that groovy can import internal/collector functions like hostProps.get() without the collector needing to directly modifying your code with search-replace. Since the collector is java-based I assume that was easy to do but powershell is dotnet based so it can't just import java classes.

  • Anonymous's avatar
    Anonymous
    Just now, Mike Moniz said:

    groovy can import internal/collector functions like hostProps.get() without having the collector needing to directly modifying your code with search-replace

    Yes, that is true. What I mean is that to escape a quote in a string in Groovy, you do it the same whether it's single quotes or double quotes encapsulating the string:

    def string1 = "mystring\"withquotes"
    def string2 = 'mystring\"withquotes'
    assert string1 == string2

     

  • OK, I got the feedback back from the Support.  So here it is, right from the horse's mouth, so to speak;

    This is actually a known issue that our developers are working on.  It looks like it should be solved in collector version 31.200, which is scheduled to be released by the end of the month.

  • Chiming in here to provide some public clarification as I've done some additional review of the issue and response that you've received from our support team-

    It seems that there was some unfortunate misunderstanding when first receiving your ticket.

    I did review the engineering plans that were referenced as the "incoming fix" and unfortunately they are unrelated to single or double-quote prematurely exiting strings and throwing parse errors. At this time there are no plans for this to be resolved through LM product changes.

    Our suggested workarounds are to use escape characters embedded within the property value itself which should prevent these issues from occurring, as we have seen similar problems with "$" used in  properties/credentials in the past. As you noted in the ticket you can also get the data via API and sanitize it by stripping the single or double quotation, etc. when declaring your variables.