Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-62300

How we can send request through api/v2 for Ansible Tower version 3.6.4

    • 0.15.0

      Hi Team

      As we found that the ansible tower plugin has disabled api/v1, may i know how we can send request through api/v2 for Ansible Tower version 3.6.4

      We are using Jenkins version 2.184 and plugin version 0.8.5, thanks in advance. 

          [JENKINS-62300] How we can send request through api/v2 for Ansible Tower version 3.6.4

          John Westcott added a comment -

          The tower plugin has worked with api/v2 since at least 2018 and the new version of the plugin should work with a new version of Tower such as 3.6.4.
          I am noticing that you are reporting using version 0.8.5 while the latest version is 0.14.1.
          In 0.13.0 we did some work on the back end authentication. Please try upgrading to 0.14.1 and let me know if you are still having problems. If so, please send me whatever specific error message you are getting and what you are trying to have the plugin do.

          John Westcott added a comment - The tower plugin has worked with api/v2 since at least 2018 and the new version of the plugin should work with a new version of Tower such as 3.6.4. I am noticing that you are reporting using version 0.8.5 while the latest version is 0.14.1. In 0.13.0 we did some work on the back end authentication. Please try upgrading to 0.14.1 and let me know if you are still having problems. If so, please send me whatever specific error message you are getting and what you are trying to have the plugin do.

          angel liang added a comment -

          Thanks, we have upgraded to the latest version 0.14.1, in our Jenkins config, i can see it is using username/password for the connection information, but from the log, it is now requested OAuth Token connection, is there any config in Jenkins that we can make it to use such a OAuth Token connection for Ansible please.

          Jenkins config:

          following from the logs
          [Ansible-Tower] Starting to test connection with (https://**ansible-tower-dev**) and (ID) and (true) with debugging (true)

          [Ansible-Tower] Building GET request to https:// **ansible-tower-dev** /api/v2/ping/

          [Ansible-Tower] Forcing cert trust

          [Ansible-Tower] Request completed with (200)

          [Ansible-Tower] Ping page loaded

          [Ansible-Tower] Successfully got version 3.6.4

          [Ansible-Tower] Connecting to Tower version: 3.6.4

          [Ansible-Tower] Created a connector with **ansible-tower-dev**

          [Ansible-Tower] Testing authentication

          [Ansible-Tower] Building GET request to **ansible-tower-dev** /api/v2/jobs/

          [Ansible-Tower] Determining authorization headers

          [Ansible-Tower] Checking if Tower can: **ansible-tower-dev** /api/o/

          [Ansible-Tower] Forcing cert trust

          [Ansible-Tower] Can Tower request completed with (200)

          [Ansible-Tower] Tower supoorts /api/o/

          [Ansible-Tower] Getting an oAuth token for ID

          [Ansible-Tower] Forcing cert trust

          angel liang added a comment - Thanks, we have upgraded to the latest version 0.14.1, in our Jenkins config, i can see it is using username/password for the connection information, but from the log, it is now requested OAuth Token connection, is there any config in Jenkins that we can make it to use such a OAuth Token connection for Ansible please. Jenkins config: following from the logs [Ansible-Tower] Starting to test connection with ( https://** ansible-tower-dev ** ) and ( ID ) and (true) with debugging (true) [Ansible-Tower] Building GET request to https:// ** ansible-tower-dev ** /api/v2/ping/ [Ansible-Tower] Forcing cert trust [Ansible-Tower] Request completed with (200) [Ansible-Tower] Ping page loaded [Ansible-Tower] Successfully got version 3.6.4 [Ansible-Tower] Connecting to Tower version: 3.6.4 [Ansible-Tower] Created a connector with ** ansible-tower-dev ** [Ansible-Tower] Testing authentication [Ansible-Tower] Building GET request to ** ansible-tower-dev ** /api/v2/jobs/ [Ansible-Tower] Determining authorization headers [Ansible-Tower] Checking if Tower can: ** ansible-tower-dev ** /api/o/ [Ansible-Tower] Forcing cert trust [Ansible-Tower] Can Tower request completed with (200) [Ansible-Tower] Tower supoorts /api/o/ [Ansible-Tower] Getting an oAuth token for  ID [Ansible-Tower] Forcing cert trust

          John Westcott added a comment -

          It should work with a username/password (it will request an oauth token for that user). However, if you want to use an oauth token directly you can look at the tower plugin documentation https://plugins.jenkins.io/ansible-tower/ under the section: OAuth Authentication.

          John Westcott added a comment - It should work with a username/password (it will request an oauth token for that user). However, if you want to use an oauth token directly you can look at the tower plugin documentation  https://plugins.jenkins.io/ansible-tower/  under the section: OAuth Authentication.

          angel liang added a comment -

          Thanks John.

          Unlucky we found that it can't support username and password(we prefer this method too), in logs it only shows it supports Outh2, and also we checked in our Ansible tower, the authentication with Outh2 is disabled, may i know any luck that we can prove it from our Jenkins to see it is using username/password for the connection, say if any debug level log config can make the log shows it is now connecting by username/password directly, thanks again.

          angel liang added a comment - Thanks John. Unlucky we found that it can't support username and password(we prefer this method too), in logs it only shows it supports Outh2, and also we checked in our Ansible tower, the authentication with Outh2 is disabled, may i know any luck that we can prove it from our Jenkins to see it is using username/password for the connection, say if any debug level log config can make the log shows it is now connecting by username/password directly, thanks again.

          John Westcott added a comment -

          Basic auth can be an expensive process in Tower if you are using an external authenticator (such as LDAP). This is because your basic auth creds need to be checked with the source for every API call. Where as a token auth method is significantly faster because only Tower needs to validate that the token is valid within its own database.

          Because of this the plugin is specifically written to seek out one of the token authentication methods. It will first look for the endpoint /api/o. If found your installation support oauth2 and that will be used. If that does not exist but instead the endpoint /api/v2/authtoken exists then then the older authtoken mechanism will be used.  If neither of those work it will revert to basic auth for every request. 

          With either oauth or authtoken the plugin should work with either a direct token entered or via username/password. If you give the plugin a token it will craft a header with it directly. However, if you use username/password those credentials will be used to get an initial token of either type and then subsequent requests will utilize the generated token.

          With the verbosity turned on you should see messages in your jenkins.log like you have above. Those messages will tell you what the plugin is attempting to do. Unfortunately, your snippet above ended just short of where the plugin attempts to get the token. 

          ```

          [Ansible-Tower] Checking if Tower can: ansible-tower-dev /api/o/

          [Ansible-Tower] Forcing cert trust

          [Ansible-Tower] Can Tower request completed with (200)

          [Ansible-Tower] Tower supoorts /api/o/
          ```

          This section says that your Tower instance does support the /api/o endpoint so the plugin is going to use the given username/password to attempt to get a token. The next two lines:

          ```

          [Ansible-Tower] Getting an oAuth token for ID

          [Ansible-Tower] Forcing cert trust

          ```

          Are the plugin going to use the configured username/password combo to get a temporary oauth token to use.

           

          There is currently no way within the plugin to force basic auth through tower. If you could figure out how to make Jenkins not be able to hit either of the two endpoints mentioned above it would, in theory, revert to using basic auth for everything. But again, that method can be significantly slower compared to using the username/password to get a token and then using the token.

           

          Also, please do not get confused between an oauth authentication setting within Tower vs the oauth to the Tower API. They are two different things. You do not need to configure anything within Tower settings => Authentication for the oAuth connection to work. However, in settings => System there is an option for "Enable HTTP Basic Auth". If you are using username/password instead of a direct token you will likely need that enabled otherwise the initial call to get a token will be rejected.

          John Westcott added a comment - Basic auth can be an expensive process in Tower if you are using an external authenticator (such as LDAP). This is because your basic auth creds need to be checked with the source for every API call. Where as a token auth method is significantly faster because only Tower needs to validate that the token is valid within its own database. Because of this the plugin is specifically written to seek out one of the token authentication methods. It will first look for the endpoint /api/o. If found your installation support oauth2 and that will be used. If that does not exist but instead the endpoint /api/v2/authtoken exists then then the older authtoken mechanism will be used.  If neither of those work it will revert to basic auth for every request.  With either oauth or authtoken the plugin should work with either a direct token entered or via username/password. If you give the plugin a token it will craft a header with it directly. However, if you use username/password those credentials will be used to get an initial token of either type and then subsequent requests will utilize the generated token. With the verbosity turned on you should see messages in your jenkins.log like you have above. Those messages will tell you what the plugin is attempting to do. Unfortunately, your snippet above ended just short of where the plugin attempts to get the token.  ``` [Ansible-Tower]  Checking if Tower can:  ansible-tower-dev   /api/o/ [Ansible-Tower]  Forcing cert trust [Ansible-Tower]  Can Tower request completed with (200) [Ansible-Tower]  Tower supoorts /api/o/ ``` This section says that your Tower instance does support the /api/o endpoint so the plugin is going to use the given username/password to attempt to get a token. The next two lines: ``` [Ansible-Tower]  Getting an oAuth token for  ID [Ansible-Tower]  Forcing cert trust ``` Are the plugin going to use the configured username/password combo to get a temporary oauth token to use.   There is currently no way within the plugin to force basic auth through tower. If you could figure out how to make Jenkins not be able to hit either of the two endpoints mentioned above it would, in theory, revert to using basic auth for everything. But again, that method can be significantly slower compared to using the username/password to get a token and then using the token.   Also, please do not get confused between an oauth authentication setting within Tower vs the oauth to the Tower API. They are two different things. You do not need to configure anything within Tower settings => Authentication for the oAuth connection to work. However, in settings => System there is an option for "Enable HTTP Basic Auth". If you are using username/password instead of a direct token you will likely need that enabled otherwise the initial call to get a token will be rejected.

          johnwestcottiv I think the implementation of the mechanism you described has a bug. In file [TowerConnector.java|https://github.com/jenkinsci/ansible-tower-plugin/blob/master/src/main/java/org/jenkinsci/plugins/ansible_tower/util/TowerConnector.java] around line 200 there are check for specific endpoints but invocations of functions like getOAuthToken are not in a try-catch block. On exception there is no fallback to basic auth, Jenkins job just fails. The relevant code snippet: 

          if (this.towerSupports("/api/o/")) {                        
          logger.logMessage("Getting an oAuth token for "+ this.username);                        
          this.authorizationHeader = "Bearer " + this.getOAuthToken();
          }

          We use LDAP users to connect to AWX and we don't allow external (LDAP) users to create a token. I think the plugin should fallback to username/password on a failed attempt to obtain a token but it just fails a job run. Is it intentional or is it possible to fix this issue?

           

          On a side note, it would be great to have an option to force a specific connection method next to Trust Cert and Debugging options.

          Bartosz Drzazga added a comment - johnwestcottiv I think the implementation of the mechanism you described has a bug. In file [TowerConnector.java| https://github.com/jenkinsci/ansible-tower-plugin/blob/master/src/main/java/org/jenkinsci/plugins/ansible_tower/util/TowerConnector.java ] around line 200 there are check for specific endpoints but invocations of functions like getOAuthToken are not in a try-catch block. On exception there is no fallback to basic auth, Jenkins job just fails. The relevant code snippet:  if ( this .towerSupports( "/api/o/" )) { logger.logMessage( "Getting an oAuth token for " + this .username); this .authorizationHeader = "Bearer " + this .getOAuthToken(); } We use LDAP users to connect to AWX and we don't allow external (LDAP) users to create a token. I think the plugin should fallback to username/password on a failed attempt to obtain a token but it just fails a job run. Is it intentional or is it possible to fix this issue?   On a side note, it would be great to have an option to force a specific connection method next to Trust Cert and Debugging options.

          John Westcott added a comment -

          In your use case are you having users enter their credentials in Jenkins directly rather than using a service account to connect from Jenkins to Tower?

          John Westcott added a comment - In your use case are you having users enter their credentials in Jenkins directly rather than using a service account to connect from Jenkins to Tower?

          No, this is a service account which Jenkins uses to connect to AWX.

          Bartosz Drzazga added a comment - No, this is a service account which Jenkins uses to connect to AWX.

          John Westcott added a comment -

          But an LDAP based account instead of a local account on the Tower server?

          John Westcott added a comment - But an LDAP based account instead of a local account on the Tower server?

          John Westcott added a comment -

          After considering your scenario I decided that this was an acceptable pattern.
          If provided a username/password the login will now:
             Attempt to get an oauth toekn
             Attempt to get a legacy token
             Revert to basic auth

          Please test with version 0.15.0 and mark this ticket as done or let me know if you have issues.

          John Westcott added a comment - After considering your scenario I decided that this was an acceptable pattern. If provided a username/password the login will now:    Attempt to get an oauth toekn    Attempt to get a legacy token    Revert to basic auth Please test with version 0.15.0 and mark this ticket as done or let me know if you have issues.

            angelliang angel liang
            angelliang angel liang
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: