【问题标题】:JENKINS REST API throws 403 forbiddenJENKINS REST API 抛出 403 禁止
【发布时间】:2019-11-05 06:20:04
【问题描述】:

问题陈述

我有 Jenkins Sever V:2.190.2 在云上运行。在 Jenkins Config Security 上选择了“登录用户可以做任何事情”的权限。 因此,这意味着具有有效用户名和密码的用户可以登录到 jenkin 服务器并执行授权的工作。基本上我需要创造工作 通过传递作业名称和 jobXml 在 Jenkins 服务器上。

尝试以下选项

到目前为止,我已经使用了 Github 上提供的“jenkinsci/java-client-api”api。这个 api 是 Jenkins 相关操作的非常好的 api,我跟着 READ.md 上给出的说明。我创建了 Jenkins Server 实例并尝试调用 getJenkinVersion() 和 getJobs() 方法,两者都运行良好 并按预期返回结果。 但是,当我要调用 createJob(jobName, jobXml) 时,此调用会从服务器返回 403 禁止错误。

通过深入研究该问题,我发现以下内容:- 1. 当我将 Jenkins 安全配置更改为“任何用户可以做任何事情”时,这个 createJob() 方法就可以工作,我就可以创建工作了。 但是,由于安全限制,不建议使用此选项。 2. 当我将 Jenkins 安全配置保持为“登录用户可以做任何事情”时,createJob() 方法不起作用并返回 403 禁止错误。 在这里,我还注意到,虽然我提供了正确的用户名和密码/令牌,用于登录,但从 UI 登录到 Jenkins 服务器以创建 用户文档中定义的Jenkins服务器实例,当它到达该方法时,它以“ANONYMOUS USER”身份登录到jenkin。我想这是 返回 403 错误的根本原因。

下面的代码 sn-p

**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 连接直接调用 Jenkins 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)

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

【问题讨论】:

    标签: java rest jenkins http-post jenkins-cli


    【解决方案1】:

    即使在启用 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>
    

    【讨论】:

    • 非常感谢您的回答。你有一些示例代码吗?我不太喜欢饼干等。
    • 我想在这里说明的另一点是我们没有启用 CSRF。所以,我认为,没有必要对请求进行破坏。如果您有任何可用的示例代码,请您发布示例代码。谢谢
    • 我尝试使用 API 仅使用 CURL 而不是 Java,就像您所做的那样。但是,如果我能找到使用相同的解决方案,我将尝试用 Java 发布示例代码。您是否在 Jenkins 配置中禁用了 CSRF?如果是,请尽量避免这样做,建议保持启用。
    • 是的,目前已禁用。但我会尝试启用它。但到目前为止,最大的问题是使用 Java 调用创建作业。这就是为什么我也发布了代码示例(根据您的建议,它是上述代码示例中使用 HttpUrlConnection 的选项 2。)
    • 我尝试使用 REST API GET 方法从我的 jenkins 服务器获取 Crumb,但这里也再次出现 403 错误。
    【解决方案2】:

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

    这是我使用的 CURL:

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

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

    提示?可能想使用 https 而不是 http。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-01
      • 1970-01-01
      • 2019-03-19
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多