janjoerke / vscode-jenkins-pipeline-linter-connector

MIT License
60 stars 21 forks source link

Examples of using Jenkins API Tokens #10

Closed hubez closed 5 years ago

hubez commented 5 years ago

I'm using Jenkins with Azure Active Directory authentication, and in this mode passing user/pass (in Azure) doesn't authenticate me. I'm thinking the ideal model would be using Jenkins API Tokens instead. Even better since the password is stored openly.

Does this plugin support the use of Jenkins API Tokens? I've tried the more common means seen when using cURL but they don't work.

Thanks

mike-pt commented 5 years ago

I was thinking the same, we use github auth, and I would like to pass the token

mike-pt commented 5 years ago

Actually shouldn't it just work with user:token?

Tried it and now get TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["Jenkins-Crumb"]

Is there a way to make this more verbose so I see the contents its trying to use?

janjoerke commented 5 years ago

Hi, the Jenkins server I used for testing is very insecure and did not support API tokens, so i did not test this, when i first made this plugin.

Today I had some spare time, so I run the latest Jenkins LTS version in a docker container and did my own tests.

I could successfully validate a Jenkinsfile with VS Code 1.32.3 and plugin 1.1.7 using API Token and crumb. I used the following settings.

{
    "jenkins.pipeline.linter.connector.url": "http://<jenkins server>:<port>/pipeline-model-converter/validate",
    "jenkins.pipeline.linter.connector.crumbUrl": "<jenkins server>:<port>/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)",
    "jenkins.pipeline.linter.connector.user": "<jenkins user name>",
    "jenkins.pipeline.linter.connector.pass": "<jenkins api token>",
}

The api token can be used via basic auth, so you only have to exchange your personal password with the api token.

janjoerke commented 5 years ago

Actually shouldn't it just work with user:token?

Tried it and now get TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["Jenkins-Crumb"]

Is there a way to make this more verbose so I see the contents its trying to use?

I would test the connection with Postman.

For the crumb request:

GET //crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb) HTTP/1.1
Host: <your server>:<port>
Authorization: Basic amFuOjExYm... (can be generated with postman)

For the validation:

POST /pipeline-model-converter/validate HTTP/1.1
Host: <your server>:<port>
Content-Type: application/x-www-form-urlencoded
Jenkins-Crumb: 38587961c1... (the crumb from the previous request)
Authorization: Basic amFuOjExYm... (can be generated with postman)
jenkinsfile=<the jenkinsfile in plain text>
mike-pt commented 5 years ago

So the problem with the crumb request is that if a token is used then it expects baisc auth, however this would need for the code to encode it (user:pass).

This works fine form curl or httpie as they do this conversion for us.

i.e.:

 curl -v --user  user:token "https://CI_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)"  will show the `Authorization` header:
`Basic base64encodedstring`

So I'm unsure how that worked for you if the extension code it self doesn't handle it

I actually did some local tests but I'm not that familiar with typeScript, maybe options.auth is actually already use basic auth, but if so why is it failing for me then if curl/httpie just work?

hubez commented 5 years ago

Hi, the Jenkins server I used for testing is very insecure and did not support API tokens, so i did not test this, when i first made this plugin.

Today I had some spare time, so I run the latest Jenkins LTS version in a docker container and did my own tests.

I could successfully validate a Jenkinsfile with VS Code 1.32.3 and plugin 1.1.7 using API Token and crumb. I used the following settings.

{
    "jenkins.pipeline.linter.connector.url": "http://<jenkins server>:<port>/pipeline-model-converter/validate",
    "jenkins.pipeline.linter.connector.crumbUrl": "<jenkins server>:<port>/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)",
    "jenkins.pipeline.linter.connector.user": "<jenkins user name>",
    "jenkins.pipeline.linter.connector.pass": "<jenkins api token>",
}

The api token can be used via basic auth, so you only have to exchange your personal password with the api token.

I got this working with the above, which involve:

  1. Changing the crumURL to match as above
  2. Password is the Jenkins API token
  3. User is the jenkins username (without :token, or :api appended)

I'm using:

Thank you @janjoerke !