JENKINS REST API 抛出 403 禁止

JENKINS REST API throws 403 forbidden

问题陈述 :

我在云端安装了 Jenkins 服务器 V:2.190.2 运行。在 Jenkins Config Security 上选择了权限 "Logged In User can do any thing"。 因此,这意味着拥有有效用户名和密码的用户可以登录到 jenkin 服务器并执行授权的工作。基本上我需要创造工作 在 Jenkin 服务器上通过传递作业名称和 jobXml。

尝试了以下选项

到目前为止,我已经使用了 "jenkinsci/java-client-api" api Github。这个api对于Jenkins相关的操作真的很好api我也跟着 READ.md 上给出的说明。我创建了 Jenkins Server 实例并尝试调用 getJenkinVersion() 和 getJobs() 方法,两者都运行良好 returns 结果符合预期。 但是,当我要调用 createJob(jobName, jobXml) 时,此调用来自服务器的 returns 403 forbidden 错误。

通过更深入地研究这个问题,我发现了以下内容:- 1. 当我将 Jenkin 安全配置更改为 "Any User can do any thing" 时,此 createJob() 方法起作用,我能够创建作业。 但是,由于安全限制,不推荐使用此选项。 2. 当我将 Jenkin 安全配置保持为 "Logged in user can do any thing" 时,createJob() 方法不起作用并且出现 returns 403 forbidden 错误。 在这里我还注意到,尽管我提供了正确的用户名和用于登录的 password/token,但从 UI 登录到 Jenkins 服务器以创建 用户文档中定义的 Jenkin 服务器实例,当它命中该方法时,它以 "ANONYMOUS USER" 身份登录到 jenkin。我认为这是 返回 403 错误的根本原因。

下面的代码片段

**Sample 1**:
        HttpClientBuilder builder = HttpClientBuilder.create();
        JenkinsHttpClient client = new JenkinsHttpClient(uri, builder, "XXX", "XXX");
        JenkinsServer jenkins = new JenkinsServer(client);
        String sourceXML = readFile("src/main/resources/config.xml");
        System.out.println(String.format("Installed Jenkins Version >> %s", jenkins.getVersion().getLiteralVersion()));//works and gives correct result
        jenkins.createJob("test-nov1", sourceXML);

**Sample 2**:
        HttpClientBuilder builder = HttpClientBuilder.create();
        JenkinsHttpClient client = new JenkinsHttpClient(uri, addAuthentication(builder, uri, userName, passwordOrToken));
        JenkinsServer jenkins = new JenkinsServer(client);
        String sourceXML = readFile("src/main/resources/config.xml");
        System.out.println(String.format("Installed Jenkins Version >> %s", jenkins.getVersion().getLiteralVersion()));
        jenkins.createJob(null,"test-nov1", sourceXML,true);

**Sample Exception**:
    Exception in thread "main" org.apache.http.client.HttpResponseException: status code: 403, reason phrase: Forbidden
    at com.offbytwo.jenkins.client.validator.HttpResponseValidator.validateResponse(HttpResponseValidator.java:11)
    at com.offbytwo.jenkins.client.JenkinsHttpClient.post_xml(JenkinsHttpClient.java:375)
    at com.offbytwo.jenkins.JenkinsServer.createJob(JenkinsServer.java:389)
    at com.offbytwo.jenkins.JenkinsServer.createJob(JenkinsServer.java:359)
    at com.xx.OffByTwoJenkins.main(OffByTwoJenkins.java:31)

选项 2: 我还尝试了其他选项,直接使用 HttpUrl 连接直接调用 Jenkin REST API。

**Sample Code** :
public int createJob(final String username, final String password, final String jenkinsUrl, final String jobName) {
        // http://JENKINSURL//createItem?name=JOBNAME
        String jobUrl = jenkinsUrl + "/createItem?name=" + jobName;

        int responseCode = 00;
        try {
            String basicAuth = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8));
            //String encoding = Base64.getEncoder().encodeToString((username+":"+password).getBytes("utf-8"));
            System.out.println(String.format("User Auth >> %s", basicAuth));
            String sourceXML = readFile("src/main/resources/config.xml");
            URL url = new URL(jobUrl);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            //connection.setReadTimeout(10000);
            //connection.setConnectTimeout(15000);
            connection.setRequestProperty("Authorization", "Basic " + basicAuth);
            connection.setRequestProperty("Content-Type", "application/xml");
            connection.setRequestProperty("Content-Language", "en-US");
            connection.setRequestMethod("POST");
            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setInstanceFollowRedirects(false);
            OutputStream os = connection.getOutputStream();
            os.write(sourceXML.getBytes());
            os.flush();
            responseCode = connection.getResponseCode();
            BufferedReader br = new BufferedReader(new InputStreamReader((connection.getInputStream())));
            String output;
            System.out.println("Output from Server .... \n");
            while ((output = br.readLine()) != null) {
                System.out.println(output);
            }
            connection.disconnect();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return responseCode;

    }

This also returns with same error 403 forbidden.

**Exception** :
Caused by: java.io.IOException: Server returned HTTP response code: 403 for URL: <<JenkinsURL>>
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at java.net.HttpURLConnection.getResponseCode(Unknown Source)
    at com.xx.JenkinsJobExecutor.createJob(JenkinsJobExecutor.java:109)

我真的不明白我需要在哪里进行调整才能创建作业。 谢谢

即使启用了 CSRF,以下解决方案也对我有效。

public class JenkinsJobCreate {
public static void main(String[] args) {

    System.out.println("JenkinsJobsTrigger has started ###############################");

    String ipAddress = "http://localhost:8080/";
    String jobName = "Hello-world";

    String username = "admin";
    String password = "admin";

    System.out.println("ipAddress: " + ipAddress);
    System.out.println("jobName: " + jobName);

    System.out.println("username: " + username);
    System.out.println("password: " + password);


    try (JenkinsServer jenkinsServer = new JenkinsServer(new URI(ipAddress), username, password)) {

        // our XML file for this example
        File xmlFile = new File("src/main/resources/config.xml");

        // Let's get XML file as String using BufferedReader
        // FileReader uses platform's default character encoding
        // if you need to specify a different encoding, use InputStreamReader
        Reader fileReader = new FileReader(xmlFile);
        BufferedReader bufReader = new BufferedReader(fileReader);

        StringBuilder sb = new StringBuilder();
        String line = bufReader.readLine();
        while( line != null){
            sb.append(line).append("\n");
            line = bufReader.readLine();
        }
        String jobXml = sb.toString();
        System.out.println("XML to String using BufferedReader : ");
        System.out.println(jobXml);

        bufReader.close();

        jenkinsServer.createJob(jobName, jobXml, true);

    } catch (Exception e) {
        System.out.println("Exception Occured!!!");
        e.printStackTrace();
    }

    System.out.println("JenkinsJobsTrigger has Finished ###############################");

}

}

config.xml

<?xml version='1.1' encoding='UTF-8'?>
<project>
  <description></description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <scm class="hudson.scm.NullSCM"/>
  <canRoam>true</canRoam>
  <disabled>false</disabled>
  <blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
  <blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
  <triggers/>
  <concurrentBuild>false</concurrentBuild>
  <builders>
    <hudson.tasks.Shell>
      <command>echo &quot;Jenkins Testing Hello World!&quot;</command>
    </hudson.tasks.Shell>
  </builders>
  <publishers/>
  <buildWrappers/>
</project>

我的诀窍是使用标准语法将用户名和密码简单地包含在 URL 中。

这是我用的 CURL:

curl -I http://user:gNouIkl2ca1t@54.226.181.123/job/RemoteTriggerExample/build?token=abc-123

因此,如果没有用户名和密码,它会给出 403。使用 URL 中的用户名和密码,它可以正常工作。

小费?可能想使用 https 而不是 http。