14 Replies Latest reply on Feb 21, 2019 2:32 AM by phoffmann

    Evaluation of different available APIs and Authentication issues

    jackhorner Rookie

      We are trying to crudely wrap LDMS with our own company framework and setup respective proxy APIs specifically for MS patching.  I'm having trouble authenticating to several of the APIs.

       

      I'm a developer just getting started learning LDMS and working with our engineers who use the product via console.  Here's what I know:

       

      API

      Parent Product

      Url

      Auth

      Documentation

      Notes

      LDSD

      BridgeIT

      http://mycoreserver/My.Framework

      My.IdentityServer

      Not found

      -Service Desk API?

      -configured via https://coreserver/ConfigurationCenter BridgeIt

      Discovery

      BridgeIT

      http://mycoreserver/discovery/api

      My.IdentityServer?

      Not found

      -Purpose?

      -configured via https://coreserver/ConfigurationCenter BridgeIt

      LDMS (LDAPI)

      BridgeIT

      http://mycoreserver/ldapi/api

      My.IdentityServer?

      Not found

      Swagger?

      -Purpose? Same as Restful Api?

      -configured via https://coreserver/ConfigurationCenter BridgeIt

      -How do you specifically auth?

      Legacy MBSDK

      LDMS 2017

      http://mycoreserver/mbSDKService/MsgSDK.asmx

       

      WSDL

      -Auth working using integrated security

      -Legacy product

      Restful SDK

      LanDesk SDK

      http://baseuri/api/v1

      SAML 1.1 sig

      LanDesk SDK document

      -Read only for “canned” DB queries

      -Have document LanDesk SDK

      -Same as LDMS (LDAPI)?

      -How do you configure?

      -How do you specifically auth?

      Distribution

      EPM

      http://mycoreserver/DistributionApi

      My.IdentityServer oauth2.0

      Swagger

      -Using PostMan but getting invalid_trust (https://community.ivanti.com/docs/DOC-70864)

      -Using creds of LDMS admin; same as EPM Admin?

      Patch

      EPM

      http://mycoreserver/PatchApi

      My.IdentityServer oauth2.0

      Swagger

      -Using PostMan but getting invalid_trust (https://community.ivanti.com/docs/DOC-70864)

      -Using creds of LDMS admin; same as EPM Admin?

      -Seems to be ready only queries

       

      I think i'm mainly interested in LDAPI, MBSDK, Patch APIs for patching.  here are my questions if anyone can help...

       

      -Is LDAPI the same as Restful SDK? the later seems to be "read only".

      -Trying to auth to EPM apis and getting invalid_trust response from identity server.  i am trying to log in as LDMS admin.  is that the same as EPM admin?

      -How do i auth to LDAPI, same way as EPM apis? 

      -I am able to successfully use MBSDK

       

      any comments, help, or direction pointing is greatly appreciated!

       

      -dave

        • 1. Re: Evaluation of different available APIs and Authentication issues
          phoffmann SupportEmployee

          So I can help here a little bit hopefully.

           

           

          • LDAPI == The 'new' REST-ful API. Correct.
          • BridgeIT was an attempt at "a common API interface" across various Ivanti products (EPM and Service Desk at the time) ... that is by and large unused now, the thing "from that period" that's still of use is the Identity server (historically speaking).
          • You can probably try to get some non public documentation for the LDAPI (useful. because REST-ful and all that ... SOAP has its issues) by trying to go through support (who can contact me internally if they're not sure how to proceed / stuck ). I'm intending to do an MBSDK-like article but for LDAPI "as I can set aside time", but it's not a small thing (those articles aren't meant for just devs, but a "starting from 0"-type article, as a lot of folks benefit from a gentle leg up).
          • LDAPI should be mostly SWAGGER-documented (again, I have some stuff which we can probably get you via support - but since I'm not sure whether any official docs / NDA-s or whatnot need to be signed, I'm asking you to go through support first). .
          • LDAPI has a few modes of authentication - from SAML-tokens to others (such as NT). What version of EPM / Management Suite are you looking at exactly ("Authenticating to LDAPI" will likely be a separate sub-article as there's a bunch of different ways) ?

           

          Let's start with that?

          • 2. Re: Evaluation of different available APIs and Authentication issues
            jackhorner Rookie

            Thank you so much for the valued info!   Yes, i did successfully use the first article you mentioned and the WSDL to get a skeleton proof of concept working.  Authentication and execution is working perfectly.

             

            We are on 2017.3.3 in production but plan to upgrade within the next 6 months.  Not sure if My.IdentityServer is an option but with the other newer EPMs (patch and distribution), i get invalid_trust as a response when using the documentation (https://community.ivanti.com/docs/DOC-70864) under postman.  Is there a difference between LDMS admin vs EPM admin? 

             

            I ask this because i'm assumimg the same oauth2.0 would be valid option for LDAPI?

             

            again thanks!!!

            • 3. Re: Evaluation of different available APIs and Authentication issues
              phoffmann SupportEmployee

              I'll have a dig around my documents and such tomorrow, to see if I can give you a quick leg up.

               

              A few bullet points though,

               

              • EPM ("Endpoint Manager") == "LDMS"-s new name. See here for info -- Ivanti Product Names & Acronyms -- that may help with some confusion .
              • So you have a few authentication options. OAuth 2 is one of them - yes.

              ... I'll see what I can dig up if I get a bit of quiet time, and try to share something to get you rolling.

              • 4. Re: Evaluation of different available APIs and Authentication issues
                phoffmann SupportEmployee

                Here's a bit on Authentication with a OAuth 2 JWT (JSON Web Token)... pinched (and slightly modified) these from an Interchange lab (so those steps aren't mine). I hope I caught all instances where there were Interchange-specific lab names ... *fingers crossed*.

                 

                Get a jwt (JSON web token) using the resource only password flow.

                1. Open Postman
                2. Click on the “Authorization” tab
                3. Select “OAuth 2.0” from the “Type” drop-down list
                4. Click on the orange “Get New Access Token” button
                5. Fill in the “GET NEW ACCESS TOKEN” form:
                  1. Give the token the name “Resource
                  2. Select the “Password Credentials” grant type in the “Grant Type” dropdown list.
                  3. The Access Token Url is “https://MYSERVERNAME/my.identityserver/identity/connect/token”. You can find it by opening Chrome and browsing to “https://MYSERVERNAME/my.identityserver/identity/.well-known/openid-configuration” or type it in.
                  4. Enter your NT-user name and password (i.e. "MyDomain\MyUser"). Note that this MUST be a user that has EPM console rights

                  5. Enter “ResourceOnly” for the Client ID

                  6. Enter “<YOURSECRET>” for the Client Secret

                  7. Enter “openid” for scope

                  8. Select “Send Client Credentials in body” in the “Client Authentication” dropdown list

                  9. Click on the orange “Request Token” button. You should get a token here. It could take up to a minute to get a token the first time. After that all the services should be up and running, and a token request will be must faster.

                  10. Close the “MANAGE ACCESS TOKENS” window

                  11. Select “Resource”, or whatever you named your token, from the “Available Tokens” dropdown.

                  12. Remove the extra OData query placeholder information and leave only "https://MYSERVERNAME/DistributionApi/api/v1/Packages" in the textbox to the right of the “GET” dropdown.

                  13. Click on the blue “Send” button. There may be a lot of packages, and we are getting all the attributes, so it may take a while, but there should be an array of packages returned.
                6. You just used the api to get a list of Software Distribution packages that you have rights to view. The api validates the signature of the jwt and looks at the claims to see what EPM console user you are. The api authorizes the user’s rba rights and checks if the user is the owner of the package or if the package is public when creating the result set.

                 

                ... that should help you to get going, I hope?

                • 5. Re: Evaluation of different available APIs and Authentication issues
                  phoffmann SupportEmployee

                  One thing to note (that I ran afoul of) by the by -- not sure if this is a GENERAL REST-ful API thing, or something about ours, but case sensitivity *IS* a thing (which caught me VERY much by surprise).

                   

                  Unlike SOAP-services, the case-sensitivity really caught me out.

                   

                  NOTE -- the below include a few work-arounds as my dev core uses a self-signed cert (unsurprisingly I don't have a "proper" cert) ... it should also be noted that using HTTP (rather than HTTPS) can be *VERY* much more helpful (though works only locally on the Core) when developing, as HTTP based comms give you vaguely relevant error messages, while HTTPS is a pain in the butt as pretty much *ANY* kind of error in your code gives you the same failure code

                   

                  ... a basic "get a SAML token" script ...

                  $url = "https://localhost/sts/issuetoken"
                  $web = New-Object System.Net.WebClient
                  $web.UseDefaultCredentials = $true
                  
                  # WARNING - Only use a self-signed certificate for testing!
                  [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
                  
                  $response = $web.DownloadString($url)
                  $psToken = $response | ConvertFrom-Json
                  
                  Write-Host ("Here comes my SAML Token! My token is good for 12 hours by default!")
                  Write-Host $psToken.SAMLToken
                  

                   

                  As an aside, here's a simple little Powershell script to query some inventory data using/authenticating with a SAML-token for instance ...

                  # Point to the STS site to receive an STS token.
                  $url = "https://localhost/sts/issuetoken"
                  
                  # Configure
                  $web = New-Object System.Net.WebClient
                  # Enable the use of pass-through credentials for ease of use in this example.
                  # You can equally prompt for credentials, which we'll go through in another example seperately.
                  $web.UseDefaultCredentials = $true
                  
                  # WARNING - Only use a self-signed certificate for testing!
                  [System.Net.ServicePointManager]::ServerCertificateValidationCallback = { $true }
                  
                  $response = $web.DownloadString($url)
                  $MySAMLToken = $response | ConvertFrom-Json
                  
                  # We no longer need to use pass-through credentials, since we'll be authenticating with the
                  # SAML token! So let's turn off pass-through authentication!
                  $web.UseDefaultCredentials = $false
                  
                  # Now, let's point our powershell at the LDAPI we want to hit up
                  $url = "https://localhost/ldapi/api/v1/Devices"
                  
                  # Constructing / adding the SAML token to our Authorisation string.
                  # NOTE the following
                  #   - US spelling (with a "z" instead of an "s" of "Authorisation"
                  #   - The space after the "SAML " is intentional and NECESSARY!
                  $web.Headers.Add("Authorization", "SAML " + $MySAMLToken.SAMLToken )
                  $response = $web.DownloadString($url);
                  
                  # Get the response and convert it into something PowerShell can operate with from the JSON format.
                  $psDevices = $response | ConvertFrom-Json
                  
                  # Create a fresh array called $Devices of "just the device names" from the received data-set.
                  $Devices = $psDevices.value
                  
                  # Display the list of device names via a simple loop based on the # of elements in our result-set.
                  for ($i=0; $i -lt $Devices.length; $i++) {
                      Write-Host $Devices[$i].displayname
                  }
                  

                   

                  This explains / points out PS'es issues with self-signed SSL certs ("great" for dev environments)

                   

                  "I don't care policy" for devving... (Powershell specific)

                  • 6. Re: Evaluation of different available APIs and Authentication issues
                    phoffmann SupportEmployee

                    Addendum - reminder ... be aware that the JWT token tends to have a default lifetime of 1 hour.

                     

                    Not a problem once scripts are running / done usually, but can be relevant while doing dev. So don't forget to request new tokens as needed .

                    • 7. Re: Evaluation of different available APIs and Authentication issues
                      jackhorner Rookie

                      THANK YOU THANK YOU for all this glorious info!!!

                       

                      I haven't gone down the explicit route of JWTs yet but i will try.  i did follow this document to the "T": How to connect to EPM APIs ?

                      I'm assuming it's very similar to JWTs just looking at some of the set up between the two.

                       

                      Just a few notes about following that document and the error i'm receiving of "invalid_trust" back from the identity server:

                      -I'm pretty sure i have everything set up properly from the document because if i mistype either the clientid or the client secret or select the wrong trust type, i get the respective up stream error.

                      -I think invalid_trust would be down stream in actually validating the EPM admin uid and pwd.

                       

                      after chatting with a coworker familiar with our setup, he thinks we didn't set up STS on the instance that i'm working with. could that be the underlying issue?  another clue to support that would be from the console context menu when i select tools ->  configuration -> Ivanti workspaces, it opens a browser window to authenticate (https://mycoreserver/My.IdentityServer/identity/login?signin=XXXX).  no matter what valid creds i supply, i always receive this error of "there was an unexpected error. request id XXX" with url https://mycoreserver/My.IdentityServer/identity/callback.

                       

                      does STS need to be configured properly and are there any simple tests that i can perform to isolate my auth issues?

                       

                      again many many thanks!

                      • 8. Re: Evaluation of different available APIs and Authentication issues
                        phoffmann SupportEmployee

                        <Dislcaimer -- if I appear to cover a few "how to suck eggs" scenarios here, it's mainly as I intend to write things out & include them in the LDAPI-article ... so this way I may as well have them written out in a "copy & paste"-able form for the best part. Not being patronising >

                         

                        STS should "be there" - as it's part of the install normally. If STS (the Secure Token Server) is missing, then yes - that'll cause a bunch of issues as that's how you authenticate to the LDAPI.

                         

                        It should "work straight from the install" normally ...

                         

                        So checking on my own Core (this is 2018.3 + SU1 for reference) .. first up, in IIS you should have something like the following under the "Default Web Site"... (click on the picture for the full-size version).

                        • The red highlights are the various API-s...
                        • while I've marked in blue the Identity server.

                         

                        Useful logs here (all Core-side):

                        • "C:\ProgramData\LANDesk\ServiceDesk\My.IdentityServer\Logs\ LANDESK.IdentityServer.log" - this log is helpful if you cannot login.
                        • "C:\Program Files\LANDesk\ManagementSuite\log\DistributionApi.dll.log" - Distribution API log
                        • "C:\Program Files\LANDesk\ManagementSuite\log\PatchApi.dll.log" - Patch API log.
                        • "C:\Program Files\LANDesk\ManagementSuite\log\ldapi.dll.log" - LDAPI log.

                         

                        Most everything should have SWAGGER documentation, so "https://localhost/distributionapi/swagger" (no authentication needed) should net you something like this (click on picture for full-size):

                        Don't forget to import the SWAGGER documentation into Postman - so for instance ...

                        1. Open Postman
                        2. Close the initial popup screen, if it comes up, by clicking “X” or typing “Esc”.
                        3. Click on the “Import” button in Postman. The button is to the right of the New button in the top menu bar.
                        4. Click on “Import from Link
                        5. Enter “https://MyCoreServerName:443/DistributionApi/swagger/docs/v1”. You can copy this URL from the text box on the swagger document page or type it in.

                         

                        <For some reason, Postman was stubborn about importing on my system from the link, so I ended up going to the (...)/swagger/docs/v1 link & copy & pasted the resulting text into Postman "Raw" ...>

                         

                        Try making an api call

                        1. Click on “Collections” in the left sidebar.
                        2. Click on “DistributionApi
                        3. Click on “api”, and you will see a list of api commands.
                        4. Click on “Gets a list of public packages and packages owned by the user.
                        5. Click on the blue “Send” button.

                          NOTE - You should see a 401 Unauthorized. We'll fix that issue in a moment because you must have a token for the api to authorize your api call.

                          NOTE - you MIGHT need to disable SSL verification on self-signed certs if you're not working with a "proper" cert. Do that here ...

                          ... then disable SSL verification here ...

                         

                        ================================

                        Side-line ... setting / identifying key security items

                         

                         

                        ================================

                         

                        Authenticating ... (getting our JWT token)

                        1. Click on the “Authorization” tab & select “OAuth 2.0” from the “Type” drop-down list
                        2. Click on the orange “Get New Access Token” button.

                         

                        <To be edited & continued later ... need to save this & do something else for a bit ...>

                        • 9. Re: Evaluation of different available APIs and Authentication issues
                          phoffmann SupportEmployee

                          So - quick troubleshooting checkpoints for both STS and Identityserver are as here -- both should just be thrown into a browser & should give you something back ...

                           

                          To check the health of the identity server.  I would call https://yourcoreserver/my.identityserver/identity/.well-known/openid-configuration. This output from this endpoint gives all the important endpoints of the identity server.

                           

                          For checking the STS endpoint, you might as well call https://localhost/sts/issuetoken and see if you can get a saml token.

                          • 10. Re: Evaluation of different available APIs and Authentication issues
                            jackhorner Rookie

                            continued thanks!

                             

                            here are my results:

                            -iis applicaiton list under default website looks identical

                            -both swagger ui for patch and distribution apis return fine with unauthenticated requests

                            -sts/issuetoken does indeed return a SAML response with my integrated ad account

                            -.well-known/openid-configuration returns a well formed json list

                            -as mentioned before legacy MBSDK calls are working perfectly

                            -identity server log shows this for context:

                             

                            INFO  2019-02-14 12:45:06,738 4206511ms CorsPolicyProvider     MoveNext           - CORS request made for path: /connect/token from origin: chrome-extension://aejoelaoggembcahagimdiliamlcdmfm
                            INFO  2019-02-14 12:45:06,753 4206526ms faultCorsPolicyService OriginAllowedAsync - AllowAll true, so origin: chrome-extension://aejoelaoggembcahagimdiliamlcdmfm is allowed
                            INFO  2019-02-14 12:45:06,753 4206526ms CorsPolicyProvider     Info               - CorsPolicyService allowed origin
                            INFO  2019-02-14 12:45:06,769 4206542ms okenEndpointController Info               - Start token request
                            DEBUG 2019-02-14 12:45:06,769 4206542ms ClientSecretValidator  Debug              - Start client validation
                            DEBUG 2019-02-14 12:45:06,785 4206557ms enticationSecretParser Debug              - Start parsing Basic Authentication secret
                            DEBUG 2019-02-14 12:45:06,785 4206557ms PostBodySecretParser   Debug              - Start parsing for secret in post body
                            DEBUG 2019-02-14 12:45:06,785 4206557ms SecretParser           MoveNext           - Parser found secret: PostBodySecretParser
                            INFO  2019-02-14 12:45:06,800 4206573ms SecretParser           MoveNext           - Secret id found: nrecaapiclient
                            DEBUG 2019-02-14 12:45:06,800 4206573ms SecretValidator        MoveNext           - Secret validator success: HashedSharedSecretValidator
                            INFO  2019-02-14 12:45:06,800 4206573ms ClientSecretValidator  Info               - Client validation success
                            INFO  2019-02-14 12:45:06,816 4206589ms TokenRequestValidator  Info               - Start token request validation
                            INFO  2019-02-14 12:45:06,816 4206589ms TokenRequestValidator  Info               - Start password token request validation
                            WARN  2019-02-14 12:45:06,847 4206620ms TokenRequestValidator  Warn               - User authentication failed: Unauthorized
                             {
                              "ClientId": "XXX",
                              "GrantType": "password",
                              "Scopes": "openid",
                              "UserName": "XXX",
                              "AuthenticationContextReferenceClasses": [],
                              "Raw": {
                                "grant_type": "password",
                                "client_id": "XXX",
                                "client_secret": "******",
                                "scope": "openid",
                                "username": "XXX",
                                "password": "******"
                              }
                            }
                            INFO  2019-02-14 12:45:06,863 4206636ms okenEndpointController Info               - End token request
                            INFO  2019-02-14 12:45:06,863 4206636ms TokenErrorResult       Info               - Returning error: invalid_grant
                            
                            
                            • 11. Re: Evaluation of different available APIs and Authentication issues
                              phoffmann SupportEmployee

                              OK so ... I'm *still* having authorisation issues in POSTMAN due to the self-signed cert (even though I went as far as trusting my own cert in the Windows CA).

                               

                              I got things to work in Powershell OK (requesting a JWT token -- creating a package via POSH) ... so I'll try to get together with a dev over the SDK and see where their & my setup differs (Unsurprisingly they use POSTMAN too ... and I'd expect them to have self-signed certs ...).

                               

                              In the meantime, hopefully this (VERY hacky code) example can help you with both requesting a JWT token programatically & using one of the methods (creating a package for instance).

                               

                              IMPORTANT NOTE -- I'm (knowingly) doing "bad" things here by having a plain text password in the script. This is *NOT* recommended for coding, this is just meant as a quick leg-up!

                              $body = @{
                                  'client_id' = 'roclient'
                                  'client_secret' = 'MySecret' # Replace with YOUR client secret
                                  'grant_type' = 'password'
                                  'scope' = 'openid'
                                  'username' = 'fantasia\AdminBob' # Replace with YOUR domain\username
                                  'password' = 'MyPassword' # Replace with YOUR domain users' password
                              }
                              
                              
                              $params = @{
                                  ContentType = 'application/x-www-form-urlencoded'
                                  Headers = @{'accept'='application/json'}
                                  Body = $body
                                  Method = 'Post'
                                  Uri = 'https://atreyu/my.identityserver/identity/connect/token' # Replace 'Atreyu' with your Core's name
                              }
                              
                              
                              $token = Invoke-RestMethod @params
                              # Output token to screen "to prove that we have it".
                              Write-host $token.access_token
                              
                              
                              ################
                              # Creating a package via the API
                              ################
                              
                              
                              $data = @{
                                  Type = 'GENERIC_EXE'
                                  Name = 'Powershell 7-zip'
                                  Description = '7-zip powershell package'
                                  PrimaryFile = 'http://Atreyu//ldlogon/Xx/7-zip/7z1801-x64.exe' # Obviously needs to be a path/file that actually exists on your Core
                                  CommandLine = '/S'
                              }
                              $body = $data | ConvertTo-json
                              $params = @{
                                  ContentType = 'application/json'
                                  Headers = @{'authorization' = 'Bearer ' + $token.access_token }
                                  Method = 'Post'
                                  Body = $body
                                  Uri = 'https://atreyu/distributionapi/api/v1/Package'
                              }
                              
                              
                              # call the create package api to actually create our package
                              $response = Invoke-RestMethod @params
                              
                              
                              # When done, you can check this exists in the EPM console.
                              

                               

                              That should help while I try & figure out what nonsense is going on with POSTMAN hopefully ... darn thing ...

                              • 12. Re: Evaluation of different available APIs and Authentication issues
                                phoffmann SupportEmployee

                                As an aside - the LDAPI collection does *NOT* have SWAGGER documentation. To get info on that, you'll probably need to go via support-channels (in case there's any NDA's or so that need to be signed) so we can get you the relevant "old style" doc documentation for the various methods & parameters in that.

                                 

                                The hope is that we can get time allocated to "catch up" on that & have the relevants devs do the SWAGGER thing, but will see ... subject to other peoples' decisions as usual .

                                • 13. Re: Evaluation of different available APIs and Authentication issues
                                  phoffmann SupportEmployee

                                  So - I've definitely got some problems with Postman -- across 2 Cores, I've got the same problem ... even had a dev look at the setup, and it's all good.

                                   

                                  My Powershell code works fine ... so I tried out Insomnia (at the dev's suggestion) -- https://insomnia.rest/download/ -- and (after disabling SSL checks for certs there), I was able to get a JWT token just fine.

                                   

                                  So you MIGHT have the same problem potentially -- mine manifested that when I requested a JWT token (and had the POSTMAN console open, via CTRL + ALT + C ) noticed that it complained about self-signed certs, even though I (a) had the relevant cert trusted by the root CA, and (b) had disabled SSL-checking on certs within POSTMAN itself ...

                                   

                                  So I'll be filing a defect (or checking about known issues / how to debug this further) with the POSTMAN people, since it's pretty clear that they've got issues at this point ... annoying, but there you go. So - if you have similar problems, try the code I've given above (fixing it for your relevant environment obviously), and/or try out Insomnia ... I'm not sure how good it is given that I've not used it in anger yet, but at least it seems to work, which is a bonus at present .

                                  • 14. Re: Evaluation of different available APIs and Authentication issues
                                    phoffmann SupportEmployee

                                    Just checking in on this, whether the POSH scripts helped you (and in my case - using INSOMNIA, since POSTMAN is having issues in some cases).