1

I have jobs in Jenkins that i cannot access unless i log in first using a my username and password.

For example if i try to access "localhost:xxx/job/some_job_1" i will get a 404 Error unless i log in first. And i say this because i have tried the following using WebRequest class:

string formParams = "j_username=bobbyLee&j_password=SecretPassword25&from=%2F&json=%7B%22j_username%22%3A+%bobbyLee%22%2C+%22j_password%22%3A+%22SecretPassword%25%22%2C+%22remember_me%22%3A+false%2C+%22from%22%3A+%22%2F%22%7D&Submit=log+in";
        // ***this is the exact string that is sent when i log in normally, obtained using Fiddler***

        string formUrl = "http://serverName:PortNum/j_acegi_security_check";
        // ***I have also tried http://serverName:PortNum/login***
        string cookieHeader;
        WebRequest req = WebRequest.Create(formUrl);
        req.ContentType = "application/x-www-form-urlencoded";
        req.Method = "POST";
        byte[] bytes = Encoding.ASCII.GetBytes(formParams);
        req.ContentLength = bytes.Length;
        using (Stream os = req.GetRequestStream())
        {
            os.Write(bytes, 0, bytes.Length);
        }
        WebResponse resp = req.GetResponse();
        cookieHeader = resp.Headers["Set-cookie"];

        string pageSource;
        string getUrl = "http://serverName:portNum/job/some_job/";
        WebRequest getRequest = WebRequest.Create(getUrl);
        getRequest.Headers.Add("Cookie", cookieHeader);
        WebResponse getResponse = getRequest.GetResponse();
        using (StreamReader sr = new StreamReader(getResponse.GetResponseStream()))
        {
            pageSource = sr.ReadToEnd();
        }

The response that i get back from the POST request is "HTML OK", and cookieHeader is not null. But when i then try to make a GET request to get what i want, i get a 404 error when attempting to access the job "http://serverName:portNum/job/some_job/", as if i didn't log in successfully.

So what is the correct way to log into Jenkins from c#, and get the HTML source code of the jobs that only appears after logging in?

Andrew Gray
  • 3,593
  • 3
  • 35
  • 62
  • have you read this here? https://wiki.jenkins.io/display/JENKINS/Remote+access+API it might exist a way through the api – FrankM Dec 07 '18 at 08:00
  • Oh yeah, there is a link to it on the bottom right of my server's interface. It didn't have, or at least i couldn't find, a solution for logging into Jenkins for .NET users. –  Dec 07 '18 at 08:06
  • https://stackoverflow.com/a/11164487/1037841 this might help too, there they are using ```HttpWebRequest``` for setting cookies Quote: ```webRequest.Headers.Add("Cookie", "...") will fail.``` with a comment to use: ```HttpWebRequest.Headers.Add("Cookie", "...")``` – FrankM Dec 07 '18 at 08:23

1 Answers1

1

The RESTAPI is your best friend here.

It is an incredibly rich source of information. I have written a system that will show an entire program of work on a page with full deployment traceability.

I am going to assume you have some security in place in your Jenkins instance which means requests need to be authenticated.

I use the following class for this:

using System;
using System.Net;
using System.Text;

namespace Core.REST
{
    public class HttpAdapter
    {
        private const string ApiToken = "3abcdefghijklmnopqrstuvwxyz12345";  // you will need to change this to the real value

        private const string UserName = "restapi";

        public string Get(string url)
        {
            try
            {
                const string credentials = UserName + ":" + ApiToken;
                var authorization = Convert.ToBase64String(Encoding.ASCII.GetBytes(credentials));
                using (var wc = new WebClient())
                {
                    wc.Headers[HttpRequestHeader.Authorization] = "Basic " + authorization;
                    var htmlResult = wc.DownloadString(string.Format(url));
                    return htmlResult;
                }
            }
            catch (WebException e)
            {
                Console.WriteLine("Could not retrieve REST API response");
                throw e;
            }
        }
    }
}

restapi is a dedicated user I created. I think I gave it admin access just so I didn't have to worry about it. I was admin but all the other developers and testers in the 3 crews had highly controlled and limited access to only what they needed and nothing more. It is also better practice to have a dedicated users for functions like this.

I constructed my c# classes to consume (deserialise) data from any page that supports the api/json suffix.

Andrew Gray
  • 3,593
  • 3
  • 35
  • 62
  • I added a method to compute the API token and implemented in my project, it worked, thank you! –  Feb 20 '19 at 01:15