Skip to content
Merged
12 changes: 12 additions & 0 deletions docs/features/configurationReload.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ $ curl -X POST -G -d @/path/to/secret/file "JENKINS_URL/reload-configuration-as-
permissions. Since Jenkins 2.96 CRUMB is not needed for API tokens.
- via [Jenkins CLI](https://www.jenkins.io/doc/book/managing/cli/): with the Jenkins CLI (either with SSH or JAR), the command `java -jar jenkins-cli.jar -s ${JENKINS_URL} reload-jcasc-configuration` triggers a configuration reload.
This Jenkins CLI command is only present when the plugin `configuration-as-code` is installed, and reported in the help message:

- via http POST to `JENKINS_URL/configuration-as-code/configure`
This endpoint allows you to send raw YAML directly in the HTTP POST body (useful for Git webhooks).
Because sending raw YAML containing secrets over unencrypted HTTP is dangerous, this endpoint is disabled by default.

To use this endpoint, you must:
1. Start Jenkins with the system property `-Dcasc.allow.http.post.config=true`.
Comment thread
somiljain2006 marked this conversation as resolved.
Outdated
2. Authenticate the request using the username and API token of a user with `Administer` permissions.

**Example Usage:**
```sh
$ curl -X POST -u admin:YOUR_API_TOKEN --data-binary @jenkins.yaml "JENKINS_URL/configuration-as-code/configure"
Comment thread
timja marked this conversation as resolved.
Outdated

```shell
$ java -jar jenkins-cli.jar -s ${JENKINS_URL} help
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public class ConfigurationAsCode extends ManagementLink {

public static final String CASC_JENKINS_CONFIG_PROPERTY = "casc.jenkins.config";
public static final String CASC_JENKINS_CONFIG_ENV = "CASC_JENKINS_CONFIG";
public static final String CASC_ALLOW_HTTP_POST_CONFIG = "casc.allow.http.post.config";
public static final String DEFAULT_JENKINS_YAML_PATH = "jenkins.yaml";
public static final String YAML_FILES_PATTERN = "glob:**.{yml,yaml,YAML,YML}";

Expand Down Expand Up @@ -985,4 +986,50 @@ public static String printThrowable(@NonNull Throwable t) {
.replaceAll("\t", " ");
return s.substring(0, s.lastIndexOf(")") + 1);
}

@RequirePOST
@Restricted(NoExternalUse.class)
@SuppressWarnings("unused")
public void doConfigure(StaplerRequest2 req, StaplerResponse2 res) throws Exception {

if (!Jenkins.get().hasPermission(Jenkins.ADMINISTER)) {
res.sendError(HttpServletResponse.SC_FORBIDDEN, "Requires ADMINISTER permission");
return;
}

boolean isAllowed = Boolean.parseBoolean(System.getProperty(CASC_ALLOW_HTTP_POST_CONFIG, "false"));
if (!isAllowed) {
res.sendError(
HttpServletResponse.SC_FORBIDDEN,
"Raw YAML POST configuration is disabled for security. Enable with -D" + CASC_ALLOW_HTTP_POST_CONFIG
+ "=true");
return;
}

if (req.getContentLength() <= 0) {
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
res.setContentType("application/json; charset=utf-8");
JSONArray errors = new JSONArray();
errors.add(new JSONObject().accumulate("line", -1).accumulate("message", "Request body cannot be empty."));
Comment thread
somiljain2006 marked this conversation as resolved.
Outdated
res.getWriter().print(errors);
return;
}

try {
configureWith(YamlSource.of(req));
res.setStatus(HttpServletResponse.SC_OK);
res.setContentType("text/plain; charset=utf-8");
res.getWriter().print("Configuration successfully applied.");

} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Failed to apply configuration from POST payload", e);
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
res.setContentType("application/json; charset=utf-8");

JSONArray errors = new JSONArray();
errors.add(new JSONObject().accumulate("line", -1).accumulate("message", e.getMessage()));

res.getWriter().print(errors);
}
}
}
Loading
Loading